Почему не сохраняется значение реквизита при изменении в процедуре ОбработкаПроведения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8.3 часто встречается ситуация, когда программисту необходимо изменить значение какого-либо реквизита документа именно в момент его проведения. Например, снять флаг «Новый» или проставить отметку о том, что документ прошел определенную проверку. Однако, выполнив присвоение значения в процедуре ОбработкаПроведения, разработчик обнаруживает, что после завершения операции в базе данных остается старое значение. Давайте подробно разберем, почему так происходит и как правильно реализовать эту задачу.

Анализируем причину проблемы: физика процесса записи

Для того чтобы понять, почему изменения «теряются», нам необходимо рассмотреть последовательность событий, которые генерирует платформа при нажатии кнопки «Провести» в форме документа или при программном вызове метода Записать(РежимЗаписиДокумента.Проведение). Проанализируем стандартный цикл транзакции записи:

  1. ПередЗаписью (модуль объекта): Транзакция уже открыта. Здесь мы еще можем внести изменения в реквизиты, и они будут учтены.
  2. ПриЗаписи (модуль объекта): В этот момент платформа берет текущее состояние объекта из оперативной памяти и записывает его в таблицу базы данных. Это критическая точка: данные документа физически зафиксированы в БД.
  3. ОбработкаПроведения (модуль объекта): Эта процедура предназначена исключительно для создания движений по регистрам. Да, мы находимся внутри той же транзакции, но запись основной таблицы документа уже завершена.

Когда мы пишем ЭтотОбъект.ИмяРеквизита = Ложь; внутри ОбработкаПроведения, мы меняем значение только в экземпляре объекта, который находится в оперативной памяти сервера. Платформа не будет повторно записывать данные самого документа в таблицу БД после выхода из ОбработкаПроведения, так как она «считает», что запись документа уже успешно выполнена на шаге №2. После завершения транзакции объект в памяти уничтожается, а в базе остаются те данные, которые были актуальны на момент срабатывания события ПриЗаписи.

Решение №1: Использование события ПередЗаписью

Рассмотрим самый правильный и эффективный способ решения задачи. Если нам нужно изменить реквизит именно при проведении, мы должны сделать это в процедуре ПередЗаписью модуля объекта. Чтобы отличить обычную запись от проведения, мы проанализируем параметр РежимЗаписи.

Разберем пример кода, который нужно разместить в модуле документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Проверяем, что документ именно проводится, а не просто записывается
    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        
        // Устанавливаем нужное значение реквизита. 
        // Оно будет сохранено в БД автоматически на следующем шаге транзакции.
        НужнаяГалка = Ложь;
        
    КонецЕсли;

КонецПроцедуры

В этом случае платформа сначала выполнит наш код, изменит значение реквизита в памяти, а затем, в событии ПриЗаписи, зафиксирует в базе данных уже обновленное состояние. Это наиболее «чистый» метод, не создающий лишних нагрузок на СУБД.

Решение №2: Использование ДополнительныхСвойств

Иногда решение о том, нужно ли менять реквизит, принимается на основе данных, полученных в ходе формирования проводок в ОбработкаПроведения (например, если сумма по регистрам превысила лимит). В этом случае нам сложнее, так как ПередЗаписью срабатывает раньше.

Проанализируем стратегию использования коллекции ДополнительныеСвойства. Мы можем передать информацию из модуля формы или из начала транзакции в процедуру проведения, чтобы логика отработала корректно. Однако помните: изменять реквизиты документа внутри ОбработкиПроведения — плохая практика. Если вам крайне необходимо обновить документ после формирования движений, лучше использовать механизм задач или фоновых заданий, либо пересмотреть архитектуру в пользу регистров сведений.

Типичные ошибки, которых следует избегать

Разберем несколько опасных подходов, которые часто пытаются применить начинающие разработчики:

Как убедиться, что решение работает?

Проанализируем ситуацию с точки зрения отладки. Чтобы убедиться, что реквизит теперь сохраняется правильно, выполните следующие шаги:

  1. Перенесите код изменения реквизита в ПередЗаписью.
  2. Поставьте точку останова в ОбработкаПроведения.
  3. Запустите проведение документа.
  4. В табло отладчика проверьте значение реквизита — оно уже должно быть изменено.
  5. После завершения процедуры проверьте значение через «Консоль запросов» или в списке документов. Теперь оно будет соответствовать ожидаемому.

Важный нюанс: Если документ уже был проведен ранее и вы его перепроводите, условие РежимЗаписи = РежимЗаписиДокумента.Проведение все равно сработает. Это гарантирует актуальность вашего флага при любых манипуляциях с документом, связанных с его проведением.

Таким образом, понимание жизненного цикла объекта в транзакции позволяет избежать досадных ошибок и писать код, который работает предсказуемо и эффективно.

← На главную