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