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