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