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





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

Обмен через универсальный формат широко используется в типовых конфигурациях. Для ознакомления есть хорошая статья //infostart.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-файл, среди узлов которого присутствует некий документ "Поступление товаров и услуг" с номером и товарами выгруженного документа-реализации:

 

12 Comments

  1. shutilin

    «Но что делать, если в компании участвуют несколько баз данных — стандартных, самописных (неважно), между которыми идет активный обмен данными EnterpriseData — и на каждый узел обмена могут действовать свои специфические правила?»

    Обычно в таких случаях модуль обмена помещаем в модуль внешней обработки,

    и при настройке обмена указываем путь к ней. Разве так не проще?

    Reply
  2. artkor

    Изначально так и делалось, только с отладкой «замучался» — пока не знаю способа отладки внешней обработки в режиме «Подключить». Принцип одинаковый, но имхо через расширение в разы удобнее делать, если совместимость конфы позволяет 🙂

    Reply
  3. acanta

    Я тоже с этим столкнулась. Не понимаю, почему в узел нельзя добавить какой нибудь реквизит, чтобы обозначить по какой конвертации он работает — 2й или 3ей?

    План обмена полный может быть один (регистрируются все). А узлы по одному переводить правильнее (разные релизы периферийных баз могут же быть).

    Reply
  4. MaxS

    (2) В этой статье указана ссылка на статью, где описано как отлаживать внешние обработки с правилами. 😉

    Reply
  5. Leits

    (1) мне на партнерском портале отвечали что в новых версия так уже не прокатит — типа юзайте расширения 🙂

    Reply
  6. kolya_tlt

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

    Reply
  7. KRIHA

    Подскажите пожалуйста, в

    Процедура РасшОбмен_ВыполнитьПравилаРегистрацииОбъектовДляПланаОбмена(МассивУзловРезультат, Объект, ИмяПланаОбмена, ДополнительныеПараметры)

    в месте:

    Для каждого ТекСтрока Из Объект.Товары Цикл
    МассивСсылок.Добавить(ТекСтрока.Номенклатура);
    ПолучитьСсылкиВнутриОбъекта(ТекСтрока.Номенклатура.Родитель, МассивСсылок);
    Если Не ТекСтрока.Упаковка.Пустая() Тогда
    МассивСсылок.Добавить(ТекСтрока.Упаковка);
    КонецЕсли;
    КонецЦикла;
    
    
    ПолучитьСсылкиВнутриОбъекта(ТекСтрока.Номенклатура.   ->Родитель<-    , МассивСсылок);
    

    Показать

    в чем смысл этой строки?

    Reply
  8. artkor

    (7) Цель — собрать все ссылки внутри номенклатуры, чтобы в приемнике не было «сюрпризов» вида «<Объект не найден…>» внутри карточки товара и всех объектов по цепочке. Возможно там ошибка в коде «ТекСтрока.Номенклатура.Родитель», а надо просто «ТекСтрока.Номенклатура», спасибо что заметили 😉 надо в рабочем проекте проверить…

    Reply
  9. KRIHA

    да, я про «родителя» и написал ))

    Reply
  10. KRIHA

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

    КомпонентыОбмена.УзелКорреспондента.Код равен «90af25b2-c4cc-4890-a62a-418ec3a70977», и до буквенного префикса (в отладчике смотрю) — даже не знаю как к нему подобраться.

    Reply
  11. artkor

    (10) Обычно все безвыходные ситуации в новых «конфах» на 8.3.10 и выше решаю расширениями: можно и процедуры переопределить и нужные реквизиты на форму выложить…

    Reply
  12. KRIHA

    да обойти понятно как — по наименованию тому же — суть не в этом — поменялась там логика немного — ымей ввиду )

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *