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