Как создать другой документ при отказе в обработке проведения в 1С

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

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

Транзакционная модель 1С и причина проблемы

Проанализируем, как платформа 1С выполняет запись и проведение документов. Обработчик ОбработкаПроведения всегда выполняется внутри неявной транзакции базы данных. Если в коде устанавливается значение Отказ = Истина или возникает исключение, платформа инициирует автоматический откат (Rollback) транзакции.

Важно понимать:

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

Поэтому попытка вызвать НовыйДокумент.Записать() внутри процедуры ОбработкаПроведения при установке Отказ = Истина не приведет к созданию документа — его запись будет откатана вместе с проведением исходного документа.

Вариант 1. Запуск независимого фонового задания

Фоновое задание выполняется в отдельном сеансе на сервере со своим собственным независимым транзакционным пространством. Если перед установкой флага Отказ = Истина передать необходимые данные и запустить фоновое задание, откат транзакции в текущем сеансе никак не повлияет на работу фонового процесса.

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


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

Разберем код фоновой процедуры в общем серверном модуле:


Процедура СоздатьКорректировкуФоново(ДокументОснование, ТаблицаРасхождений) Экспорт
    
    ДокКорректировка = Документы.КорректировкаВнутреннегоЗаказа.СоздатьДокумент();
    ДокКорректировка.Дата = ТекущаяДатаСеанса();
    ДокКорректировка.ДокументОснование = ДокументОснование;
    ДокКорректировка.Товары.Загрузить(ТаблицаРасхождений);
    
    Попытка
        ДокКорректировка.Записать(РежимЗаписиДокумента.Запись);
    Исключение
        ЗаписьЖурналаРегистрации("СозданиеКорректировки", УровеньЖурналаРегистрации.Ошибка,,, 
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    
КонецПроцедуры

Вариант 2. Проверка и создание документа на клиенте (в форме)

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

Рассмотрим пример кода команды формы:


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

Обратите внимание: данный подход работает только при проведении из формы объекта. Если документ проводится групповой обработкой, регламентным заданием или через контекстное меню динамического списка, данный алгоритм не сработает.

Вариант 3. Архитектурная альтернатива (Проведение без блокировки)

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

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