Отправка документов - Сценарии ExtSdk2
В СБИС отправка документов похожа на отправку письма электронной почты. Т.е. вы формируете письмо (пакет = комплект электронных документов = объект API документ) указываете от кого кому собираетесь отправить, заполняете тему письма (набор вспомогательных реквизитов - тип документа, регламент документооборота и т.п.), прикладываете к нему вложения (электронные документы) и нажимаете отправить. В зависимости от содержимого вашего письма и настроек СБИС дополнительно может потребоваться подписать или зашифровать вложения перед отправкой.
Поскольку многие информационные системы появилось задолго до электронного документооборота, то для тех из них, которые не умеют работать с JSON, BASE64, криптографией, шифрованием, HTTPS или делают это недостаточно эффективно – например работают исключительно синхронно (последовательно) в ExtSdk2 имеется набор вспомогательных инструментов помогающий решить эти проблемы.
Содержание
Отправка электронного документа
Отправка любого комплекта документов в СБИС (запуск в документооборот) состоит из 3 этапов:
- Запись документа в СБИС – на данном этапе в СБИС записываются все необходимые данные, файлов может быть много или они могут быть большие, поэтому эта операция может выполнятся за один или несколько вызовов.
- Подготовка действия – на данном этапе вы говорите СБИС, какое действие хотите сделать с документом, СБИС проверяет достаточность данных, выполняет вспомогательные операции (например дописывает в документы идентификаторы участников документооборота, переименовывает вложения в соответствии с требованиями формата), конвертирует XML в PDF для контрагентов в роуминге, определяет какие файлы необходимо подписать, какой подписью и в каком формате это требуется сделать. Данный этап является не обязательным и его можно пропустить в случаях если информационная система реализовала на своей стороне всю необходимую логику работы и её не требуется помощь.
- Выполнение действия на этом этапе в СБИС выполняет требуемую операцию (в нашем случае отправку), кроме этого на этом этапе в СБИС как правило загружаются подписи и недостающие файлы.
Для каждого из выше перечисленных этапов в ExtSdk2 есть отдельные методы, которые можно использовать для интеграции WriteDocument , PrepareAction , ExecuteAction .
Запись документа в СБИС
Результатом данной операции является созданный в одном из реестров СБИС объект Документ – карточка документа. Основными реквизитами Документа СБИС, определяющими его поведение в системе и атрибутный состав являются свойства «Тип» и «Регламент». Кроме этого к любому документу СБИС может быть прикреплено не ограниченное количество вложений (файлов) это могут быть как формализованные так и не формализованные документы любого размера. Загружать файлы вложения можно двумя способами:
Либо вызвав для каждого вложения отдельный метод записи WriteAttachment , либо передав данные вложения в метод записи документа WriteDocument .
Подготовка действия
Результатом данной операции является объект документ подготовленный к переходу на следующий этап документооборота. Метод PrepareAction .
Выполнение действия
Результатом данной операции является объект документ с выполненным действием для подготовленного документа к переходу на следующий этап документооборота. Метод ExecuteAction .
Комплексный метод отправки электронного документа
Дополнительно для облегчения интеграции в ExtSdk2 реализован комплексный метод, выполняющий несколько операций за один вызов - WriteDocumentEx выполняет WriteDocument + PrepareAction + ExecuteAction .
Массовая отправка электронных документов
Задача - максимально эффективно сформировать и отправить пакеты документов. Данный алгоритм предназначен для систем с синхронным исполнением кода, которые будут использовать ExtSdk2 через OLE объект.
Т.к. ExtSdk2 работает асинхронно алгоритм отправки для достижения максимального быстродействия (уменьшения ожиданий) более сложен в реализации, чем например алгоритм при отправке через SDK.
Сравнение подходов можно посмотреть на данной диаграмме. ... ссылка на схему..
Схема алгоритма отправки
На входе имеем список внутренних идентификаторов документов (ссылок), на основании которых хотим сформировать комплекты электронных документов (далее пакеты) для отправки и идентификатор настроек описывающих правила формирования пакета. Это может быть как список отмеченных пользователем записей, так и список полученный для автоматической операции.
Данный алгоритм желательно оформить в виде отдельного метода, каждый прямоугольник так же выделить в отдельный метод.
Ресурсы приемника документов в плагине и на сервисе СБИС ограничена, чтобы не создавать задержки из-за переполнения очереди, не потреблять лишние ресурсы по памяти, процессору, каналу и не получать ошибки истекшего таймаута (не усложнять алгоритм) отправка осуществляется параллельно в N потоков. Количество потоков по умолчанию равно 10, и может быть увеличено по обращению путем выделения дополнительных ресурсов.
Предполагается, что основную долю времени занимает отправка документов. Кратко алгоритм выглядит следующим образом: Интеграционный модуль передает документ на отправку как только появляется свободный поток. Пока все потоки заняты модуль подготавливает к отправке следующие документы - хранит в кэше однократный или двукратный (исходя из максимального количества потоков) запас документов. В оставшееся свободное время модуль получает события с результатами отправки, сохраняет для последующей обработки. Обновлением статусов у отправленных документов занимается по остаточному принципу.
Работа алгоритма предполагает, что для его работы будет создан объект контекста содержащий необходимые для работы алгоритма свойства:
- listLinks - Массив внутренних идентификаторов документов (ссылок), на основании которых хотим сформировать комплекты электронных документов
- countAll = Количество документов которые требуется отправить
- countThread - Количество потоков отправки
- countFreeThread = Количество свободных потоков отправки
- countSend - Количество документов по которым запущена процедура отправки
- countComplete - Количество документов по которым отправка завершена,
- countError - Количество ошибок
- countPrepare - Количество подготовленных к отправке документов
- cachePrepare - Массив с данными подготовленных к отправке документами (это данные которые просто достаточно передать методу отправки).
- cacheAnswer - Массив с результатами отправки
- callback - словарь с обработчиками которые необходимо позвать при получении события
sendDocFromCache
Берет первый документ из cachePrepare и вызывает метод отправки ExtSdk2.WriteDocumentEx.
Обновляет счетчики свободных потоков и количества подготовленных, отправленных документов.
регистрирует callback
def sendDocFromCache(self):
document = cachePrepare.pop(0)
query_id = str(uuid.uuid4())
ole.CallMethod( query_id, guid_module, "ExtSdk2.WriteDocumentEx", json.dumps({"Document": document}, ensure_ascii=True), account_id )
countPrepare -= 1
countFreeThread -= 1
countSend += 1
getData
Формирует объект документ. Получает из информационной системы необходимые данные. Подготовленный объект сохраняет в cachePrepare.
def getData():
uuid_document = listLinks.pop()
document = fromation_document( uuid_document )
cachePrepare.append(document)
countPrepare += 1
Функция fromation_document возвращает подготовленный объект Документ для отправки с переданным идентификатором документа.
readEvents
Получает одну страницу событий (OLE.ReadAll). Вызывает зарегистрированные колбеки для полученных событий.
result_read_all_object = read_all_object()
while len(result_read_all_object) != 0:
callback_WriteDocumentEx(result_read_all_object.pop())
Функция read_all_object() возвращает обработанный массив событий, полученный за один вызов ole.ReadAllObject(). См. раздел Пример функции обработки одной страницы событий
callback_WriteDocumentEx
Сохраняет полученный результат в cacheAnswer, обновляет счетчик свободных потоков.
Для временных ошибок возвращает пакет в cachePrepare или идентификатор в список не отправленных.
В список временных ошибок так же попадает переаутентификация. Контекст должен содержать время последней аутентификации / начала работы метода, а колбеки время вызова, чтобы понимать под какой сессией они ходили.
так же данный колбек отвечает за прерывание отправки если идут постоянные ошибки (нет успешных отправок).
Алгоритм работы надо отдельно прописать...
def callback_WriteDocumentEx(event):
countFreeThread += 1
result_event = parse_event( event )
cacheAnswer.append(result_event)
Функция parse_event разбирает полученное событие. См.
processAnswer
Берет первые N записей из chacheAnswer и обновляет статусы у документа. N определяем динамически исходя из времени работы метода.
Начинаем с N = countThread и рассчитываем после каждого выполнения сколько влезает в 3 сек исходя из среднего времени на один статус.
processAllAnswer
Вызывает processAnswer пока chacheAnswer не опустеет.
sendStat
Делает один вызов для записи статистики (данные статистики и массив ошибок, ошибки сгруппированы по типу)
Отправка нескольких электронных комплектов документов без формирования вложений
На входе имеем список объектов «Документ» подлежащих отправке и набор относящихся к ним файлов вложений в каталоге. Нам требуется загрузить и запустить его в документооборот СБИС, при необходимости выполнив операции подписания и шифрования.