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