Как программно изменить движения в документе «Корректировка записей регистров» в 1С

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

Документ КорректировкаЗаписейРегистров отличается от стандартных документов тем, что в нем нет привычной единой табличной части с аналитикой. Вместо этого он содержит несколько специальных табличных частей (например, ТаблицаРегистровСведений, ТаблицаРегистровНакопления, ТаблицаРегистровБухгалтерии), в которых хранятся метаданные — имена регистров, скорректированных данным документом.

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

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

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

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

Шаг 1. Получение списка регистров через запрос

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

Для регистров сведений обратимся к табличной части ТаблицаРегистровСведений, а для регистров накопления — к ТаблицаРегистровНакопления.

Шаг 2. Чтение и модификация наборов записей

После получения имен регистров мы циклически обращаемся к глобальным коллекциям РегистрыСведений и РегистрыНакопления по имени, создаем набор записей, устанавливаем отбор по документу-регистратору, считываем данные, вносим правки и сохраняем изменения.

Посмотрим на практическую реализацию данного алгоритма:


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

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

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

Альтернативный подход через коллекцию «Движения»

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

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

Важные технические нюансы

При выполнении массовой или программной корректировки записей важно учитывать следующие рекомендации:

1. Использование транзакций
При программном обновлении нескольких регистров всегда рекомендуется оборачивать операции записи в блок НачатьТранзакцию() ... ЗафиксироватьТранзакцию(). В случае ошибки при изменении одного из регистров транзакция будет отменена методом ОтменитьТранзакцию(), что убережет базу данных от рассинхронизации.

2. Флаг загрузки данных
Если вы модифицируете существующие движения без необходимости выполнения сложной бизнес-логики и подписок на события, перед вызовом метода Записать() объекта документа установите свойство ДокОбъект.ОбменДанными.Загрузка = Истина.

3. Полный охват типов регистров
Не забывайте, что в типовых конфигурациях документ КорректировкаЗаписейРегистров также может содержать движения по регистрам бухгалтерии (табличная часть ТаблицаРегистровБухгалтерии) и регистрам расчета (табличная часть ТаблицаРегистровРасчета). В универсальных обработках следует проверять все четыре вида табличных частей.

← На главную