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