.. _EDI: EDI ===== Основные принципы ------------------- Интеграция с ЭДО провайдерами построена на стандартном для микросервиса интеграций механизме - синхронизациях. Это означает, что у нас есть простой способ управлять состоянием интеграции с конкретным ЭДО провайдером в рамках настроенного ящика в ECOS посредством уже готового функционала (включение/выключение чекбоксами, сброс состояния при необходимости для старта интеграции с самого начала и тд). Перейдем к описанию самого функционала с указанием классов. Citeck синхронизации работают на механизме объявления реализации **SyncExecutionFactory**, которые поставляют реализации SyncExecution, в котором уже происходит шедулинг интеграции. В нашем случае, за это ответственны классы **EdiSyncExecutionFactory** и **EdiSyncExecution**. Работу **EdiSyncExecutionFactory** рассматривать не будем, так как кроме регистрации в **SyncService** и создания **EdiSyncExecution** - никакой работы он и не делает. Рассмотрим работу **EdiSyncExecution**: * Зашедулить джобу по настройкам. * В джобе - повесить лок с помощью ShedLock. Если смог повесить лок - работа продолжается. * Собирает данные для интеграции, ищет зарегистрированную для ЭДО-провайдера из настроек ящика реализацию интерфейса EdiEventsSyncService. Если не находит - сыпет исключения. Важно отметить, что реализаций **EdiEventsSyncService** в самом микросервисе integrations на самом деле нет, как они подключаются будет описано в разделе ниже. * Делегирует работу найденному EdiEventsSyncService, передавая ему собранные ранее данные + метод-колбек для обновления состояния синхронизации. То есть, по факту, особой работы EdiSyncExecution не делает, полезная работа выполняется за счет делегирования. Связь сервисов-реализации с EdiSyncExecution для интеграции ------------------------------------------------------------ Ответ довольно прост, существует общая либа *ecos-edi-commons*, в которую вынесены основные интерфейсы интеграции и структуры данных. Таким образом, удается связать решение на уровне интерфейсов (то есть, связь такая, что интерфейс используется в микросервисе integrations, а реализация идет в сторонних либах). Ок, с этим разобрались, что-то реализуется, а как микросервис то получит это, если он этих зависимостей даже не имеет? Тут ответ уже сложнее. Решение основано на загрузке кода библиотек в микросервис в виде OSGi бандлов. Для более подробного изучения этого - можно почитать статью :ref:`Функционал загрузки OSGI пакетов` (и рекомендованные статьи), а так же пример загрузки либы контур для этих целей - :ref:`Настройка получения событий с ящиком Контур_Диадок` Рассмотрим что именно за интерфейсы и сервисы определены в ecos-edi-commons либе: * **EdiEventsSyncService** - интерфейс, в который делегируется вся интеграция с ЭДО-провайдером. * **EdiEventsSyncServiceResolver** - класс, в котором регистрируются EdiEventsSyncService по связке **"ЭДО-провайдер - Сервис"** при загрузке бандла, предназначенного для интеграции с каким-то ЭДО-провайдером. Содержится в микросервисе в виде бина. * **EdiBoxService** - интерфейс для получения информации о ящике. Расширяется в основном коде микросервиса в виде бина. * **EdiApiService** - интерфейс для общения с ЭДО провайдером. Содержит методы для всех операций с ЭДО (или почти все). * **EdiApiServiceResolver** - класс, в котором регистрируются EdiApiService по связке **"ЭДО-провайдер - Сервис"** при загрузке бандла, предназначенного для интеграции с каким-то ЭДО-провайдером. Содержится в микросервисе в виде бина. * **EdiService** - Класс, который содержит те же методы, что и в EdiApiService, за исключением того, что в каждый метод дополнительно передается параметр EdiProviderType. По сути, является композитным EdiApiService. Делегирует логику в конкретный EdiApiService, полученный по связке с EdiProviderType из EdiApiServiceResolver. * **EdiGenerator + дочерние интерфейсы** - интерфейсы для расширения возможностей генерации контента в ЭДО провайдерах. К примеру, может быть 2 реализации генерации печатной формы: через вызов API генерации ПФ в сервисах диадока (удаленная генерация) или генерация силами ECOS (локальная). Регистрируется в EdiGeneratorResolver. * **EdiGeneratorResolver** - класс для регистрации EdiGenerator реализаций по составному ключу **"Эдо-провайдер+Тип-генератора+вид-генератора"**, где Эдо-провайдер - Контур или Корус, Тип генератора - Генерация печатной формы или Генерация титула покупателя, Вид генератора - Произвольная строка с символизирующая вид. Обычно, что то вроде "локальная генерация" или "генерация по API". * **EdiStateService** - сервис для отправки событий на обработку после получения и первичной обработки их в либе (будет рассмотрено ниже). Примерное взаимодействие сервисов можно изучить подробнее на `drawIO `_ диаграмме: `edi_services `_ Что происходит в либах обработки и что за зверь - EdiStateService ------------------------------------------------------------------- Либы не обрабатывают события. Они их получают исходя последнего обработанного события (хранящегося в состоянии синхронизации), составляют универсальную структуру Event, хранящуюся в либе *ecos-edi-commons* и после этого отправляет эту структуру в EdiStateService. Структуры в *ecos-edi-commons* можно посмотреть в следующей диаграмме `drawIO `_ : `edi_structures `_ EdiStateService - класс в ecos-edi-commons, который отправляет события по определенному endpoint внутри camel контекста. CamelContext отправителя и CamelContext получателя события - как правило, разные контексты. Подобная передача осуществляется использованием эндпоинта direct-vm типа, а не простого direct. Таким образом, происходит следующее взаимодействие: .. image:: _static/EDI/integration_EDI_1.png :width: 800 :align: center :alt: Integration EDI где указано по шагам: - **1** - Отправляется запрос выполнить интеграцию через Контур (или иной другой вариант ЭДО-провайдера), для какого-то ящика, от такого то события (вызов EdiEventsSyncService). - **2** - В случае найденных событий - трансформирует их в структуру Event и через EdiStateService отправляет сообщение в Camel из контекста Camel микросервиса интеграций. - **3** - Camel контекст микросервиса интеграций отправляет сообщение с Event в CamelContext внутри VM, в котором зарегистрирован указанный эндпоинт. На скриншоте указано, что мы используем еще какой-то customer-lib со своим camel контекстом, но такая кастомизация нужна не всегда, в общем случае - будет использоваться сразу переход в ecos-lib. - **4** - После выполнения каких-то работа в customer-lib роутах - они отправляют сообщение в CamelContext либы ecos-lib. Там происходит обновление документов, подписей и тд в альфреско путем вызовов Records API. Стоит уточнить еще раз, customer-lib и ecos-lib - отдельные OSGi бандлы, включенные в микросервис после его старта, которые создают и стартуют Camel контекст, на роутах которого возложена связь между ними. Обязательно нужно соблюдать контракт по именованию endpoint. Структура Event ---------------- Event - обычный POJO, с сеттерами, геттерами, equals и тд. Однако, заполнение Event носит определенный характер. Внутри него ДОЛЖНЫ содержаться все документы, состояния которых изменены в рамках данного события. Это означает, что если обрабатываем событие "Документ подписан", то это означает, что должна прийти не просто подпись, а еще и информация о документе с АКТУАЛЬНЫМ статусом. Другая ситуация, если по документу типа УПД пришла корректировка УКД - это означает, что в рамках этого события придет не только УКД, но и информация о текущем новом состоянии УПД (только статус). Неизменившиеся поля, вроде контента или основанных на контенте формализованных атрибутах, которые могут быть тяжелыми при транспортировании - опускаются.