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

Программист 1С v8.3 (Управляемые формы) 1C:Бухгалтерия Бухгалтерский учет Торговля и дистрибуция
← На главную

В процессе разработки часто возникают задачи, требующие вывода итоговой суммы документа непосредственно в его реквизиты. Однако при попытке присвоить значение сумме в модуле объекта в процедуре ОбработкаПроведения, многие разработчики сталкиваются с тем, что данные не сохраняются или ведут себя непредсказуемо. Давайте разберем, почему это происходит и как решить данную задачу правильно.

Разбор проблемы: почему код не работает?

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

Эффект «неожиданного сохранения» при двойном нажатии кнопки «Провести» объясняется тем, что после первого проведения форма документа в управляемом интерфейсе получает измененные данные объекта из памяти. Система видит расхождение данных и помечает форму как модифицированную. При повторном нажатии «Провести» платформа берет уже измененные данные из формы и записывает их в базу, что создает иллюзию работоспособности кода.

Почему не стоит использовать программную запись внутри проведения

Некоторые разработчики пытаются исправить ситуацию, вызывая Объект.Записать() внутри обработки проведения. Это категорически не рекомендуется по следующим причинам:

  1. Вызов записи внутри проведения инициирует рекурсивный цикл всех обработчиков записи, что крайне негативно сказывается на производительности.
  2. Риск нарушения транзакционной целостности: если в процессе «вложенной» записи произойдет ошибка, вся транзакция проведения будет откачена, что приведет к трудноуловимым ошибкам системы.
  3. Блокировки: повторная запись захватывает дополнительные ресурсы базы данных, снижая параллельность работы пользователей.

Правильные способы решения задачи

Рассмотрим архитектурно верные подходы для реализации расчета и вывода суммы документа:

1. Расчет в процедуре «ПередЗаписью»

Если для расчета суммы достаточно данных, имеющихся в табличных частях документа, выполняйте расчет в событии ПередЗаписью. В этом случае платформа корректно сохранит измененный реквизит в базу данных в рамках текущей транзакции записи.


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        ЭтотОбъект.СуммаДокумента = Товары.Итог("Сумма");
    КонецЕсли;
КонецПроцедуры

2. Использование регистра сведений (Рекомендуемый метод)

Если сумма документа зависит от результатов проведения (например, от списания себестоимости по ФИФО), правильным решением будет вынос суммы в отдельный непериодический регистр сведений.

  1. Создайте регистр сведений, где измерением является Ссылка на ваш документ, а ресурсом — Сумма.
  2. В ОбработкеПроведения создайте набор записей для этого регистра и заполните его рассчитанными данными.
  3. Для отображения суммы в списке документов настройте Динамический список в форме, добавив в него ЛЕВОЕ СОЕДИНЕНИЕ с созданным регистром сведений.

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

← На главную