Документ КорректировкаЗаписейРегистров отличается от стандартных документов тем, что в нем нет привычной единой табличной части с аналитикой. Вместо этого он содержит несколько специальных табличных частей (например, ТаблицаРегистровСведений, ТаблицаРегистровНакопления, ТаблицаРегистровБухгалтерии), в которых хранятся метаданные — имена регистров, скорректированных данным документом.
В этой статье мы разберем по шагам, как правильно прочитать список модифицируемых регистров из документа, получить их наборы записей, внести необходимые изменения в реквизиты и сохранить обновленные данные.
При стандартной работе через интерфейс пользователи добавляют в документ строки с ручными правками. Однако при решении задач автоматизации (например, массовом изменении даты/периода движений или исправлении битых ссылок) возникает необходимость программной обработки.
Разберем основной принцип: мы не можем сразу обратиться к конкретному регистру, так как в документе может быть перечень самых разных регистров. Нам необходимо сначала запросить имена регистров из табличных частей документа, а затем сформировать наборы записей с отбором по регистратору.
Рассмотрим порядок действий для работы с регистрами сведений и регистрами накопления. Для начала сформируем запрос к табличным частям документа, чтобы извлечь имя каждого регистра, движение по которому создано этим документом.
Для регистров сведений обратимся к табличной части ТаблицаРегистровСведений, а для регистров накопления — к ТаблицаРегистровНакопления.
После получения имен регистров мы циклически обращаемся к глобальным коллекциям РегистрыСведений и РегистрыНакопления по имени, создаем набор записей, устанавливаем отбор по документу-регистратору, считываем данные, вносим правки и сохраняем изменения.
Посмотрим на практическую реализацию данного алгоритма:
Процедура ИзменитьДвиженияДокументаКорректировки(ДокументКорректировки, НоваяДатаКорректировки)
// 1. Обработка регистров сведений
ЗапросРС = Новый Запрос;
ЗапросРС.Текст =
"ВЫБРАТЬ
| ТЧ.Имя КАК Имя
|ИЗ
| Документ.КорректировкаЗаписейРегистров.ТаблицаРегистровСведений КАК ТЧ
|ГДЕ
| ТЧ.Ссылка = &ДокументКорректировки";
ЗапросРС.УстановитьПараметр("ДокументКорректировки", ДокументКорректировки);
ВыборкаРС = ЗапросРС.Выполнить().Выбрать();
Пока ВыборкаРС.Следующий() Цикл
НЗ = РегистрыСведений[ВыборкаРС.Имя].СоздатьНаборЗаписей();
НЗ.Отбор.Регистратор.Установить(ДокументКорректировки);
НЗ.Прочитать();
Для Каждого СтрокаЗаписи Из НЗ Цикл
СтрокаЗаписи.Период = НоваяДатаКорректировки;
КонецЦикла;
НЗ.Записать();
КонецЦикла;
// 2. Обработка регистров накопления
ЗапросРН = Новый Запрос;
ЗапросРН.Текст =
"ВЫБРАТЬ
| ТЧ.Имя КАК Имя
|ИЗ
| Документ.КорректировкаЗаписейРегистров.ТаблицаРегистровНакопления КАК ТЧ
|ГДЕ
| ТЧ.Ссылка = &ДокументКорректировки";
ЗапросРН.УстановитьПараметр("ДокументКорректировки", ДокументКорректировки);
ВыборкаРН = ЗапросРН.Выполнить().Выбрать();
Пока ВыборкаРН.Следующий() Цикл
НЗ = РегистрыНакопления[ВыборкаРН.Имя].СоздатьНаборЗаписей();
НЗ.Отбор.Регистратор.Установить(ДокументКорректировки);
НЗ.Прочитать();
Для Каждого СтрокаЗаписи Из НЗ Цикл
СтрокаЗаписи.Период = НоваяДатаКорректировки;
КонецЦикла;
НЗ.Записать();
КонецЦикла;
// Обновляем сам документ, если изменялась его шапка или реквизиты
ДокОбъект = ДокументКорректировки.ПолучитьОбъект();
ДокОбъект.Записать();
КонецПроцедуры
Проанализируем еще один эффективный способ работы — напрямую через объект документа и его коллекцию Движения. В этом случае платформой управляет сам объект документа, что снижает риск ошибок при автономной перезаписи наборов.
ПолучитьОбъект().Набор = ДокОбъект.Движения[ИмяРегистра].Набор.Прочитать(), модифицируем строки набора записей.ДокОбъект.Записать(). При этом платформа автоматически сохранит все измененные наборы записей.При выполнении массовой или программной корректировки записей важно учитывать следующие рекомендации:
1. Использование транзакций
При программном обновлении нескольких регистров всегда рекомендуется оборачивать операции записи в блок НачатьТранзакцию() ... ЗафиксироватьТранзакцию(). В случае ошибки при изменении одного из регистров транзакция будет отменена методом ОтменитьТранзакцию(), что убережет базу данных от рассинхронизации.
2. Флаг загрузки данных
Если вы модифицируете существующие движения без необходимости выполнения сложной бизнес-логики и подписок на события, перед вызовом метода Записать() объекта документа установите свойство ДокОбъект.ОбменДанными.Загрузка = Истина.
3. Полный охват типов регистров
Не забывайте, что в типовых конфигурациях документ КорректировкаЗаписейРегистров также может содержать движения по регистрам бухгалтерии (табличная часть ТаблицаРегистровБухгалтерии) и регистрам расчета (табличная часть ТаблицаРегистровРасчета). В универсальных обработках следует проверять все четыре вида табличных частей.