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