Почему документ проводится с формы, но не проводится программно командой Записать

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

В практике разработки на платформе 1С:Предприятие 8.3 часто встречается ситуация: бухгалтер открывает документ, нажимает кнопку «Провести и закрыть», и всё отрабатывает идеально. Однако, как только мы пытаемся выполнить аналогичное действие программно с помощью метода Записать(РежимЗаписиДокумента.Проведение), система либо выдает ошибку, либо документ записывается, но не формирует движения. Особенно часто это проявляется в современных конфигурациях, таких как Бухгалтерия предприятия 3.0, ERP 2.5 или ЗУП 3.1.

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

Различие контекста: Форма против Объекта

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

  1. События модуля формы: ПередЗаписьюНаСервере, ПриЗаписиНаСервере, ПослеЗаписиНаСервере. Часто именно в этих процедурах разработчики конфигураций (или авторы доработок) прописывают заполнение важных реквизитов документа или подготовку данных в связанных регистрах.
  2. Интерактивные проверки: В форме могут быть визуальные элементы (флажки, переключатели), значения которых не хранятся в базе данных, но используются в коде формы для принятия решения о заполнении реквизитов объекта перед его сохранением.

Проанализируем ситуацию: если ваш код выглядит так, как в примере ниже, вы минуете весь «умный» функционал формы:


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

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

Ключевой фактор: ДополнительныеСвойства (AdditionalProperties)

Одной из самых частых причин отказа в проведении является использование структуры ДополнительныеСвойства. В конфигурациях на базе БСП (Библиотеки стандартных подсистем) эта структура активно используется для передачи инструкций от формы к объекту.

Разберем подробнее: когда форма инициирует проведение, она может добавить в объект специальные флаги, например:

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

Посмотрим на пример правильного заполнения свойств перед записью:


ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();

// Если мы знаем, что БСП требует определенные флаги
ДокОбъект.ДополнительныеСвойства.Вставить("ЭтоПроведениеИзФормы", Истина);
// Иногда нужно отключить проверки, которые мешают программной обработке
ДокОбъект.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаРедактирования", Истина);

Попытка
    ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
    Сообщить("Ошибка проведения: " + ОписаниеОшибки());
КонецПопытки;

Интерактивные вопросы и предупреждения

Еще одна причина, по которой проведение с формы работает, а программно — нет, заключается в клиент-серверном взаимодействии. В коде формы могут быть вызовы диалоговых окон: «Цены в документе изменились, пересчитать?», «Склад не заполнен, продолжить?». Если пользователь отвечает «Да», выполнение продолжается.

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

Механизм ОбменДанными.Загрузка

Иногда разработчики, желая «обойти» проверки, устанавливают флаг ОбменДанными.Загрузка = Истина. Рассмотрим ситуацию: вы устанавливаете этот флаг и вызываете проведение.


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

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

Фоновое проведение в БП 3.0

В последних редакциях «Бухгалтерии предприятия» реализован механизм отложенного или фонового проведения. Когда вы нажимаете кнопку на форме, система может не проводить документ мгновенно, а ставить его в очередь фоновых заданий.

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

Как найти точную причину? Пошаговая инструкция

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

  1. Точка останова в модуле объекта: Откройте модуль объекта документа и поставьте точку останова в самой первой строке процедуры ПередЗаписью.
  2. Запуск из формы: Проведите документ вручную. Когда отладчик остановится, внимательно изучите содержимое коллекции ДополнительныеСвойства. Запишите все ключи и значения, которые там присутствуют.
  3. Запуск программно: Запустите ваш программный код. Снова посмотрите на ДополнительныеСвойства. Те свойства, которых не хватает по сравнению с интерактивным запуском, и являются причиной «тихого» отказа или ошибки.
  4. Проверка параметра Отказ: Прошагайте код клавишей F8 до конца процедуры ОбработкаПроведения. Следите за переменной Отказ. Как только она станет Истина, вы поймете, какая именно проверка (в какой строке кода) блокирует операцию.

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

← На главную