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