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