Обмен через универсальный формат широко используется в типовых конфигурациях. Для ознакомления есть хорошая статья //infostart.ru/public/695523/, также множество различных курсов, в которых разложены основные моменты по работе с правилами конвертации, синхронизации объектов метаданных.
Основной принцип создания "нестандартных" правил обмена заключается в доработке модуля "МенеджерОбменаЧерезУниверсальныйФормат" (в различных конфигурациях название может немного отличаться). Но что делать, если в компании участвуют несколько баз данных - стандартных, самописных (неважно), между которыми идет активный обмен данными EnterpriseData - и на каждый узел обмена могут действовать свои специфические правила?
В данном случае удобно использовать механизм расширений конфигурации - и если требуется организовать специфичные правила обмена, тогда в конфигурации создается отдельное расширение о обмену.
Рассмотрим пример передачи данных из базы УТ 11.3 в идентичную по структуре базу данных "Дочерняя УТ 11.3".
Постановка задачи: в основной базе данных производятся продажи товаров специфическому контрагенту, который является "дочерней фирмой" по отношению к основной. Необходимо реализовать "одностороннее" правило обмена "Реализации товаров и услуг -> Поступления товаров и услуг" по контрагенту с фиксированным ИНН.
Сокращения:
ЦБ - база-источник УТ 11.3, из которой идет выгрузка документов "Реализации товаров и услуг"
УТ - база приемник, в которой при обмене создаются "Поступления товаров"
ED - универсальный обмен (EnterpriseData)
В базе ЦБ создаются и проводятся "Реализации товаров" - и после проведения регистрируются в обмене ED, далее происходит обмен (через фоновое задание, либо вручную через каталог обмена). В при этом документ "Реализация товаров" должен "превратиться" в "Поступление товаров и услуг", а контрагент и организация "поменяться местами".
Как настраивать синхронизацию данных по плану обмена описано не будет - для этого существует множество различных статей. Переходим непосредственно к созданию правил обмена.
Предположим, что у нас настроен обмен, при котором главный узел организации-источника имеет код "ЦБ", а узел приемника код "УТ".
База-источник:
База-приемник:
Для начала создадим расширение конфигурации: назовем его, для примера "РасширениеОбмен" - и добавим модули, которые нам нужны для решения задачи.
1.Установка активного узла обмена в параметре сеанса. К сожалению, в процессе обмена не всегда можно получить активный узел, для которого происходит обмен. В процессе самого обмена данными структура данных "КомпонентыОбмена", содержащая все настройки обмена ED (в том числе ссылку на узел обмена) доступна не в каждой процедуре при обмене данными: например, при непосредственном заполнении перечня правил обмена "МенеджерОбменаЧерезУниверсальныйФормат.ЗаполнитьПравилаОбработкиДанных" этой переменной в параметрах нет.
На этапе инициализации обмена данными установим код узла обмена в параметры сеанса:
&Перед("ИнициализироватьТаблицыПравилОбмена")
Процедура РасшОбмен_ИнициализироватьТаблицыПравилОбмена(КомпонентыОбмена) Экспорт
Если КомпонентыОбмена.УзелКорреспондента <> Неопределено Тогда
Буф = Новый Структура(ПараметрыСеанса.БуферОбмена);
Буф.Вставить("КомпонентыОбмена_УзелКорреспондента_Код", КомпонентыОбмена.УзелКорреспондента.Код);
ПараметрыСеанса.БуферОбмена = Новый ФиксированнаяСтруктура(Буф);
КонецЕсли;
КонецПроцедуры
2. Регистрация объектов. Также необходимо выделить перечень объектов, необходимых для регистрации в нужном нам узле универсального обмена. Это можно сделать, отредактировав правила регистрации объектов с использованием конфигурации "Конвертер 2.1", но в случае с расширением достаточно переопределить работу функции, разбирающей правила регистрации. В задании для нашего узла обмена нам нужны совсем "немногие" ссылки на объекты, остальное необходимо "отсечь".
Регистрироваться будет документ "Реализации товаров и услуг" и некоторые входящие в него ссылки: организация, контрагент, валюта, склад.
&После("ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена")
// Процедура-обертка, выполняет код основной процедуры в режиме попытки
// (см. ВыполнитьПравилаРегистрацииОбъектовДляПланаОбменаПопыткаИсключение).
//
// Параметры:
// МассивУзловРезультат - Массив - массив узлов получателей плана обмена ИмяПланаОбмена,
// для которых необходимо выполнить регистрацию.
// Объект - Произвольный - изменяемые данные: объект, набор записей, константа или сведения об удалении объекта.
// ИмяПланаОбмена - Строка - имя плана обмена, для которого выполняется механизм регистрации.
// ДополнительныеПараметры - Структура - уточняющие сведения об изменяемых данных:
// * ОбъектМетаданных - ОбъектМетаданных - объект метаданных, которому соответствуют изменяемые данные. Обязательный.
// * ЭтоРегистр - Булево - значение Истина означает, что обрабатывается регистр.
// Необязательный, значение по умолчанию Ложь.
// * ЭтоУдалениеОбъекта - Булево - значение Истина означает, что обрабатывается удаление объекта.
// Необязательный, значение по умолчанию Ложь.
// * РежимЗаписи - см. в синтаксис-помощнике РежимЗаписиДокумента - режим записи документа (только для документов).
// Необязательный, значение по умолчанию Неопределено.
// * Замещение - Булево - режим записи регистра (только для регистров).
// Необязательный, значение по умолчанию Неопределено.
// * ПроверятьСсылку - Булево - признак необходимости учитывать версию данных на момент до их изменения.
// Необязательный, значение по умолчанию Ложь.
// * Выгрузка - Булево - параметр определяет контекст выполнения правила регистрации.
// Истина - правило регистрации выполняется в контексте выгрузки объекта.
// Ложь - правило регистрации выполняется в контексте перед записью объекта.
// Необязательный, значение по умолчанию Ложь.
//
Процедура РасшОбмен_ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры)
Если ИмяПланаОбмена = "СинхронизацияДанныхЧерезУниверсальныйФормат" Тогда
//ищем входит ли регистрируемый объект ключевой узел обмена с кодом "УТ"
ПОСсылка = Неопределено;
Для каждого ТекУзел Из МассивУзловРезультат Цикл
Если ТипЗнч(ТекУзел.Ссылка) = Тип("ПланОбменаСсылка."+ИмяПланаОбмена) И ТекУзел.Код = "УТ" Тогда
ПОСсылка = ТекУзел.Ссылка
КонецЕсли;
КонецЦикла;
Если ПОСсылка <> Неопределено Тогда
Если ТипЗнч(Объект) = Тип("ДокументОбъект.РеализацияТоваровУслуг") Тогда
//проверяем, является ли контрагент по документу реализации "фирмой", ИНН которой есть среди "Справочник.Организации"
ЭтоОрганизация = ложь;
Выборка = Справочники.Организации.выбрать();
Пока Выборка.Следующий() Цикл
Если НЕ Выборка.ПометкаУдаления И Выборка.ИНН = Объект.Контрагент.ИНН Тогда
ЭтоОрганизация = истина;
КонецЕсли;
КонецЦикла;
Если Не ЭтоОрганизация Тогда
МассивУзловРезультат.Удалить(МассивУзловРезультат.Найти(ПОСсылка));
Возврат
КонецЕсли;
// для регистрации данных в файле обмена должны появиться не только сам документ-реализация,
// но и определенный перечень ссылок из объекта: так как возможно, что какой-то из объектов "уходит"
// в приемник в 1-й раз
МассивСсылок = новый Массив;
МассивСсылок.Добавить(Объект.Организация);
МассивСсылок.Добавить(Объект.Контрагент);
МассивСсылок.Добавить(Объект.Склад);
МассивСсылок.Добавить(Объект.Валюта);
Для каждого ТекСтрока Из Объект.Товары Цикл
МассивСсылок.Добавить(ТекСтрока.Номенклатура);
ПолучитьСсылкиВнутриОбъекта(ТекСтрока.Номенклатура, МассивСсылок);
Если Не ТекСтрока.Упаковка.Пустая() Тогда
МассивСсылок.Добавить(ТекСтрока.Упаковка);
КонецЕсли;
КонецЦикла;
Взаимодействия.УдалитьПовторяющиесяЭлементыМассива(МассивСсылок);
Для каждого ТекСсылка Из МассивСсылок Цикл
Если ТекСсылка = Объект.Ссылка Тогда
Продолжить;
ИначеЕсли Не ЗначениеЗаполнено(ТекСсылка) Тогда
Продолжить;
ИначеЕсли Метаданные.ПланыОбмена[ИмяПланаОбмена].Состав.Найти(ТекСсылка.Метаданные()) = Неопределено тогда
Продолжить;
КонецЕсли;
ОбъектПоСсылке = ТекСсылка.ПолучитьОбъект();
ОбъектПоСсылке.ДополнительныеСвойства.Вставить("РегистрироватьОбмен", истина);
ПланыОбмена.ЗарегистрироватьИзменения(ПОСсылка, ОбъектПоСсылке);
КонецЦикла;
ИначеЕсли Не Объект.ДополнительныеСвойства.Свойство("РегистрироватьОбмен") Тогда
МассивУзловРезультат.Удалить(МассивУзловРезультат.Найти(ПОСсылка));
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Также создана простая дополнительная процедура, которая "собирает" все подчиненные ссылки объекта в массив
// собирает рекурсивно ссылки из объекта "ОбъектИлиСсылка" в массив "МассивСсылок"
Процедура ПолучитьСсылкиВнутриОбъекта(ОбъектИлиСсылка, МассивСсылок)
Если ОбщегоНазначения.ЭтоПеречисление(ОбъектИлиСсылка.Метаданные()) Тогда
Возврат
ИначеЕсли МассивСсылок.Найти(ОбъектИлиСсылка) <> Неопределено Тогда
Возврат
КонецЕсли;
МассивСсылок.Добавить(ОбъектИлиСсылка.Ссылка);
Для каждого ТекМД Из ОбъектИлиСсылка.Метаданные().Реквизиты Цикл
Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(ОбъектИлиСсылка[ТекМД.Имя])) И Не ОбъектИлиСсылка[ТекМД.Имя].Пустая() Тогда
ПолучитьСсылкиВнутриОбъекта(ОбъектИлиСсылка[ТекМД.Имя], МассивСсылок)
КонецЕсли;
КонецЦикла;
Для каждого ТекМДТЧ Из ОбъектИлиСсылка.Метаданные().ТабличныеЧасти Цикл
Для каждого ТекСтрока Из ОбъектИлиСсылка[ТекМДТЧ.Имя] Цикл
Для каждого ТекМД Из ОбъектИлиСсылка.Метаданные().ТабличныеЧасти[ТекМДТЧ.Имя].Реквизиты Цикл
Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(ТекСтрока[ТекМД.Имя])) И Не ТекСтрока[ТекМД.Имя].Пустая() Тогда
ПолучитьСсылкиВнутриОбъекта(ТекСтрока[ТекМД.Имя], МассивСсылок)
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
3. Создание правил отправки данных. Все правила конвертации/отправки/получения данных находятся в модуле "МенеджерОбменаЧерезУниверсальныйФормат". Данный модуль содержит множество стандартных правил обмена - необходимо добавить к ним несколько "своих" правил конвертации. Новых правил можно выделить 3:
- Реализация товаров, услуг -> Поступление товаров,услуг
- Организации -> Контрагенты
- Контрагенты -> Организации
Для создания правил можно использовать конфигурацию "Конвертер 3.0", но в целом можно просто использовать функции из типового модуля МенеджерОбменаЧерезУниверсальныйФормат как шаблоны методом "копи-пасты".
В результате получилась область с набором процедур следующего вида: