Используем механизмы обмена данными БСП для произвольного обмена





Механизм БСП заточен на обмен XML по правилам обмена. Чтобы использовать его для любого другого обмена, коих в мире немало, требуются доработки. В статье описан вариант, как из положения выйти.

    Столкнулся давеча с проблемой: необходимо реализовать обмен данными через ftp. Причём хотелось использовать механизм БСП, чтобы не городить свои велосипеды. Казалось бы, для этого стоит только почитать документацию с ИТС, но не всё так просто. Механизм БСП заточен на обмен XML по правилам обмена. Чтобы использовать его для любого другого обмена, коих в мире не мало, требуются доработки. В статье описан вариант, как из положения выйти (так сказать, и рыбку съесть и косточкой не подавиться и формат обмена использовать произвольный и стандартным механизмом нагло воспользоваться).

    Ещё раз уточню. Здесь по сути нет инфы с ИТС, т.к. статья описывает использование механизмов БСП для произвольного обмена. Для обмена в формате XML по правилам обмена надо читать ИТС.

Какие возможности обмена БСП мы можем использовать:

Для начала стоит отметить, какие же такие типовые возможности я позарился использовать. Речь идёт о справочнике СценарииОбменовДанными.

Где можно прописать параметры обмена данными:

  • действие — выгрузка или загрузка
  • подключение — каталог или FTP или EMAIL или веб сервис или COM подключение (хранится это в РС «НастройкиТранспортаОбмена», значит нам не надо думать, где хранить эти данные)
  • расписание — расписание РЗ (значит не надо добавлять своё)

Вдобавок нам не надо создавать форму, на которой можно задавать все эти настройки и  имеются доп. возможности:

  • выполнить сценарий обмена прямо сейчас
  • Открыть журнал регистрации с отбором по событию обмена

Более подробно, о том, как сие выглядит в режиме предприятия написано ниже, в инструкции для пользователя.

Какие требуются доработки:

1. Добавить План обмена. Даже если он не нужен. Ибо без него ничего не взлетит. Это требование БСП. В модуль менеджера добавить следующий код, скопировав из типовых или взяв с ИТС. Естественно добавив только те виды транспорта, которые могут использоваться в вашем обмене. На всякий случай укажу, что вид «FILE» — это обмен через каталог.

Функция ИспользуемыеТранспортыСообщенийОбмена() Экспорт
Результат = Новый Массив;
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FILE);
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FTP);
Возврат Результат;
КонецФункции  

2. Переопределить механизм обмена БСП. Для этого нам любезно предназначен специальный ОМ ОбменДаннымиПереопределяемый. В зависимости от задачи, нам нужна одна из двух (или сразу обе) процедур этого ОМ — ПриЗагрузкеДанных или ПриВыгрузкеДанных. Для нового обмена в означенные процедуры необходимо добавить следующий текст:

в ПриЗагрузкеДанных

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

в ПриВыгрузкеДанных

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

Также в модуль добавляем блок методов УниверсальныйОбменДаннымиСПомощьюБСП

#Область УниверсальныйОбменДаннымиСПомощьюБСП

//Если обмен инициализирован справочником СценарииОбменовДанными
//
Процедура ПриВыгрузке(СтандартнаяОбработка, Получатель, ИмяФайлаСообщения, ДанныеСообщения,
КоличествоЭлементовВТранзакции, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов) Экспорт
//КоличествоОтправленныхОбъектов - сюда можно присвоить количество выгруженного, которое потом запишется в ЖР
//ИмяСобытияЖурналаРегистрации - его использует БСП при записи в ЖР,
//нам надо делать также, чтобы удобно смотреть ЖР из сценария тестирования

//Планы обмена фиктивные, поэтому СтандартнаяОбработка не требуется
СтандартнаяОбработка = Ложь;

//Типовой механизм сам задаёт имя файла выгрузки и формат у него может быть только XML (так выглядит имя - Message_1_2.xml),
//поэтому,если мы хотим это переопределить, надо получить настройки обмена (такие, как каталог обмена или ftp)
НастройкиТранспорта = НастройкиТранспортаУзла(Получатель, Перечисления.ДействияПриОбмене.ВыгрузкаДанных);
//в структуре НастройкиТранспорта лежат настройки из РС НастройкиТранспортаОбмена. Присутствуют не все поля РС, а только те,
//которые соответствуют выбранному в сценарии обмена виду транспорта обмена (см. Перечисления.ДействияПриОбмене)

//ТЕЛО ВЫГРУЗКИ
//здесь мы знаем куда выгружать и описываем код выгрузки
ОбщегоНазначения.МенеджерОбъектаПоСсылке(Получатель).ПриВыгрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов);

//эта строка выполняется в самом конце, если выгрузка прошла успешно
СоздатьФайлВыгрузкиЗаглушкуДляОбменаНаБСП(ИмяФайлаСообщения);
КонецПроцедуры

//Если обмен инициализирован справочником СценарииОбменовДанными
//
Процедура ПриЗагрузке(СтандартнаяОбработка, Отправитель, ИмяФайлаСообщения, ДанныеСообщения,
КоличествоЭлементовВТранзакции, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов) Экспорт
СтандартнаяОбработка = Ложь;
НастройкиТранспорта = НастройкиТранспортаУзла(Отправитель, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);

//ТЕЛО ЗАГРУЗКИ
//здесь мы знаем откуда загружать и описываем код загрузки
ОбщегоНазначения.МенеджерОбъектаПоСсылке(Отправитель).ПриЗагрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов);
КонецПроцедуры

Процедура СоздатьФайлВыгрузкиЗаглушкуДляОбменаНаБСП(ИмяФайлаСообщения)
//Чтобы типовой механизм понял, что выгрузка данных произошла,
//надо заполнить типовой файл выгрузки содержимым.
ЗаписьХМЛ = Новый ЗаписьXML;
ЗаписьХМЛ.ОткрытьФайл(ИмяФайлаСообщения);
ТекстЗаглушка = "Этот файл создаётся типовым механизмом обмена БСП. Его следует игнорировать. Можно удалять.";
ЗаписьХМЛ.ЗаписатьНачалоЭлемента("Данные");
ЗаписьХМЛ.ЗаписатьТекст(ТекстЗаглушка);
ЗаписьХМЛ.ЗаписатьКонецЭлемента();
ЗаписьХМЛ.Закрыть();
КонецПроцедуры

Функция НастройкиТранспортаУзла(Узел, ВыполняемоеДействие)
//к сожалению, здесь мы не имеем ссылки на сценарий обмена, откуда он и был запущен,
//а она нужна, чтобы определить ВидТранспортаОбмена, т.е. понять куда выгружать (в каталог, или ftp, или ещё куда)
//есть несколько вариантов решить эту задачу и все "кривые":
//
//1. в модуле менеджера ПО, в функции ИспользуемыеТранспортыСообщенийОбмена() разрешить только один ВидТранспортаОбмена
//2. сделать ВидТранспортаОбмена равным РегистрыСведений.НастройкиТранспортаОбмена.ВидТранспортаСообщенийОбменаПоУмолчанию(...),
//но тогда настройка транспорта в сценарии обмена станет фиктивной, что приведёт к непониманию со стороны пользователей
//(ВидТранспортаСообщенийОбменаПоУмолчанию задаётся в предприятии в настройках плана обмена)
//3. Для СОВОКУПНОСТИ (УЗЕЛ нашего ПО + выполняемое действие (загрузка или выгрузка))
//ограничить возможность использования сценариев для обмена одним сценарием.
//Если их будет создано больше - отменять обмен. Если найден один - брать ВидТранспортаОбмена оттуда.
//
//Здесь реализован лучший, на мой взгляд, третий путь. Таким образом, мы получим одно ограничение:
//чтобы выполнять несколько сценариев с данным обменом и выполняемым действием (загрузка или выгрузка),
//нужно на каждый новый сценарий создавать копированием узел ПО (на всякий случай уточню: в режиме предприятия)
//но для подавляющего большинства хватит и одного сценария (ведь возможность их множественности, это фича БСП).

Запрос = Новый Запрос;
Запрос.Текст =
//поскольку помеченный на удаление сценарий всё равно можно выполнять, отбирать в запросе только непомеченные нельзя
"ВЫБРАТЬ
| СценарииОбменовДаннымиНастройкиОбмена.ВидТранспортаОбмена
|ИЗ
| Справочник.СценарииОбменовДанными.НастройкиОбмена КАК СценарииОбменовДаннымиНастройкиОбмена
|ГДЕ
| СценарииОбменовДаннымиНастройкиОбмена.УзелИнформационнойБазы = &УзелИнформационнойБазы
| И СценарииОбменовДаннымиНастройкиОбмена.ВыполняемоеДействие = &ВыполняемоеДействие";
Запрос.УстановитьПараметр("УзелИнформационнойБазы", Узел);
Запрос.УстановитьПараметр("ВыполняемоеДействие", ВыполняемоеДействие);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Количество() > 1 Тогда
//Вызывающая процедура обработает исключение и запишет его в ЖР
ВызватьИсключение "Для узлов данного плана обмена нельзя задавать больше чем по одному сценарию обмена!!!";
ИначеЕсли Выборка.Количество() = 0 Тогда
//вообще, здесь мы не можем оказаться, но на всякий случай
ВызватьИсключение "Не найден сценарий обмена для данного узла обмена";
КонецЕсли;
Выборка.Следующий();
НастройкиТранспорта = РегистрыСведений.НастройкиТранспортаОбмена.НастройкиТранспорта(Узел, Выборка.ВидТранспортаОбмена);

Возврат НастройкиТранспорта;
КонецФункции

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

Сами процедуры обмена данными находятся в модуле менеджера плана обмена. Таким образом, шаблон модуля менеджера ПО будет выглядеть так:

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ПрограммныйИнтерфейс

#Область ПроцедурыИФункцииБсп

// Возвращает массив используемых транспортов сообщений для этого плана обмена
//
// 1. Например, если план обмена поддерживает только два транспорта сообщений FILE и FTP,
// то тело функции следует определить следующим образом:
//
// Результат = Новый Массив;
// Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FILE);
// Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FTP);
// Возврат Результат;
//
// 2. Например, если план обмена поддерживает все транспорты сообщений, определенных в конфигурации,
// то тело функции следует определить следующим образом:
//
// Возврат ОбменДаннымиСервер.ВсеТранспортыСообщенийОбменаКонфигурации();
//
// Возвращаемое значение:
//  Массив - массив содержит значения перечисления ВидыТранспортаСообщенийОбмена
//
Функция ИспользуемыеТранспортыСообщенийОбмена() Экспорт

Результат = Новый Массив;
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FILE);
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FTP);
Возврат Результат;

КонецФункции

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

#Область ВыгрузкаЗагрузкаЭкспортныеМетоды

//Вызывается из _омОбмен.ПриВыгрузке
//
Процедура ПриВыгрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов) Экспорт

КонецПроцедуры

//Вызывается из _омОбмен.ПриВыгрузке
//
Процедура ПриЗагрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов) Экспорт

КонецПроцедуры

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

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


#Область Выгрузка

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

#Область Загрузка

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

#КонецЕсли

Ограничения, особенности использования нашего механизма:

  1. Для СОВОКУПНОСТИ (УЗЕЛ нашего ПО + выполняемое действие (загрузка или выгрузка)) можно задать только один сценарий. Если необходимо больше, то, на каждый новый сценарий надо создавать копированием узел ПО (на всякий случай уточню: в режиме предприятия), но для подавляющего большинства хватит и одного сценария (ведь возможность их множественности, это фича БСП).
  2. В папке обмена будет находиться один лишний файл или (в случае «2.в») придётся смириться с типовым именем файла. Но это тоже легко пережить =)
    1. а) Выгрузка. В папке выгрузки автоматом создаётся ненужный файл «Message_1_2.xml» с текстом «<Данные>Этот файл создаётся типовым механизмом обмена БСП. Его следует игнорировать. Можно удалять.</Данные>»
    2. б) Загрузка. В папку загрузки надо кинуть файл «Message_2_1.xml». Можно поместить в него следующий текст: «<Данные>ФАЙЛ НЕ УДАЛЯТЬ!! Без него него не будет работать механизм загрузки на БСП.</Данные>».
    3. в) Если выгрузка в ХМЛ, то можно обойтись без минусов 1 и 2, больше используя механизм БСП. Поскольку БСП как раз рассчитана именно на выгрузку в ХМЛ, то здесь лишних хлопот не требуется и мы можем прямо в ПриВыгрузкеДанных писать файл выгрузки (т.е. блок методов УниверсальныйОбменДаннымиСПомощьюБСП тут не нужен). Пример, как это сделать см в процедуре СоздатьФайлВыгрузкиЗаглушкуДляОбменаНаБСП. Но, у данного решения есть один недостаток: Имя файла генерирует БСП («Message_1_2.xml», где «1» и «2» это коды узлов «откуда» и «куда» соответственно).

Особенности использования механизма БСП:

В предприятии надо создать два узла ПО, т.к. обмен с самим собой делать нельзя. Также обоим узлам надо задать Код, иначе обмен не взлетит. Данные проверки производятся в процедуре ОбменДаннымиСервер.ВыполнитьПроверкуСтруктурыОбменаНаВалидность.

Инструкция для пользователей:

В плане обмена создаём два узла. Узел Этой базы (у него на картинке зелёная точка справа внизу) и узел базы приёмника. Обязательно заполняем им код и наименование (для простоты можно назвать как на скрине «1» и «2»). Далее для обмена (выгрузки или загрузки) данными надо выбирать узел базы с которой идёт обмен, т.е. «2». Если выберем «1», то обмен проходить не будет а в ЖР появится запись «Нельзя организовать обмен данными с текущим узлом информационной базы. Обмен отменен.».

Спр. «Сценарии синхронизации данных».

Задаём имя сценария, добавляем строку настройки обмена в ТЧ.

Настраиваем параметры подключения.

После того, как всё настроено, можно настроить РЗ или выполнить обмен прямо сейчас.

После выполнения обмена, можно посмотреть его лог в ЖР.

ОпосляСкриптум:

Пришлось немного разобрать механизмы БСП, вследствие  чего родилась сия статья.  В сухом остатке мы имеем:

  • Чтобы использовать механизм обмена данными БСП для произвольного обмена, нужно просто скопировать описанные процедуры. Всё. Дальше можно заняться собственно самими процедурами обмена.
  • Также представлена инструкция для пользователей.

————————————

ИНТЕРЕСНЫХ ВАМ ЗАДАЧ, ПЛОДОТВОРНОЙ РАБОТЫ И ОРИГИНАЛЬНЫХ/ОПТИМАЛЬНЫХ РЕШЕНИЙ!!

21 Comments

  1. Поручик

    Полезная вещь.

    Reply
  2. sansys

    Спасибо за статью, очень помогла.

    Reply
  3. Патриот

    (2) sansys, на здоровье, рад, что мой труд помог ещё кому-то.

    (1) Поручик, ваш комментарий, похоже стал шикарнейшей рекламой для статьи =)

    Reply
  4. Dach

    Статья гуд. Кстати, вопрос с ВидомТранспорта можно решить, добавив в план обмена соответствующий реквизит. И для каждого узла заполнить его нужным образом. В этот узел будет через файл выгружаться, а вот в этот — веб-сервисом. Ну а в целом мне очень нравится, когда для нестандартных решений используется стандартный механизм.

    Reply
  5. Патриот

    (4) Dach, да, можно вид транспорта писать в реквизит плана обмена. Но у этого решения присутствует тот же минус, что и у одного из предложенных в статье. Цитирую: можно

    //2. сделать ВидТранспортаОбмена равным РегистрыСведений.НастройкиТранспортаОбмена.ВидТранспортаСообщенийОбменаПоУмолчанию(…),
    //но тогда настройка транспорта в сценарии обмена станет фиктивной, что приведёт к непониманию со стороны пользователей

    Вот если к вашему предложению добавить ещё пару строк кода в форму механизма БСП (при заполненном реквизите у ПО, брать вид транспорта из него, не давая возможности выбора пользователю), то получится уже действительно красиво! Вот только многие ли решатся внести правку в типовой механизм? Спасибо за идею. Попозже добавлю сей вариант в статью.

    Reply
  6. Dach

    (5) я это и имел ввиду. Можно создавать несколько сценариев данных, имя сценария должно быть строго определено; при выборе реквизита «ВидТранспорта» в узле плана обмена находить нужный сценарий и менять настройку там. Тогда не придется код БСП править. Ну примерно так, навскидку. Единственное, не особо надежно — если имя сценария кто-то поменяет, но сомневаюсь что кто-то полезет так глубоко

    Reply
  7. Патриот

    (6) Dach, если сделать, как вы предлагаете

    при выборе реквизита «ВидТранспорта» в узле плана обмена находить нужный сценарий и менять настройку там. Тогда не придется код БСП править.

    то при создании нового сценария, придётся перевыбирать «ВидТранспорта» в узле плана обмена, чтобы он проставился в сценарии, что не очень хорошо.

    Reply
  8. alest

    Поясните, пожалуйста, чем не угодил обмен по правилам. Какой «любой другой обмен» нельзя выполнить из модулей правил обмена?

    Reply
  9. Патриот

    (8) alest, вы прикалываетесь? Хотите сказать, что вам не известно, что кроме как в ХМЛ можно в любой другой формат выгружать (или из него загружать) данные? В зависимости от системы, с которой производится обмен и целей.

    Reply
  10. rozer

    (9) для этого 1с и придумала ED и КД3. Можно описать любую хмл-схему и xdto-пакет по ней или использовать стандартный от 1с…

    Reply
  11. Патриот

    (10) rozer, для чего для этого? Вам раз в день надо выгружать список сотрудников в CSV файл для пропускной системы. И кидать его на ФТП, откуда сторонняя система его заберёт и будет разрешать пропускать тех сотров, которые указаны в файле.

    Опишите, будьте добры,

    хмл-схему и xdto-пакет

    для решения этой задачи

    Reply
  12. rozer

    (11) пожалуйста http://v8.1c.ru/edi/edi_stnd/enterprisedata/1.0/#00000000055, в КД3 создается ПКО и ПОД за 3мин. В КД2 правила регистрации для физлиц еще 2 мин. И через 5мин. — вуаля у вас готов xml-файлик на ФТП. Осталось еще желание изобретать «велик» ?

    Reply
  13. Патриот

    (12) rozer, какая из букв

    CSV

    вам не понятна в названии формата, требуемого сторонней системой, разработчиком которой вы не являетесь?

    Reply
  14. kkkelena1963

    А мне статья очень понравилась! Спасибо большое.

    Reply
  15. Патриот

    (14) kkkelena1963, пожалуйста! А если вы ещё нажмёте на плюс статье, то это меня смотивирует написать ещё =)

    Reply
  16. rozer

    (13) все понял.Извиняюсь…

    Reply
  17. dvs69

    Спасибо за статью, доступно изложен материал, еще раз спасибо.

    Reply
  18. Makushimo

    А чем и с кем вы «нестандартно» обменивались в этой статье?

    В чем нестандартность вашей ситуации?

    Reply
  19. Патриот

    (18) Makushimo, нестандартность, с точки зрения разработчиков БСП состоит в том, что я грузил данные не в ХМЛ, а в любой другой формат, в зависимости от требований со стороны того, кому я данные выгружаю. Например в эксель или текст.

    Reply
  20. Makushimo

    (19) Патриот

    я понял.

    в статье это осталось за кадром.

    спасибо.

    Reply
  21. kembrik

    (15)

    Статья отличная, плюс поставил, пишите ещё! Воспользовался, чтобы убрать наконец «костыль» на обработках ожидания с выгрузкой в JSON

    Вдруг будете раздумывать над темой новой статьи — очень интересен вариант с доработкой «старой» конфы на БСП (Например УТ 11.0.9.9) до «необходимого минимума», позволяющего использовать обмен данными на основе ED и КД3 (вон выше вам про него напомнили)

    Reply

Leave a Comment

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