Почему программно созданный документ не сохраняется при ошибке записи основного объекта?

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

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

Механизм транзакций и откат изменений

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

Проанализируем ситуацию: если в коде обработчика ПередЗаписью вызывается метод Записать() для нового документа, данные физически передаются в СУБД, но транзакция еще не зафиксирована (не сделан COMMIT). Если после выполнения вашего кода платформа обнаруживает ошибку (например, попытку проведения документа, помеченного на удаление), она инициирует отмену транзакции (ROLLBACK). В результате все изменения, внесенные в базу данных с момента начала транзакции, аннулируются. Это касается и основного документа, и того, который вы создали программно.

Разбор практического примера

Рассмотрим ситуацию, которую описывает автор вопроса. В модуле объекта основного документа написан следующий код:


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

Функция СоздатьДокументДругогоВида()
    НовыйДок = Документы.ДокДругогоВида.СоздатьДокумент();
    НовыйДок.Дата = ТекущаяДата();
    // Заполнение других реквизитов...
    НовыйДок.Записать(РежимЗаписиДокумента.Запись);
    Возврат НовыйДок.Ссылка;
КонецФункции

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

Как обеспечить независимое сохранение документа?

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

  1. Использование фоновых заданий. Это наиболее надежный и современный метод для управляемого приложения. Вместо прямого создания документа в ПередЗаписью, вы запускаете фоновое задание. Фоновое задание выполняется в отдельном сеансе и в своей собственной транзакции. Откат транзакции в основном сеансе никак не повлияет на результат работы фонового задания.
  2. Проверка состояния объекта перед созданием. Чтобы не тратить ресурсы системы на операции, которые гарантированно будут отменены, добавьте явную проверку в код. Если ЭтотОбъект.ПометкаУдаления истинна, выполнение логики создания стороннего документа следует прервать.
  3. Использование дополнительных свойств. Если создание документа должно зависеть от успешности записи основного объекта, можно использовать структуру ДополнительныеСвойства. В обработчике ПередЗаписью вы подготавливаете данные и устанавливаете флаг в ДополнительныеСвойства, а фактическое создание документа переносите в обработчик ПриЗаписи (хотя это все равно будет в одной транзакции) или вызываете логику из формы после успешной записи.
  4. Внешнее соединение (COM) или HTTP-сервисы. В исключительных случаях можно вызвать метод создания документа через новое внешнее соединение к этой же базе. Это создаст новую транзакцию, но такой метод является ресурсоемким и сложным в отладке.

Важные архитектурные ограничения

Проанализируем еще несколько нюансов, о которых стоит помнить программисту 1С при работе с транзакциями:

Таким образом, если вы видите, что программно созданный объект не появился в списке, всегда проверяйте журнал регистрации на наличие ошибок проведения или записи основного объекта. Помните: любая ошибка в транзакции — это автоматический откат всех действий, выполненных внутри неё.

← На главную