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

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

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

Суть проблемы: работа с разными контекстами

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

Этот объект не имеет никакой связи с тем документом, который сейчас проводится в системе. У него есть своя собственная, изолированная коллекция движений. Процедура заполняет эту временную коллекцию, но как только работа процедуры завершается, объект удаляется сборщиком мусора, а все «движения» теряются. Исходная коллекция документа при этом остается нетронутой.

Разберем на примере ошибочного кода

Рассмотрим фрагмент кода, который приводит к этой ошибке:


// Ошибка: использование ПолучитьОбъект() создает копию документа
ПрослеживаемостьБП.СформироватьДвиженияРеализацияТоваров(..., СтруктураШапкиДокумента.Ссылка.ПолучитьОбъект().Движения);

Внутри вызываемой функции СформироватьДвиженияРеализацияТоваров происходит запись в переданную коллекцию. Однако эта коллекция принадлежит объекту, который существует только внутри данного вызова. Оригинальный объект, существующий в контексте формы или процесса проведения, «не видит» этих изменений.

Как правильно организовать процесс

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

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

Пример корректного формирования движений

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


Процедура СформироватьДвиженияПрослеживаемыхТоваров(ТаблицаТовары, Реквизиты, Движения, Списание = Ложь)
    
    // Работаем с переданной коллекцией движений, которая связана с объектом
    Для Каждого СтрокаТаблицы Из Параметры.Товары Цикл
        Если Списание Тогда
            Запись = Движения.ПрослеживаемыеТовары.ДобавитьРасход();
        Иначе
            Запись = Движения.ПрослеживаемыеТовары.ДобавитьПриход();
        КонецЕсли;
        
        Запись.Период = Реквизиты.Дата;
        ЗаполнитьЗначенияСвойств(Запись, Реквизиты);
        ЗаполнитьЗначенияСвойств(Запись, СтрокаТаблицы);
    КонецЦикла;
    
    // Указываем системе, что движения по этому регистру необходимо записать
    Движения.ПрослеживаемыеТовары.Записывать = Истина;
    
КонецПроцедуры

Выводы и рекомендации

Проанализировав данную ситуацию, можно сделать следующие выводы:

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

← На главную