При разработке механизмов интеграции и создании собственных планов обмена разработчики нередко сталкиваются с ситуацией, когда в дереве метаданных у объекта План обмена отсутствует привычная ветка или пункт контекстного меню Предопределенные. Возникает закономерный вопрос: как зафиксировать конкретный узел в системе, чтобы программно или настроечно регистрировать на нем изменения объектов, не заставляя пользователя выбирать узел вручную?
Разберем архитектурные особенности платформы 1С:Предприятие, выясним причину отсутствия предопределенных узлов и рассмотрим проверенные альтернативные варианты решения поставленной задачи.
Проанализируем структуру объекта метаданных План обмена. В отличие от справочников или планов счетов, архитектура планов обмена в 1С рассчитана на динамическое связывание информационных баз в распределенные или гетерогенные структуры. На уровне платформы в каждом плане обмена заложен ровно один предопределенный узел — это ссылка на текущую базу данных. Обратиться к нему программно можно с помощью конструкции:
ТекущийУзел = ПланыОбмена[ИмяПланаОбмена].ЭтотУзел();
Все остальные узлы, представляющие собой базы-корреспонденты, создаются исключительно динамически — либо администратором в пользовательском режиме «1С:Предприятие», либо программно в момент инициализации обмена. Платформа принципиально запрещает создавать пользовательские предопределенные элементы конфигурации в планах обмена.
Если нам требуется жестко зафиксировать узел, для которого будут регистрироваться изменения справочников или документов, необходимо использовать альтернативные приемы проектирования.
Когда требуется минимальное вмешательство в типовую конфигурацию (например, в «1С:Управление нашей фирмой»), наиболее простым и надежным решением является добавление отдельной константы. Разберем этот вариант по шагам:
УзелДляРегистрацииИзменений с типом данных ПланОбменаСсылка.[ИмяВашегоПланаОбмена].Посмотрим на пример программной регистрации изменений с использованием константы:
УзелОбмена = Константы.УзелДляРегистрацииИзменений.Получить();
Если ЗначениеЗаполнено(УзелОбмена) И УзелОбмена <> ПланыОбмена.МойПланОбмена.ЭтотУзел() Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, СсылкаНаОбъект);
КонецЕсли;
Если мы не хотим добавлять новые реквизиты или константы для хранения настроек, можно опереться на регламентированный код узла либо программно получать единственный узел обмена, отличный от предопределенного узла ЭтотУзел().
Рассмотрим подробнее программный поиск по заранее оговоренному строковому коду. При создании узла в базе ему присваивается определенный код, например, "EXTERNAL_SYSTEM":
УзелОбмена = ПланыОбмена.МойПланОбмена.НайтиПоКоду("EXTERNAL_SYSTEM");
Если Не УзелОбмена.Пустая() Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, ДанныеДляРегистрации);
КонецЕсли;
Если же архитектура предполагает взаимодействие «точка-точка» (одна текущая база и строго одна база-приемник), настраивать отдельное хранение ссылки вовсе необязательно. Мы можем запросом выбрать подчиненный узел, исключив текущую базу:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Т.Ссылка КАК Узел
|ИЗ
| ПланОбмена.МойПланОбмена КАК Т
|ГДЕ
| Т.Ссылка <> &ЭтотУзел";
Запрос.УстановитьПараметр("ЭтотУзел", ПланыОбмена.МойПланОбмена.ЭтотУзел());
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ПланыОбмена.ЗарегистрироватьИзменения(Выборка.Узел, ОбъектДляРегистрации);
КонецЕсли;
Чтобы исключить человеческий фактор и необходимость ручной настройки узла пользователем, можно инициализировать узел с фиксированным уникальным идентификатором прямо в коде (например, в обработчике обновления информационной базы или при первом обращении к функции обмена).
Разберем пример создания узла с заранее известным УникальныйИдентификатор:
ФиксированныйГУИД = Новый УникальныйИдентификатор("11111111-2222-3333-4444-555555555555");
СсылкаНаУзел = ПланыОбмена.МойПланОбмена.ПолучитьСсылку(ФиксированныйГУИД);
УзелОбъект = СсылкаНаУзел.ПолучитьОбъект();
Если УзелОбъект = Неопределено Тогда
УзелОбъект = ПланыОбмена.МойПланОбмена.СоздатьУзел();
УзелОбъект.УстановитьСсылкуНового(СсылкаНаУзел);
УзелОбъект.Код = "EXT";
УзелОбъект.Наименование = "Внешний сервис";
УзелОбъект.Записать();
КонецЕсли;
Такой подход фактически превращает динамический элемент в аналог предопределенного: мы в любой момент можем обратиться к нему через фиксированный идентификатор без риска потерять соответствие при переносе или обновлении.
Автор обсуждения упомянул конфигурацию УНФ и выразил желание внести минимум изменений в типовое решение. В современных реалиях 1С:Предприятия оптимальным путем является перенос новых механизмов в Расширение конфигурации:
Используя предложенные подходы, можно гибко управлять регистрацией изменений на узлах обмена без необходимости использовать несуществующие в платформе предопределенные узлы.