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