В процессе настройки синхронизации данных между несколькими информационными базами 1С через универсальный формат (EnterpriseData) разработчики часто сталкиваются с жестким ограничением платформы: код узла плана обмена должен быть уникальным. Если в вашей экосистеме есть несколько баз с одинаковым префиксом (например, несколько филиалов на «1С:Бухгалтерия» с префиксом БП), стандартный «Помощник создания обмена данными» выдаст ошибку: Значение поля "Код" не уникально. Это происходит потому, что платформа 1С на уровне метаданных контролирует уникальность поля Код для объектов типа ПланОбмена.
В этой статье мы подробно разберем, почему возникает эта проблема, и рассмотрим несколько стратегий ее решения — от простых «костылей» до глубокой программной модификации механизмов обмена.
Проанализируем ситуацию с точки зрения архитектуры платформы. Поле Код в плане обмена используется не только для визуальной идентификации. Оно является ключом для поиска узла при поступлении входящих данных. Когда база получает файл обмена, она считывает заголовок, находит там код отправителя и ищет соответствующий узел в справочнике плана обмена. Если бы в системе существовало два узла с кодом БП, программа не смогла бы определить, к какому именно узлу применить изменения и для какого узла зафиксировать номер принятого сообщения.
Кроме того, префикс базы (который обычно совпадает с кодом узла) участвует в формировании номеров документов и кодов справочников. Дублирование префиксов в одной центральной базе может привести к коллизиям — ситуации, когда два разных документа из разных баз получат одинаковые номера.
Рассмотрим первый вариант обхода, предложенный в сообществе. Если стандартный план обмена СинхронизацияДанныхЧерезУниверсальныйФормат уже содержит узел с кодом ХА, платформа не даст создать второй такой же. Однако ограничение уникальности действует только в рамках одного конкретного плана обмена.
Пошаговый алгоритм действий:
ХА, так как в этом пространстве имен данный код еще не занят.Важное примечание: Этот метод требует значительных трудозатрат, так как вам придется переписывать или адаптировать все подсистемы БСП (Библиотеки стандартных подсистем), которые «заточены» под работу с конкретным типовым планом обмена. Рассмотрим этот вариант только как крайнюю меру.
Разберем более простой, но «хитрый» способ. Платформа проверяет строковую уникальность. Для нее строки "БП" и "БП " (с неразрывным пробелом в конце) — это разные значения.
Выясним, как это реализовать:
Код введите основной префикс и добавьте специальный символ (например, неразрывный пробел, Alt+255 или символ с кодом 160).БП, но ошибка уникальности исчезнет.Риски: Будьте осторожны, так как функции СокрЛП() или ТримП() в программном коде могут обрезать этот пробел, что снова приведет к конфликтам при поиске узла. Также это может повлиять на имена файлов выгрузки, если код узла используется в формировании пути.
Проанализируем самый профессиональный и безопасный подход. Мы оставляем коды узлов уникальными (например, БП1, БП2, БП3), чтобы платформа была «довольна». Но при этом мы модифицируем сами данные в момент обмена, чтобы целевая база воспринимала их как данные от префикса БП.
Для этого нам понадобится расширение конфигурации. Нам нужно вмешаться в процесс формирования сообщения обмена. Рассмотрим пример кода, который можно внедрить в процедуру перед отправкой данных:
// В модуле менеджера или через расширение в общем модуле ОбменДаннымиСервер
Процедура ПередОтправкойДанных(УзелИнформационнойБазы, ОтправкаДанных)
// Проверяем, что это наш "особенный" узел
Если УзелИнформационнойБазы.Код = "БП1" Тогда
// Логика подмены кода отправителя в заголовке сообщения
// Здесь мы можем программно изменить текст XML, заменив БП1 на БП
КонецЕсли;
КонецПроцедуры
Разберем по шагам, что нужно сделать в рамках этого метода:
БП1, БП2 и т.д.).ОбщиеНастройкиУзловИнформационныхБаз оставляем возможность сопоставления.ПриОтправкеДанных (в правилах конвертации или через подписки на события), чтобы в XML-файле в поле КодОтправителя всегда записывалось значение БП.ПриПриемеДанных, чтобы выполнить обратное преобразование: если файл пришел от БП, но мы знаем (по GUID или другим признакам), что это БП1, мы подставляем нужный узел плана обмена.Как мы видели в первом сообщении темы, ошибка часто генерируется программно в модуле менеджера Обработка.ПомощникСозданияОбменаДанными. Посмотрим на код, который вызывает прерывание:
Иначе
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Значение префикса программы ""%1"" не уникально (""%2"")...'"),
НастройкиПодключения.НаименованиеВторойБазы, КодНовогоУзла);
КонецЕсли;
Чтобы обойти эту проверку, создадим расширение и воспользуемся аннотацией &Вместо для метода, производящего проверку. Рассмотрим пример реализации:
&Вместо("ПроверитьУникальностьПрефикса")
Процедура Расш_ПроверитьУникальностьПрефикса(Параметры)
// Просто оставляем тело процедуры пустым или пишем свою логику.
// Это позволит помощнику пройти этап проверки.
Возврат;
КонецПроцедуры
Внимание: Подавление проверки в помощнике — это только половина дела. При вызове НовыйУзел.Записать() сама платформа 1С может выбросить ошибку, если в свойствах Плана Обмена в Конфигураторе стоит флажок «Уникальность кода». В типовых конфигурациях этот флаг обычно включен. Изменить его в расширении невозможно, поэтому данный метод сработает только в паре со Способом №2 (невидимые символы).
Мы проанализировали ситуацию и выяснили, что требование уникальности префиксов — это фундаментальный механизм обеспечения целостности данных в 1С. Однако в сложных распределенных системах его приходится обходить.
Наш совет: наиболее стабильным решением является использование уникальных кодов узлов в базе (БП_ФИЛИАЛ1, БП_ФИЛИАЛ2) с последующей настройкой префиксации документов. В современных конфигурациях на базе БСП префикс номера документа можно хранить отдельно от кода узла плана обмена. Это позволит вам иметь уникальные узлы для синхронизации, но при этом сохранять привычную нумерацию документов с префиксом БП в обеих базах.
Если же это невозможно, используйте Способ №3 (программная подмена в XML) как наиболее гибкий и не нарушающий логику работы платформы.