Как провести зависимый документ, не прерывая транзакцию основного документа

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

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

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

Почему обычная Попытка-Исключение может подвести

Многие начинающие разработчики пытаются решить задачу «в лоб», вызывая проведение второго документа внутри транзакции первого в блоке Попытка. Однако стоит помнить: если ошибка при проведении второго документа произошла на уровне базы данных (например, нарушение уникальности или конфликт блокировок), вся транзакция помечается как «битая». Даже если вы перехватили ошибку в 1С-коде, при попытке завершить процедуру ОбработкаПроведения платформа выдаст фатальную ошибку: «Транзакция уже испорчена и не может быть зафиксирована».

Поэтому для надежной работы нам нужно разнести процессы проведения двух документов во времени или в разные программные контексты.

Решение 1: Использование регистра очереди и регламентного задания

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

Алгоритм реализации:

  1. Создадим РегистрСведений (например, «ОчередьПроведенияДокументов»), где основным измерением будет Ссылка на первый документ.
  2. В процедуре ОбработкаПроведения первого документа будем записывать в этот регистр признак того, что для данного объекта нужно сформировать второй документ.
  3. Настроим регламентное задание, которое с определенной периодичностью (например, раз в минуту) считывает записи из этого регистра.
  4. Регламентное задание в цикле пытается создать и провести второй документ. Если попытка удачна — запись из очереди удаляется. Если нет — документ просто записывается, а в регистре помечается ошибка для последующего анализа администратором.

Рассмотрим пример кода для записи в очередь:


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

Этот подход гарантирует, что основной документ всегда будет проведен, а зависимый «подтянется» следом, как только это станет возможным.

Решение 2: Запуск фонового задания

Разберем ситуацию, когда проведение второго документа должно произойти максимально быстро после первого. В платформе 1С есть интересная особенность работы метода ФоновыеЗадания.Выполнить(). Если вызвать его внутри транзакции, само фоновое задание фактически стартует только после успешной фиксации (COMMIT) основной транзакции.

Преимущества этого метода:

Пример инициализации фонового задания:


ПараметрыПроцедуры = Новый Массив;
ПараметрыПроцедуры.Добавить(ЭтотОбъект.Ссылка);

ФоновыеЗадания.Выполнить("МойОбщийМодуль.СформироватьСвязанныйДокумент", 
                         ПараметрыПроцедуры, 
                         Новый УникальныйИдентификатор(), 
                         "Проведение зависимого документа");

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

Решение 3: Механизмы БСП (Библиотека стандартных подсистем)

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

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

Решение 4: Предварительная проверка возможности проведения

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

Выясним причину возможного отказа заранее:

  1. В модуле объекта создаем функцию ПроверитьВозможностьПроведенияСвязанногоДокумента().
  2. Вызываем её в самом начале процедуры ОбработкаПроведения первого документа или даже в обработчике ПередЗаписью.
  3. Если проверка показывает, что второй документ точно не проведется, мы можем либо выдать предупреждение пользователю, либо сразу установить флаг «Записывать второй документ только как объект», не пытаясь его провести.

Архитектурные риски блокировок

Важно помнить, что проведение второго документа «встык» к первому (особенно в одной транзакции) резко увеличивает время удержания блокировок. Если оба документа делают движения по одним и тем же регистрам накопления (например, «Запасы»), это может привести к Deadlocks (взаимным блокировкам) при одновременной работе нескольких пользователей.

Вывод: Вынос формирования зависимых документов в фоновые процессы или регламентные задания — это не только способ обойти ограничения транзакций, но и стандарт проектирования высокопроизводительных (Highload) систем на базе 1С.

Рассмотренные нами методы позволяют сделать систему отказоустойчивой. Мы рекомендуем использовать Решение 1 (Регистр очереди) для гарантированного выполнения задач в фоновом режиме и Решение 2 (Фоновые задания) для оперативного реагирования системы.

← На главную