Можно ли проводить один документ из модуля проведения другого документа в 1С?

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

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

Разбор исходного кода: в чем кроется подвох?

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


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

На первый взгляд, логика прозрачна: если у нас есть связанный документ (РКО), который еще не проведен, мы пытаемся провести его «на лету» в транзакции текущего документа. Если возникает ошибка, мы устанавливаем Отказ = Истина, чтобы откатить проведение основного документа. Однако в этой конструкции заложено сразу несколько «мин замедленного действия».

Проблема 1: Принципы ACID и целостность транзакции

Вспомним фундаментальные требования к транзакционным системам — ACID (Atomicity, Consistency, Isolation, Durability). Проведение документа в 1С — это всегда одна атомарная транзакция. Когда мы внутри этой транзакции инициируем проведение другого документа, мы создаем вложенную логику, которая значительно усложняет работу СУБД.

Разберем, как это влияет на систему:

  1. Атомарность (Atomicity): Если второй документ не сможет проведется, вся цепочка должна откатиться. Но если разработчик забудет про Попытка...Исключение или неправильно обработает результат, система может оказаться в противоречивом состоянии.
  2. Изоляция (Isolation): Пока длится транзакция первого документа, он удерживает блокировки на свои таблицы и регистры. Вложенное проведение захватывает блокировки на таблицы второго документа. Это идеальная среда для возникновения взаимоблокировок (Deadlocks).

Проблема 2: «Обреченная» транзакция (Transaction Doom)

Использование блока Попытка...Исключение внутри ОбработкаПроведения для вызова записи другого объекта — это архитектурная ошибка. Выясним причину: если при записи РКООбъект произойдет ошибка на уровне СУБД (например, конфликт блокировок или нарушение уникальности индекса), транзакция всей сессии помечается платформой как «испорченная» (doomed).

Даже если вы перехватили ошибку в блоке Исключение и установили Отказ = Истина, транзакция уже не может быть зафиксирована. Более того, любая последующая попытка обращения к базе данных в рамках этой же транзакции вызовет системную ошибку: «В данной транзакции уже происходили ошибки!». Таким образом, Попытка не спасает от аварийного завершения процесса, а лишь маскирует первоначальную причину сбоя.

Проблема 3: Взаимоблокировки (Deadlocks)

Посмотрим на ситуацию со стороны СУБД. Представим двух пользователей:

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

Как сделать правильно: альтернативные подходы

Если бизнес-логика требует, чтобы проведение одного документа влияло на другой, следует использовать более безопасные механизмы. Рассмотрим их подробнее.

1. Использование последовательностей

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

2. Асинхронная обработка (Фоновые задания)

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

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

3. Подписки на события

Иногда логику выносят в Подписки на события (событие ОбработкаПроведения). Это позволяет соблюсти принцип слабой связанности (лоу-каплинг), о котором упоминали коллеги в обсуждении. Однако стоит помнить: подписка выполняется в той же транзакции, что и сам документ. Если вы в подписке на Документ А вызываете проведение Документа Б, вы получаете все те же риски блокировок, что и при прямом вызове в модуле объекта.

4. Использование дополнительных регистров

Вместо того чтобы заставлять Документ А проводить Документ Б, можно сделать так, чтобы оба документа делали движения по одному и тому же регистру. Таким образом, состояние системы будет определяться совокупностью движений, а не «проведенностью» какого-то конкретного связанного объекта.

Выводы

Подводя итог, проанализируем аргумент: «Если это работает и дает правильный результат клиенту — значит, так можно». В краткосрочной перспективе на базе с одним пользователем это может работать. Но как только нагрузка вырастет, такой код станет причиной невоспроизводимых ошибок, порчи данных и недовольства пользователей из-за постоянных блокировок.

Основные рекомендации:

Соблюдение этих правил обеспечит стабильную работу системы и избавит вас от необходимости «разгребать» последствия заблокированных таблиц в разгар рабочего дня.

← На главную