Как правильно провести документ программно в 1С и обеспечить формирование движений в регистрах

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

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

Базовый метод проведения объекта

Для того чтобы документ не просто записался, а именно провелся с вызовом обработчика ОбработкаПроведения, необходимо использовать метод Записать() с параметром РежимЗаписиДокумента.Проведение. Разберем стандартный пример кода:


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

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

Анализ причин отсутствия движений

Рассмотрим ситуацию, когда флаг проведения установлен, а движений нет. Выясним основные причины такого поведения системы:

  1. Не заполнены реквизиты, влияющие на логику: В типовых конфигурациях (таких как УТ 10.3, УПП или КА) код в процедуре ОбработкаПроведения часто содержит условия. Если какой-то реквизит (например, ВидОперации, Склад или Договор) не заполнен, программа может просто «перепрыгнуть» блок формирования движений, не выдавая при этом ошибки.
  2. Проверки в модуле объекта: Проанализируем модуль документа. Часто разработчики ставят условие: Если ТабличнаяЧасть.Количество() = 0 Тогда Возврат; КонецЕсли;. В этом случае документ пометится как проведенный, но движений не будет, так как выполнение процедуры прервалось раньше.
  3. Режим обмена данными: Проверьте, не установлено ли свойство Док.ОбменДанными.Загрузка = Истина. Если этот флаг включен, платформа отключает все обработчики событий, включая проведение. Движения в этом режиме не формируются автоматически.

Различие между логикой формы и логикой объекта

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

Для решения этой проблемы рекомендуется использовать метод Заполнить(), который вызывает процедуру ОбработкаЗаполнения в модуле объекта:


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

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

Оперативное и неоперативное проведение

Проанализируем влияние режима проведения на результат. Метод Записать() принимает второй параметр — РежимПроведенияДокумента. Если вы проводите документ текущей датой и временем, система по умолчанию пытается провести его оперативно.


// Неоперативное проведение (важно для документов прошлых периодов)
НовыйДок.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);

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

Проведение из другого документа (вложенные транзакции)

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

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

Чтобы избежать проблем при вложенном проведении:

Методика отладки программного проведения

Если движения так и не появились, пройдем по шагам алгоритм поиска ошибки:

  1. Откройте модуль объекта нужного документа в конфигураторе.
  2. Найдите процедуру ОбработкаПроведения.
  3. Поставьте точку останова в самом начале этой процедуры.
  4. Запустите ваш программный код создания документа.
  5. Когда выполнение остановится на точке останова, пошагово (клавиша F10) пройдите весь код.
  6. Следите за переменной Отказ. Если в какой-то момент Отказ = Истина, значит, документ не проходит по бизнес-логике.
  7. Обратите внимание на блоки, где заполняется коллекция Движения. Если код проходит мимо них — вы нашли причину (не соблюдено условие).

Использование ДополнительныеСвойства

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


НовыйДок.ДополнительныеСвойства.Вставить("ЭтоПрограммноеПроведение", Истина);
// Некоторые модули ищут такие флаги, чтобы пропускать лишние диалоги
НовыйДок.Записать(РежимЗаписиДокумента.Проведение);

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

← На главную