При разработке обработок подбора или пакетного оформления документов разработчики часто сталкиваются с задачей: на форме обработки пользователь выставляет определенный флаг (булево значение), и в зависимости от этого флага документ при проведении должен сформировать специфические движения. Попытка вызвать метод ПолучитьФорму прямо внутри модуля объекта документа приводит к ошибке контекста. Разберем, почему возникает эта ошибка и какие архитектурно правильные способы существуют для передачи данных.
Проанализируем структуру выполнения кода платформы 1С:Предприятие. Модуль объекта документа (включая обработчики ПередЗаписью, ПриЗаписи и ОбработкаПроведения) исполняется строго на стороне сервера в рамках транзакции записи базы данных.
В этой модели действуют жесткие платформенные ограничения:
ПолучитьФорму или ОткрытьФорму) не существуют на сервере. Попытка вызвать их из модуля объекта вызывает исключение недоступности контекста.ПолучитьФорму, даже если бы он вызывался на клиенте, создает совершенно новый экземпляр формы с реквизитами по умолчанию, а не обращается к уже открытому экрану с галочкой пользователя.Рассмотрим наиболее популярный способ передачи разовых параметров из обработки в модуль объекта без изменения структуры метаданных конфигурации. Коллекция ДополнительныеСвойства объекта ДокументОбъект представляет собой структуру, существующую в оперативной памяти сервера на время проведения и записи.
Разберем реализацию по шагам:
&НаСервере
Процедура ПровестиДокументИзОбработки(СсылкаНаДокумент, ЗначениеФлага)
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Передаем значение нашего флага в объект документа
ДокОбъект.ДополнительныеСвойства.Вставить("ФлагИзОбработки", ЗначениеФлага);
// Выполняем проведение
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
ОбработкаПроведения считываем переданный параметр:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Проверяем наличие переданного свойства
ФлагУстановлен = Ложь;
Если ДополнительныеСвойства.Свойство("ФлагИзОбработки") Тогда
ФлагУстановлен = ДополнительныеСвойства.ФлагИзОбработки;
КонецЕсли;
Если ФлагУстановлен Тогда
// Выполняем специфическую логику проведения
Иначе
// Стандартный алгоритм проведения
КонецЕсли;
КонецПроцедуры
Обратите внимание: Свойство живет только в момент вызова метода Записать(). Если документ позже будет перепроводиться пользователем вручную из формы документа или через групповое перепроведение, свойства ФлагИзОбработки в структуре уже не будет.
Если поведение документа при повторном проведении должно строго сохраняться независимо от того, как и когда документ перепроводится, правильным решением является добавление постоянного реквизита в метаданные документа.
Рассмотрим порядок действий:
Булево (например, ОсобыйРежимПроведения).
&НаСервере
Процедура ЗаполнитьИПровести(СсылкаНаДокумент, ЗначениеФлага)
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.ОсобыйРежимПроведения = ЗначениеФлага;
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
ОбработкаПроведения напрямую обращаемся к реквизиту ЭтотОбъект.ОсобыйРежимПроведения. Значение сохранится в базе данных навсегда и гарантирует целостность учета при любых последующих операциях.Если конфигурация находится на типовой поддержке без возможности редактирования реквизитов документа, можно создать независимый непериодический регистр сведений (например, ДополнительныеНастройкиДокументов).
Документ (тип ДокументСсылка) и ресурсом ФлагОбработки (тип Булево).
&НаСервере
Процедура ЗаписатьВРегистрИПровести(СсылкаНаДокумент, ЗначениеФлага)
МенеджерЗаписи = РегистрыСведений.ДополнительныеНастройкиДокументов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Документ = СсылкаНаДокумент;
МенеджерЗаписи.ФлагОбработки = ЗначениеФлага;
МенеджерЗаписи.Записать(Истина);
ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
СоздатьКлючЗаписи. Это позволяет сохранить историю настройки без снятия документа с поддержки.