Почему не добавляются проводки в регистр бухгалтерии через метод Движения.Добавить()?

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

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

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

Причина проблемы: отсутствие связи с регистратором

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

Чтобы запись была успешно создана, перед вызовом метода Добавить() необходимо явно указать регистратор для коллекции движений нужного регистра. Делается это через установку свойства Регистратор.

Решение 1: Установка свойства "Регистратор" напрямую

Этот способ подходит, когда вы работаете с движениями непосредственно в модуле объекта документа. Например, в обработке проведения. Посмотрим на пошаговый алгоритм.

  1. Получаем доступ к коллекции движений нужного регистра. Например, для регистра бухгалтерии "Хозрасчетный" это будет ЭтотОбъект.Движения.Хозрасчетный.
  2. Перед тем как добавлять записи, устанавливаем свойство Регистратор, присвоив ему ссылку на текущий документ (ЭтотОбъект.Ссылка).
  3. Теперь можно в цикле или поштучно добавлять новые движения с помощью метода Добавить().

Посмотрим на пример. Изначально мог быть такой код, который не работает:


// НЕПРАВИЛЬНЫЙ КОД
Процедура ОбработкаПроведения(Отказ, РежимПроведения)

    Для Каждого ТекСтрокаТЧ Из Товары Цикл
        Движение = ЭтотОбъект.Движения.Хозрасчетный.Добавить();
        Движение.СчетДт = ПланыСчетов.Хозрасчетный.ТоварыНаСкладах;
        Движение.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСПоставщиками;
        Движение.Период = Дата;
        Движение.Сумма = ТекСтрокаТЧ.Сумма;
        // ... заполнение других полей
    КонецЦикла;

КонецПроцедуры

А вот исправленный и корректно работающий вариант. Обратите внимание на одну ключевую строку, добавленную перед циклом.


// ПРАВИЛЬНЫЙ КОД
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Указываем, что все последующие движения будут принадлежать этому документу
    ЭтотОбъект.Движения.Хозрасчетный.Регистратор = ЭтотОбъект.Ссылка;
    
    Для Каждого ТекСтрокаТЧ Из Товары Цикл
        Движение = ЭтотОбъект.Движения.Хозрасчетный.Добавить();
        Движение.СчетДт = ПланыСчетов.Хозрасчетный.ТоварыНаСкладах;
        Движение.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСПоставщиками;
        Движение.Период = Дата;
        Движение.Сумма = ТекСтрокаТЧ.Сумма;
        Движение.Организация = Организация;
        
        // Заполнение субконто
        Движение.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура] = ТекСтрокаТЧ.Номенклатура;
        Движение.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Склады] = Склад;
        
        Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты] = Контрагент;
        Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры] = Договор;
    КонецЦикла;

КонецПроцедуры

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

Решение 2: Использование объекта "РегистрБухгалтерииНаборЗаписей"

Более универсальным и зачастую более производительным способом работы с записями регистров является использование специального объекта РегистрБухгалтерииНаборЗаписей. Этот подход рекомендуется использовать, особенно если вы работаете с движениями не в модуле документа, а, например, во внешней обработке, или если вам нужно выполнить пакетные операции (добавить, изменить или удалить сразу много записей).

Разберем по шагам, как работать с набором записей:

  1. Создаем объект набора записей. Для этого обращаемся к нужному регистру через менеджер регистров: НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
  2. Устанавливаем отбор по регистратору. Это самый важный шаг, аналогичный установке свойства Регистратор в первом решении. Мы говорим набору, к какому документу он будет относиться.
    
    // Предполагается, что переменная СсылкаНаДокумент уже содержит ссылку
    // на нужный документ-регистратор.
    НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);
    
  3. (Опционально, но рекомендуется) Читаем существующие записи. Если для данного документа уже могут быть записи и вы хотите их дополнить или изменить, а не полностью перезаписать, нужно сначала прочитать их из базы данных. НаборЗаписей.Прочитать();
  4. Добавляем новые записи. Используем метод Добавить() самого набора записей. Он возвращает объект новой записи, который мы затем заполняем.
    
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.Период = СсылкаНаДокумент.Дата;
    НоваяЗапись.СчетДт = ...;
    НоваяЗапись.СчетКт = ...;
    НоваяЗапись.Сумма = ...;
    // и так далее
    
  5. Записываем набор. После того как все необходимые записи добавлены или изменены, весь набор целиком записывается в базу данных одной транзакцией с помощью метода Записать(). Если нужно перед записью полностью очистить старые движения этого регистратора, можно использовать флаг Записать(Истина). НаборЗаписей.Записать(); // Записывает набор, замещая старые записи

Посмотрим на полный пример кода с использованием набора записей:


// Получаем ссылку на документ, который будет регистратором
СсылкаНаДокумент = Документы.ПоступлениеТоваровУслуг.НайтиПоНомеру("ПТ-00001", ТекущаяДата());

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

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

← На главную