Обмен через универсальный формат. Пример нестандартной конвертации данных

Обмен - Обмен через XML

В статье описан небольшой пример обмена данными через EnterpriseData без снятия конфигурации с поддержки. Тестовая площадка: Управление торговлей, редакция 11 (11.4.3.126), версия платформы 8.3.11

Обмен через универсальный формат широко используется в типовых конфигурациях. Для ознакомления есть хорошая статья //softproc.ru/public/695523/, также множество различных курсов, в которых разложены основные моменты по работе с правилами конвертации, синхронизации объектов метаданных.

Основной принцип создания "нестандартных" правил обмена заключается в доработке модуля "МенеджерОбменаЧерезУниверсальныйФормат" (в различных конфигурациях название может немного отличаться). Но что делать, если в компании участвуют несколько баз данных - стандартных, самописных (неважно), между которыми идет активный обмен данными EnterpriseData - и на каждый узел обмена могут действовать свои специфические правила?

В данном случае удобно использовать механизм расширений конфигурации - и если требуется организовать специфичные правила обмена, тогда в конфигурации создается отдельное расширение о обмену.

Рассмотрим пример передачи данных из базы УТ 11.3 в идентичную по структуре базу данных "Дочерняя УТ 11.3". 

Постановка задачи: в основной базе данных производятся продажи товаров специфическому контрагенту, который является "дочерней фирмой" по отношению к основной. Необходимо реализовать "одностороннее" правило обмена "Реализации товаров и услуг -> Поступления товаров и услуг" по контрагенту с фиксированным ИНН.

Сокращения:

ЦБ - база-источник УТ 11.3, из которой идет выгрузка документов "Реализации товаров и услуг"

УТ - база приемник, в которой при обмене создаются "Поступления товаров"

ED - универсальный обмен (EnterpriseData)

В базе ЦБ создаются и проводятся "Реализации товаров" - и после проведения регистрируются в обмене ED, далее происходит обмен (через фоновое задание, либо вручную через каталог обмена). В при этом документ "Реализация товаров" должен "превратиться" в "Поступление товаров и услуг", а контрагент и организация "поменяться местами".

Как настраивать синхронизацию данных по плану обмена описано не будет - для этого существует множество различных статей. Переходим непосредственно к созданию правил обмена.

Предположим, что у нас настроен обмен, при котором главный узел организации-источника имеет код "ЦБ", а узел приемника код "УТ".

База-источник:

База-приемник:

Для начала создадим расширение конфигурации: назовем его, для примера "РасширениеОбмен" - и добавим модули, которые нам нужны для решения задачи.

1.Установка активного узла обмена в параметре сеанса. К сожалению, в процессе обмена не всегда можно получить активный узел, для которого происходит обмен. В процессе самого обмена данными структура данных "КомпонентыОбмена", содержащая все настройки обмена ED (в том числе ссылку на узел обмена) доступна не в каждой процедуре при обмене данными: например, при непосредственном заполнении перечня правил обмена "МенеджерОбменаЧерезУниверсальныйФормат.ЗаполнитьПравилаОбработкиДанных" этой переменной в параметрах нет.

На этапе инициализации обмена данными установим код узла обмена в параметры сеанса:

&Перед("ИнициализироватьТаблицыПравилОбмена")
Процедура РасшОбмен_ИнициализироватьТаблицыПравилОбмена(КомпонентыОбмена) Экспорт
	
	Если КомпонентыОбмена.УзелКорреспондента <> Неопределено Тогда
	
		Буф = Новый Структура(ПараметрыСеанса.БуферОбмена);
		Буф.Вставить("КомпонентыОбмена_УзелКорреспондента_Код", КомпонентыОбмена.УзелКорреспондента.Код);
		ПараметрыСеанса.БуферОбмена = Новый ФиксированнаяСтруктура(Буф);
	
	КонецЕсли;
	
КонецПроцедуры

 

2. Регистрация объектов. Также необходимо выделить перечень объектов, необходимых для регистрации в нужном нам узле универсального обмена. Это можно сделать, отредактировав правила регистрации объектов с использованием конфигурации "Конвертер 2.1", но в случае с расширением достаточно переопределить работу функции, разбирающей правила регистрации. В задании для нашего узла обмена нам нужны совсем "немногие" ссылки на объекты, остальное необходимо "отсечь".

Регистрироваться будет документ "Реализации товаров и услуг" и некоторые входящие в него ссылки: организация, контрагент, валюта, склад.

 
Код изменения правил регистрации объектов

Также создана простая дополнительная процедура, которая "собирает" все подчиненные ссылки объекта в массив

 
 Процедура сбора подчиненных ссылок объекта

3. Создание правил отправки данных. Все правила конвертации/отправки/получения данных находятся в модуле "МенеджерОбменаЧерезУниверсальныйФормат". Данный модуль содержит множество стандартных правил обмена - необходимо добавить к ним несколько "своих" правил конвертации. Новых правил можно выделить 3:

  • Реализация товаров, услуг -> Поступление товаров,услуг
  • Организации -> Контрагенты
  • Контрагенты -> Организации

Для создания правил можно использовать конфигурацию "Конвертер 3.0", но в целом можно просто использовать функции из типового модуля МенеджерОбменаЧерезУниверсальныйФормат как шаблоны методом "копи-пасты".

В результате получилась область с набором процедур следующего вида:

 
Функционал новых правил отправки объектов

4. Создание правил получения данных. На каждое правило отправки данных должно быть введено хотя бы одно правило получения: выгруженный файл нужно каким-то образом загрузить в приемник.

Для создания правил получения можно воспользоваться конвертером 3.0, можно написать правила вручную (используя существующие примеры в модуле обмена).

 

4.1. Правило получения документа "Поступление товаров и услуг". В 1-ю очередь "разберемся" с основным правилом получения документа. Вариант идентификации тут подойдет "ПоУникальномИдентификатору", также необхдимы некоторые программные доработки по установке свойств из входящих данных. Например, "Номер входящего документа" в поступлении должен быть равен номеру реализации, также нужно указать вид операции поступления итд...

 
 Код получения Поступления товаров,услуг

4.2. Правила получения контрагентов, организаций. На данном этапе сталкиваемся с 2-мя проблемами: 

  • Типовые функции модуля "МенеджерОбменаЧерезУниверсальныйФормат" конфликтуют с функциями, которые создаются в расширении. Если для организации или контрагента уже существует хотя бы одно  правило обмена - то система при получении найдет именно его и будет его использовать при конвертации. Нам это не подходит - тем самым необходимо программно удалять,либо изменять типовые правила получения.

  • Все (или почти все) типовые правила получения данных имеют вариант идентификации объектов "ПоУникальномуИдентификатору", что зачастую не подходит для решения задач обмена. В нашем примере в базах данных проводился независимый учет данных - тем самым при первом же обмене получим дублирование организаций, контрагентов итд...

Определим порядок поиска контрагентов и организаций: вариант идентификации "ПоПолямПоиска" и поля поиска "ИНН,КПП". Код обработки получения организаций, контрагентов примерно следующий:

 
 Код правил получения организаций и контрагентов

4.3. Прочие правила получения. Проблема идентификации остается актуальной и для прочих ссылочных объектов: нам не нужны дубли номенклатуры итд... Для остальных объектов решено использовать вариант синхронизации "СначалаПоУникальномуИдентификаторуПотомПоПолямПоиска" - в этом случае идет поиск сначала по идентификатору, потом по полям поиска (если по идентификатору) не найдено. Также при этом используется специальный регистр соответствий ссылок, в котором можно задать соответствия ссылок объектов (подробно углубляться не будем, есть курсы и статьи, в которых это описано).

 
 Код изменения типовых правил получения данных

5. Служебные функции по обмену данными. Чтобы указанные изменения были инициализированы - нужно доработать типовые функции по заполнению правил, отработке алгоритмов итд..., иначе вышеописанные изменения не будут работать. Если вы используете конфигурацию "Конвертация данных 3.0" - то служебные функции будут автоматически созданы вместе с правилами конвертации и отправки, но можно без особого труда написать функции вручную (в нашем примере нестандартных правил немного).

Код дозаполнения правил конвертации:

&После("ЗаполнитьПравилаКонвертацииОбъектов")
Процедура РасшОбмен_ЗаполнитьПравилаКонвертацииОбъектов(НаправлениеОбмена, ПравилаКонвертации) Экспорт
	
	//фильтр по узлам источника/применика
	Если ПараметрыСеанса.БуферОбмена.Свойство("КомпонентыОбмена_УзелКорреспондента_Код") Тогда
		Если НаправлениеОбмена = "Отправка" И ПараметрыСеанса.БуферОбмена.КомпонентыОбмена_УзелКорреспондента_Код = "УТ" Тогда
		ИначеЕсли НаправлениеОбмена = "Получение" И ПараметрыСеанса.БуферОбмена.КомпонентыОбмена_УзелКорреспондента_Код =  "ЦБ" Тогда
		Иначе
			Возврат
		КонецЕсли;
	КонецЕсли;

	Если НаправлениеОбмена = "Отправка" Тогда
		ДобавитьПКО_Документ_Расход_Приход(ПравилаКонвертации);
		ДобавитьПКО_Справочник_Контрагенты_Организации(ПравилаКонвертации);
		ДобавитьПКО_Справочник_Организации_Контрагенты(ПравилаКонвертации);
		
	ИначеЕсли НаправлениеОбмена = "Получение" Тогда
		ДобавитьПКО_Документ_Расход_Приход_Получение(ПравилаКонвертации);
		ИзменитьПКО_Справочники_Получение(ПравилаКонвертации);
		РасшОбмен_ДобавитьПКО_Справочник_Контрагенты_Получение(ПравилаКонвертации);
		РасшОбмен_ДобавитьПКО_Справочник_Организации_Получение(ПравилаКонвертации);
		
	КонецЕсли;
	
КонецПроцедуры

Код дополнения правил обработки данных:

&После("ЗаполнитьПравилаОбработкиДанных")
Процедура РасшОбмен_ЗаполнитьПравилаОбработкиДанных(НаправлениеОбмена, ПравилаОбработкиДанных) Экспорт
	
	//фильтр по узлам источника/применика
	Если ПараметрыСеанса.БуферОбмена.Свойство("КомпонентыОбмена_УзелКорреспондента_Код") Тогда
		Если НаправлениеОбмена = "Отправка" И ПараметрыСеанса.БуферОбмена.КомпонентыОбмена_УзелКорреспондента_Код = "УТ" Тогда
		ИначеЕсли НаправлениеОбмена = "Получение" И ПараметрыСеанса.БуферОбмена.КомпонентыОбмена_УзелКорреспондента_Код =  "ЦБ" Тогда
		Иначе
			Возврат
		КонецЕсли;
	КонецЕсли;
	
	Если НаправлениеОбмена = "Отправка" Тогда
		Если ПравилаОбработкиДанных.Колонки.Найти("ОчисткаДанных") = Неопределено Тогда
			ПравилаОбработкиДанных.Колонки.Добавить("ОчисткаДанных");
		КонецЕсли;
		
		ДобавитьПОД_Документ_Расход_Приход(ПравилаОбработкиДанных);
		ДобавитьПОД_Справочник_Контрагенты_Организации(ПравилаОбработкиДанных);
		ДобавитьПОД_Справочник_Организации_Контрагенты(ПравилаОбработкиДанных);
		
	ИначеЕсли НаправлениеОбмена = "Получение" Тогда
		//ПравилаОбработкиДанных.Удалить(ПравилаОбработкиДанных.Найти("Документ.ПоступлениеТоваровУслуг", "ОбъектВыборкиФормат"));

	КонецЕсли;
	
КонецПроцедуры

Выполнение спец.событий при обмене данными:

#Область ОбщегоНазначения
// Процедура-обертка, выполняет запуск указанной в параметрах процедуры модуля менеджера обмена через формат.
//
// Параметры:
//  ИмяПроцедуры - строка.
//  СтруктураПараметров - структура, содержащая передаваемые параметры.
&После("ВыполнитьПроцедуруМодуляМенеджера")
Процедура Расш_ВыполнитьПроцедуруМодуляМенеджера(ИмяПроцедуры, Параметры) Экспорт
	
	Если ИмяПроцедуры = "ПКО_Документ_Расход_Приход_ПриОтправкеДанных" Тогда 
		ПКО_Документ_Расход_Приход_ПриОтправкеДанных(
			Параметры.ДанныеИБ, Параметры.ДанныеXDTO, Параметры.КомпонентыОбмена, Параметры.СтекВыгрузки);
	ИначеЕсли ИмяПроцедуры = "ПКО_Документ_Расход_Приход_Получение_ПриКонвертацииДанныхXDTO" Тогда 
		ПКО_Документ_Расход_Приход_Получение_ПриКонвертацииДанныхXDTO(
			Параметры.ДанныеXDTO, Параметры.ПолученныеДанные, Параметры.КомпонентыОбмена);
		КонецЕсли;
		
КонецПроцедуры

#КонецОбласти

 

На этом доработки правил обмена практически завершены - осталось только очистить регистрацию выгруженных данных из узла плана обмена. В модуле "ОбменДаннымиXDTOСервер" допишем функцию по очистке регистрации, в случае если обмен был завершен без ошибок:

&После("ВыполнитьВыгрузкуЗарегистрированныхДанных")
Процедура РасшОбмен_ВыполнитьВыгрузкуЗарегистрированныхДанных_После(КомпонентыОбмена, НомерСообщения)
	
	Если КомпонентыОбмена.УзелКорреспондента.Код = "УТ" Тогда
		Если СокрЛП(КомпонентыОбмена.СостояниеОбменаДанными.РезультатВыполненияОбмена) <> "Ошибка" тогда
			ПланыОбмена.УдалитьРегистрациюИзменений(КомпонентыОбмена.УзелКорреспондента);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

 

Завершающим шагом в режиме Конфигуратора добавляем в обе базы данных созданное расширение - оно должно работать как в источнике, так и в приемнике.

После создания расширения для начала можно "потестировать" обмен в режиме выгрузки файла в каталог, чтобы сразу не использовать прямое подключение к другой базе (вдруг на этапе выгрузки какие-то ошибки вскроются). Для примера проведем некий документ "реализации товаров и услуг" - после чего он должен появиться в списке зарегистрированных изменений для узла обмена "УТ":

После этого проводим синхронизацию данных: в результате в каталоге обмена должен появиться xml-файл, среди узлов которого присутствует некий документ "Поступление товаров и услуг" с номером и товарами выгруженного документа-реализации:

 

См. также

Комментарии
Сортировка: Древо
1. epresnyakova 19.06.18 09:21 Сейчас в теме
"Но что делать, если в компании участвуют несколько баз данных - стандартных, самописных (неважно), между которыми идет активный обмен данными EnterpriseData - и на каждый узел обмена могут действовать свои специфические правила?"

Обычно в таких случаях модуль обмена помещаем в модуль внешней обработки,
и при настройке обмена указываем путь к ней. Разве так не проще?
Alien_job; +1 Ответить
2. artkor 41 19.06.18 09:36 Сейчас в теме
Изначально так и делалось, только с отладкой "замучался" - пока не знаю способа отладки внешней обработки в режиме "Подключить". Принцип одинаковый, но имхо через расширение в разы удобнее делать, если совместимость конфы позволяет :)
Alien_job; +1 Ответить
4. MaxS 1112 19.06.18 15:47 Сейчас в теме
(2) В этой статье указана ссылка на статью, где описано как отлаживать внешние обработки с правилами. ;)
3. acanta 44 19.06.18 11:33 Сейчас в теме
Я тоже с этим столкнулась. Не понимаю, почему в узел нельзя добавить какой нибудь реквизит, чтобы обозначить по какой конвертации он работает - 2й или 3ей?
План обмена полный может быть один (регистрируются все). А узлы по одному переводить правильнее (разные релизы периферийных баз могут же быть).
Оставьте свое сообщение