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

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

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

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

Способ 1. Гарантированная предварительная запись с последующей попыткой проведения

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

Посмотрим на пример реализации данного алгоритма:


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

// 1. Сначала гарантированно сохраняем документ в базе
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);

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

Проанализируем преимущества этого способа:

  1. Гарантия сохранения данных: документ получает постоянную ссылку и сохраняется в базе данных независимо от того, возникнут ли проблемы при расчете движений.
  2. Безопасность транзакций: транзакция проведения изолирована от первичной транзакции записи объекта.

Способ 2. Попытка проведения с сохранением черновика в блоке Исключение

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

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

Разберем пример такого кода:


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

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

Важные рекомендации при программном проведении

Рассмотрим нюансы, которые следует учесть при написании обработок импорта и загрузки данных:

  1. Указание режима проведения: всегда явно передавайте второй параметр РежимПроведенияДокумента.Неоперативный в метод Записать(), если проведение выполняется программно. Оперативный режим по умолчанию контролирует текущее время и последовательность документов, что при пакетной обработке часто вызывает системные блокировки и ошибки.
  2. Логирование ошибок: не оставляйте блок Исключение пустым. Фиксируйте текст ошибки через ЗаписьЖурналаРегистрации или записывайте краткую причину отказа в реквизит Комментарий документа. Это позволит пользователю сразу понять, почему документ не провелся.
  3. Использование свойства ОбменДанными.Загрузка: если при создании черновика срабатывают строгие проверки модуля объекта (например, проверка заполнения реквизитов), свойство ДокументОбъект.ОбменДанными.Загрузка = Истина позволит обойти их и принудительно сохранить документ для ручного разбора.
← На главную