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