При работе с несколькими базами 1С:Управление торговлей 11 (например, при наличии рабочей базы продаж и консолидирующей базы управленческого учета) часто возникает проблема рассинхронизации справочников. Если пользователи создают номенклатуру, контрагентов или валюты параллельно в обеих системах, то при регулярном переносе документов данные начинают «плыть». Появляются многочисленные дубли, ломается аналитика, а ручные исправления превращают поддержку систем в бесконечный рутинный процесс.
В этой статье мы подробно разберем, как решить проблему рассинхронизации справочников раз и навсегда. Мы рассмотрим четыре практических сценария решения: от штатного интерактивного сопоставления до технического подключения существующей базы к РИБ и программного выравнивания уникальных идентификаторов (UUID/УИД) объектов.
В современных конфигурациях 1С на базе Библиотеки стандартных подсистем (БСП), включая Управление торговлей 11, реализован мощный механизм сопоставления данных. Вся информация о связях между объектами в разных базах хранится в регистре сведений СоответствияОбъектовИнформационныхБаз. Это позволяет связывать объекты с совершенно разными уникальными идентификаторами (GUID), предотвращая появление дублей.
Разберем по шагам, как настроить интерактивный обмен без программирования:
EnterpriseData или правила обмена.Номенклатура, Валюты) настроим поля поиска. По умолчанию 1С ищет объекты по внутреннему идентификатору (УИД). Нам необходимо отключить этот признак для первого обмена и установить сопоставление по реквизитам:
Артикулу, Штрихкоду или сочетанию Наименование + Производитель.Коду (цифровому коду валюты).СоответствияОбъектовИнформационныхБаз. При всех последующих обменах документы будут корректно находить сопоставленные элементы, даже если их УИД в базах различаются.Если нам необходимо программно внести запись в этот регистр для автоматизации процесса, мы можем использовать следующий код:
МенеджерЗаписи = РегистрыСведений.СоответствияОбъектовИнформационныхБаз.СоздатьМенеджерЗаписи();
МенеджерЗаписи.УзелИнформационнойБазы = УзелОбмена; // Ссылка на узел плана обмена
МенеджерЗаписи.СобственнаяСсылка = СсылкаВЛокальнойБазе;
МенеджерЗаписи.УникальныйИдентификаторИсточника = СсылкаВЛокальнойБазе.УникальныйИдентификатор();
МенеджерЗаписи.УникальныйИдентификаторПриемника = Новый УникальныйИдентификатор(GUID_В_Центральной_Базе);
МенеджерЗаписи.ТипИсточника = "СправочникСсылка.Номенклатура";
МенеджерЗаписи.ТипПриемника = "СправочникСсылка.Номенклатура";
МенеджерЗаписи.Записать();
Распределенная информационная база (РИБ) — это самый надежный способ поддерживать идентичность справочников «из коробки». В РИБ все изменения справочников, созданные в центральной базе, гарантированно и без искажений переносятся в подчиненные узлы.
Однако стандартный механизм создания РИБ требует генерации начального образа, что полностью затирает базу-приемник. Если в подчиненной базе уже ведется независимый учет и там накоплены документы, затирать ее нельзя. Рассмотрим технический трюк, который позволяет «привязать» уже существующую рабочую базу в качестве подчиненного узла РИБ:
.cf) из ЦБ и загрузим его в ПБ через «Конфигуратор» — «Поддержка» — «Обновить конфигурацию» (или просто «Загрузить конфигурацию из файла»).
УзелГлавный = ПланыОбмена.НайтиПоКоду("ЦБ");
Если ЗначениеЗаполнено(УзелГлавный) Тогда
ПланыОбмена.УстановитьГлавныйУзел(УзелГлавный);
Сообщить("База успешно переведена в режим подчиненного узла РИБ!");
Иначе
Сообщить("Узел с кодом ЦБ не найден в планах обмена подчиненной базы!");
КонецЕсли;
Если жесткие ограничения РИБ (например, запрет на изменение конфигурации в подчиненной базе) нам не подходят, лучшим выбором будет использование универсального формата обмена EnterpriseData. В отличие от старых правил обмена Конвертации данных 2.0, где алгоритмы поиска жестко прописаны внутри правил, в EnterpriseData (на базе Конвертации данных 3.0) логика сопоставления гибко отделена от самой структуры данных.
Проанализируем, как переопределить логику поиска элементов без изменения типовой конфигурации:
Мы можем создать небольшое Расширение конфигурации, в котором переопределим алгоритм сопоставления в общем модуле менеджера обмена. Например, переопределим обработку сопоставления номенклатуры, заставив систему искать объекты исключительно по связке реквизитов Артикул и Производитель, полностью игнорируя проверку по внутреннему УИД при первом поиске.
Для этого в расширении переопределим процедуру сопоставления в модуле МенеджерОбменаЧерезУниверсальныйФормат:
&После("ПриСопоставленииДанных")
Процедура Расш_ПриСопоставленииДанных(ДанныеИмпорта, ПолученныеДанные, СвойстваОчистки, Шла Запись)
Если ДанныеИмпорта.ТипИмпорта = "СправочникСсылка.Номенклатура" Тогда
// Наш кастомный алгоритм поиска по артикулу
АртикулИмпорта = ДанныеИмпорта.Артикул;
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", АртикулИмпорта);
Если ЗначениеЗаполнено(НайденнаяСсылка) Тогда
ДанныеИмпорта.СопоставленнаяСсылка = НайденнаяСсылка;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Такой подход позволит автоматически сопоставлять огромные массивы информации без привлечения пользователей к ручной рутинной работе.
Если обмен между базами планируется односторонний и долгосрочный, наиболее фундаментальным и изящным решением является приведение УИД (UUID) всех ключевых справочников в подчиненной базе к "общему знаменателю" центральной базы. Когда уникальные идентификаторы объектов в обеих базах станут абсолютно одинаковыми, любые стандартные обмены (даже простые обработки выгрузки/загрузки XML) начнут сопоставлять данные автоматически.
Сложность этого метода заключается в том, что в 1С нельзя напрямую перезаписать УИД у уже существующей ссылки (метод УстановитьСсылкуНового() работает только для новых, еще не записанных в базу объектов). Для решения этой задачи разберем специальный алгоритм программной замены:
НайтиИЗаменитьДубли(), чтобы перенаправлять все ссылки в документах, регистрах и движениях со старого локального элемента на новый эталонный элемент.Рассмотрим пример кода, реализующий этот алгоритм для справочника Номенклатура:
Процедура ВыровнятьУИДНоменклатуры(ЛокальнаяСсылка, ЭталонныйУИДСтрокой)
НовыйУИД = Новый УникальныйИдентификатор(ЭталонныйУИДСтрокой);
ЭквивалентнаяСсылка = Справочники.Номенклатура.ПолучитьСсылка(НовыйУИД);
// Проверим, существует ли уже в базе элемент с таким УИД
Если ЗначениеЗаполнено(ЭквивалентнаяСсылка.ВерсияДанных) Тогда
// Элемент с эталонным УИД уже есть. Просто заменим локальный дубль на него.
ЗаменитьСсылки(ЛокальнаяСсылка, ЭквивалентнаяСсылка);
Иначе
// Создаем новый элемент справочника с принудительной установкой эталонного УИД
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
НовыйОбъект.УстановитьСсылкуНового(ЭквивалентнаяСсылка);
// Копируем все данные из старого элемента
ЗаполнитьЗначенияСвойств(НовыйОбъект, ЛокальнаяСсылка.ПолучитьОбъект(), "Ссылка, Предопределенный");
НовыйОбъект.Записать();
// Заменяем все вхождения старой ссылки на новую во всей базе данных
ЗаменитьСсылки(ЛокальнаяСсылка, ЭквивалентнаяСсылка);
// Удаляем старый некорректный элемент
СтарыйОбъект = ЛокальнаяСсылка.ПолучитьОбъект();
СтарыйОбъект.УстановитьПометкуУдаления(Истина);
СтарыйОбъект.Удалить();
КонецЕсли;
КонецПроцедуры
Процедура ЗаменитьСсылки(ИсточниковаяСсылка, ЦелеваяСсылка)
ТаблицаЗамен = Новый ТаблицаЗначений;
ТаблицаЗамен.Колонки.Добавить("ИсходноеЗначение");
ТаблицаЗамен.Колонки.Добавить("ЗаменяющееЗначение");
НоваяСтрока = ТаблицаЗамен.Добавить();
НоваяСтрока.ИсходноеЗначение = ИсточниковаяСсылка;
НоваяСтрока.ЗаменяющееЗначение = ЦелеваяСсылка;
// Вызываем стандартный метод БСП для поиска и замены дублирующихся ссылок
ОбщегоНазначения.ЗаменитьСсылки(ТаблицаЗамен);
КонецПроцедуры
Важное предупреждение: Физическое выравнивание УИД — это необратимая транзакционная операция, существенно нагружающая базу данных из-за поиска ссылок по всем таблицам. Перед проведением такой процедуры обязательно создайте резервную копию базы данных и убедитесь, что в системе нет активных сеансов пользователей.
Выбор конкретного метода зависит от масштаба вашей инфраструктуры и регулярности обменов: