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