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