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