Почему при программном проведении документ не формирует движения по регистру?

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

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

Различие между прямой записью в регистр и использованием коллекции «Движения»

Одной из главных ошибок начинающих разработчиков является смешивание двух разных подходов к формированию записей. Рассмотрим первый подход, который часто приводит к проблемам кэширования и целостности данных — использование НаборЗаписей напрямую через менеджер регистра.

Когда мы пишем код подобного вида:


НаборЗаписей = РегистрыСведений.Застрахованные.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(ДоговорСсылка);
// Заполнение набора...
НаборЗаписей.Записать();

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

Для правильной работы проанализируем второй подход — использование свойства Движения объекта документа. Рассмотрим пример правильного обращения к коллекциям:


ДокОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Заполняем табличную часть
НоваяСтрока = ДокОбъект.ЗастрахованныеЛица.Добавить();
НоваяСтрока.ФизЛицо = Справочники.ФизическиеЛица.НайтиПоНаименованию("Иванов");

// Инициируем проведение
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);

Использование флага «Записывать» в коллекции движений

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

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


ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Указываем платформе, что этот регистр нужно обновить в базе
ДокументОбъект.Движения.Застрахованные.Записывать = Истина;

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

ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

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

Влияние режима удаления движений в метаданных

Разберем, как настройки конфигуратора влияют на поведение системы. В свойствах каждого документа есть важный параметр — «Удаление движений». Он может принимать значения:

  1. Удалять автоматически: При каждом перепроведении система сначала полностью очищает все записи регистров, где данный документ является регистратором, и только потом запускает процедуру ОбработкаПроведения.
  2. Не удалять автоматически: Система оставляет управление движениями на откуп разработчику.

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

Проблема отображения в интерфейсе

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

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

Для того чтобы документ корректно сформировал все движения после программного изменения его данных, рекомендуется придерживаться следующего алгоритма:

  1. Получим объект документа из ссылки: Объект = Ссылка.ПолучитьОбъект();
  2. Внесем необходимые изменения в табличные части или реквизиты документа.
  3. Убедимся, что в модуле документа в процедуре ОбработкаПроведения нет жестких условий, прерывающих выполнение (например, проверок на заполненность, которые могут не пройти при программном заполнении).
  4. Вызовем метод проведения: Объект.Записать(РежимЗаписиДокумента.Проведение);

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


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

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

ОбъектДок.Записать(РежимЗаписиДокумента.Запись); 

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

← На главную