Разработчики, сопровождающие и развивающие конфигурации на обычных формах (такие как 1С:Управление производственным предприятием 1.3 или 1С:Управление торговлей 10.3), регулярно сталкиваются со сложной задачей. Необходимо внедрить определенную логику (например, проверку данных, вывод предупреждения или динамическое изменение реквизитов) при открытии стандартной формы документа или справочника. При этом крайне важно сохранить конфигурацию на поддержке («на замке»), чтобы не усложнять последующие обновления платформы и прикладного решения.
В этой статье мы подробно разберем, почему стандартные механизмы платформы не позволяют решить эту задачу «в лоб», проанализируем популярные варианты обхода ограничений и рассмотрим наиболее изящный, современный и безопасный способ реализации этой логики с помощью механизма расширений.
---
Прежде чем перейти к решениям, давайте проанализируем технические ограничения платформы 1С:Предприятие в контексте обычных форм:
ПередЗаписью, ПриЗаписи, ОбработкаПроведения). Однако подписок на события отображения интерфейса (таких как ПриОткрытии или ПередОткрытием формы) не существует в принципе.&Перед, &После или &Вместо.---
Рассмотрим вариант решения, предложенный участниками обсуждения. Он заключается в создании дубликата стандартной формы.
Алгоритм действий разработчика:
СчетНаОплатуПокупателю) снимается с поддержки с сохранением правил обновления.ФормаДокументаКопия).ПриОткрытии прописывается вся необходимая логика проверки сопряженных документов (например, поиск корректировок заказа покупателя).Почему мы не рекомендуем этот метод:
Несмотря на кажущуюся простоту, этот подход является классическим «костылем» и несет в себе скрытые риски:
---
Давайте разберем действительно красивое и чистое решение, которое позволяет решить задачу автора темы, оставив конфигурацию полностью на стандартной поддержке.
Суть метода:
В типовых конфигурациях на обычных формах разработчики «1С» заложили сквозные вызовы общих модулей при инициализации интерфейса документов. Например, практически при открытии любого документа в УПП вызывается процедура настройки меню, панелей или подсказок из общего модуля РаботаСДиалогами (это могут быть процедуры УстановитьПодменюСоветы, УстановитьДоступностьПолейВводаНомера и др.).
При вызове этих процедур в качестве параметра передается элемент формы — чаще всего командная панель (ДействияФормы). У любого элемента обычной формы, включая командную панель, есть свойство ИсточникДействия, которое содержит прямую ссылку на саму Форму! Перехватив этот вызов в расширении общего модуля, мы получаем полный доступ к форме документа и ее свойствам.
Рассмотрим по шагам, как это реализовать программно:
Шаг 1. Создание расширения конфигурации
Создайте новое расширение в вашей информационной базе. Убедитесь, что в свойствах расширения снят флаг «Безопасный режим» (так как нам потребуется выполнять запросы к базе данных) и назначено назначение «Адаптация».
Шаг 2. Заимствование общего модуля
Найдите в основной конфигурации общий модуль, который гарантированно вызывается при инициализации форм документов. В УПП 1.3 идеально подходит модуль РаботаСДиалогами и его процедура УстановитьПодменюСоветы. Добавьте этот модуль в ваше расширение.
Шаг 3. Реализация перехвата события
В модуле расширения напишите код с использованием аннотации &После. Мы перехватим управление, получим форму через источник действия командной панели, определим тип документа и выполним необходимую нам логику.
Посмотрим на пример реализации такого кода:
&После("УстановитьПодменюСоветы")
Процедура Расш_УстановитьПодменюСоветы(КоманднаяПанель, ПараметрОтбора = "ВсеСоветы")
// Безопасно получаем саму форму через источник действия командной панели
ТекущаяФорма = Неопределено;
Попытка
ТекущаяФорма = КоманднаяПанель.ИсточникДействия;
Исключение
// Если источник действия не является формой, прерываем выполнение
Возврат;
КонецПопытки;
Если ТекущаяФорма = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем, что перед нами форма именно нужного документа
// (например, СчетНаОплатуПокупателю)
ИмяНастройкиВысотыШирины = "";
Попытка
ИмяНастройкиВысотыШирины = ТекущаяФорма.ИмяНастройкиВысотыШирины;
Исключение
Возврат;
КонецПопытки;
Если Найти(ИмяНастройкиВысотыШирины, "СчетНаОплатуПокупателю") > 0 Тогда
// Получаем ссылку на текущий документ из реквизита формы
ДокументСсылка = Неопределено;
Попытка
ДокументСсылка = ТекущаяФорма.ДокументОбъект.Ссылка;
Исключение
Возврат;
КонецПопытки;
// Проверяем, что документ записан в базу (не новый)
Если ЗначениеЗаполнено(ДокументСсылка) Тогда
// Выполняем проверку наличия корректировок заказа по данному счету
Если ЕстьКорректировкиПоСчету(ДокументСсылка) Тогда
// Выводим предупреждение пользователю
ТекстПредупреждения = "Внимание! По данному счету обнаружен проведенный документ ""Корректировка заказа покупателя""."
+ Символы.ПС + "Данные на экране могут отличаться от актуального состояния расчетов!";
ПоказатьПредупреждение(, ТекстПредупреждения, 10, "Обратите внимание");
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЕстьКорректировкиПоСчету(СчетСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Корректировка.Ссылка КАК Ссылка
|ИЗ
| Документ.КорректировкаЗаказаПокупателя КАК Корректировка
|ГДЕ
| Корректировка.Проведен = ИСТИНА
| И Корректировка.ЗаказПокупателя = &ЗаказПокупателя";
// В УПП Счет обычно создается на основании Заказа, либо сам выполняет его роль.
// Предположим, что мы ищем корректировки по связанному заказу, хранящемуся в реквизите счета:
ЗаказПокупателя = СчетСсылка.Сделка;
Если Не ЗначениеЗаполнено(ЗаказПокупателя) Тогда
Возврат Ложь;
КонецЕсли;
Запрос.УстановитьПараметр("ЗаказПокупателя", ЗаказПокупателя);
РезультатЗапроса = Запрос.Выполнить();
Возврат Не РезультатЗапроса.Пустой();
КонецФункции
Преимущества метода «псевдоподписки» через расширение:
---
Рассмотрим ситуацию, когда логика проверки должна отрабатывать строго в определенный момент времени, например, строго в конце события ПриОткрытии, а стандартные процедуры общих модулей вызываются в событии ПередОткрытием.
В обычных формах 1С доступен мощный инструмент динамического назначения действий — метод УстановитьДействие(ИмяСобытия, Действие).
Как это применить:
ТекущаяФорма.ПриОткрытии следующим образом:
НовоеДействие = Новый Действие("ИмяПроцедурыВМодулеФормы");
ТекущаяФорма.УстановитьДействие("ПриОткрытии", НовоеДействие);
Важное ограничение метода:
Процедура, имя которой передается в объект Действие, физически должна находиться внутри модуля самой формы, которую мы перехватываем. Назначить обработчиком процедуру из общего модуля напрямую невозможно.
По этой причине для нашей задачи оптимальным выбором остается Вариант 2: проведение проверки и вывод уведомления сразу в момент перехвата в процедуре общего модуля, не привязываясь к событию ПриОткрытии. На момент вызова общего модуля форма уже полностью инициализирована, данные прочитаны из базы данных, и показ диалогового окна предупреждения отработает абсолютно корректно и безопасно для пользователя.
---
Мы проанализировали несколько подходов к решению задачи выполнения кода при открытии обычных форм без изменения типовой конфигурации.
Создание копии формы и переназначение ее основной — рабочий, но устаревший и небезопасный с точки зрения дальнейшей поддержки метод. Современным стандартом разработки в экосистеме «1С:Предприятие» является использование расширений общего модуля в сочетании со свойством элемента формы ИсточникДействия. Это позволяет создавать гибкие «псевдоподписки» на события интерфейса без изменения кода стандартных объектов.