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