Сказ о том, как в одной крупной компании документооборот внедряли, или проблемы типовых обменов между КА и ДО
Приветствую всех. Сегодня пойдет речь о том, как на одной крупной компании внедряли 1С:Документооборот 2.1 в связке с КА 2.4.
Вроде бы системы типовые, мы практически не добавляли ничего в них, но проблем было столько, что я решил изложить их в статье. Может, кому-то пригодится это в дальнейшем, и не придется тратить кучу времени на поиск решений.
- Описание
- Подробнее
Описание
КА -комплексная автоматизация, ДО — документооборот.
Итак, базы развернуты, опубликованы, можем начинать. А начнем с синхронизации…
Этап 1: Синхронизация
Настраиваем типовую синхронизацию, далее первый запуск и…ничего не работает. Идем в журнал регистрации и видим странную ошибку.
Неверное имя колонки {Обработка.КонвертацияОбъектовИнформационныхБаз.МодульОбъекта(8431)}: Коллекция.Колонки.Добавить(ИмяПоля); {Обработка.КонвертацияОбъектовИнформационныхБаз.МодульОбъекта(8310)}: КоллекцияГруппировки = ИнициализацияТаблицыПоКлючевымПолям(МассивКлючевыхПолейПоиска); {Обработка.КонвертацияОбъектовИнформационныхБаз.МодульОбъекта(9955)}: ЗагрузитьТабличнуюЧасть(Объект, Имя, ИнформацияОТипах, ПараметрыОбъекта, Правило); {Обработка.КонвертацияОбъектовИнформационныхБаз.МодульОбъекта(16050)}: ПоследнийОбъектЗагрузки = ПрочитатьОбъект(); {Обработка.КонвертацияОбъектовИнформационныхБаз.МодульОбъекта(2663)}: ПроизвестиЧтениеДанныхВРежимеВнешнегоСоединения(ЧтениеСообщения); {ОбщийМодуль.ОбменДаннымиСервер.Модуль(5794)}: ОбработкаОбменаДаннымиВнешнееСоединение.ВыполнитьВыгрузкуДанных(ОбработкаДляЗагрузкиДанных); {ОбщийМодуль.ОбменДаннымиСервер.Модуль(2936)}: ВыполнитьДействиеОбменаДляУзлаИнформационнойБазыПоВнешнемуСоединению(Отказ, {Обработка.ВыполнениеОбменаДанными.МодульМенеджера(34)}: ОбменДаннымиСервер.ВыполнитьОбменДаннымиДляУзлаИнформационнойБазы( {(1)}:Обработки.ВыполнениеОбменаДанными.ВыполнитьЗапускОбменаДанными(Параметры[0],Параметры[1]) {ОбщийМодуль.ОбщегоНазначения.Модуль(4884)}: Выполнить ИмяМетода + "(" + ПараметрыСтрока + ")"; {ОбщийМодуль.ДлительныеОперации.Модуль(724)}: ОбщегоНазначения.ВыполнитьМетодКонфигурации(ИмяПроцедуры, ПараметрыПроцедуры); {ОбщийМодуль.ДлительныеОперации.Модуль(715)}: ВыполнитьПроцедуру(ВсеПараметры.ИмяПроцедуры, ВсеПараметры.ПараметрыПроцедуры);
Что ж, делать нечего…Идем в отладку. И что мы там наблюдаем? Довольно интересную картину.
По какой-то причине у нас две колонки с одним наименованием.
Идем в правила конвертации и видим, что в тч контактной информации две строки с конвертацией реквизита ДействуетС, удаляем лишнюю строку, заменяем правила — и о чудо, все работает.
Больше с синхронизацией проблем не было (только доработки, связанные со спецификой внедрения). Переходим к бесшовной интеграции.
з.ы. ошибка эта была в нескольких релизах подряд, на последнем релизе не проверял, но при необходимости могу посмотреть.
Этап 2.Интеграция (бесшовка).
Историю о настройке бесшовной интеграции начну с небольшого описания работы самого механизма.
На стороне КА имеются следующие объекты:
ПланОбмена : ИнтеграцияС1СДокументооборотомПереопределяемый
РегистрСведений: ОчередьСообщенийВ1СДокументооборот
При изменении объекта, участвующего в интеграции, этот объект регистрируется на узле плана обмена. Далее фоновое задание вызывает процедуру модуля, в котором соответственно выполняются последовательно три процедуры:
ИнтеграцияС1СДокументооборотОбмен.ПодготовитьДанныеДляОтправки();
ИнтеграцияС1СДокументооборотОбмен.ОтправитьДанные();
ИнтеграцияС1СДокументооборотОбмен.ПолучитьДанные();
ПодготовитьДанныеДляОтправки(); — формирует пакеты в формате xml и помещает их в регистр сведений ОчередьСообщенийВ1СДокументооборот в виде двоичных данных. При этом пакеты формируются с контролем длины пакета, при превышении длины пакет разбивается на части. В одном пакете может содержаться несколько объектов, а значит если возникнет проблема загрузки хотя бы одного объекта из пакета — пакет не прогрузится. По факту это сделано в угоду производительности, но при этом сказалось на устойчивости системы. (В итоге после согласования с заказчиком была механизм был изменен под логику ОдинОбъект-ОдинПакет см. далее)
ОтправитьДанные() — получает записи регистра, получает из двоичных данных пакет, формирует на основе пакетов запрос, выполняет этот запрос на стороне ДО. В случае успешного выполнения запись в регистре удаляется.
Минус этого метода — все пакеты обрабатываются в одной конструкции Попытка-Исключение. Если хотя бы один пакет с ошибкой, все остальные пакеты уже не обрабатываются.
Также была переделана — каждый пакет обрабатывается в отдельной попытке.
ПолучитьДанные() — в цикле с уловием, пока есть необработанные пакеты на стороне ДО формируется запрос, который передает на сторону ДО номер последнего успешно обработанного пакета и возвращает в КА новый пакет, после чего данный пакет обрабатывается на стороне ДО. В типовом варианте также при возникновении ошибки загрузка останавливается. (Также была доработана).
На стороне ДО:
План обмена ИнтегрированныеСистемы
регистр сведений ОчередиСообщенийОбменаСИнтегрированнымиСистемами
справочник: СообщенияИнтегрированныхСистем
Фоновое задание формирует пакет xml и в виде двоичных данных записывает его в справочник.
Далее на стороне КА вызывается процедура ПолучитьДанные()
при успешном получении элемент справочника помечается на удаление.
2.1 Выгрузка из ДО в КА (не те правила подставляются)
ИнтеграцияС1СДокументооборотОбмен ПолучитьДанные();
В этой процедуре для объекта производится поиск подходящего правила. Ниже представлен скриншот функции, получающей правило интеграции для объекта.
Как видно из текста запроса, выбирается первое попавшееся правило, у которого тип исходного и конечного объекта совпадают с условием. В нашем случае для договоров было 3 правила, отличающихся заполнением реквизитов и видом внутреннего документа. В итоге при выгрузке выбиралось некорректное правило и дальше весь обмен стопорился с ошибками (набор заполняемых полей во всех 3 правилах был разным). Указано, что функция эта устарела, но при этом даже в самых последних релизах до сих пор используется.
Заменяем на функцию, указанную в рекомендациях (заодно делаем для себя дополнительную запись в Журнал регистрации.
Теперь правило определяются корректно и большая часть ошибок уже решена. Едем дальше…
2.2 Обмен заявками на расходование ДС по физ лицам
После создания правила для Заявки на расходование ДС — Внутренний документ (Заявка на расходование ДС) с частью заявок появились проблемы. А именно, у заявки вид хоз. операции "Выдача подотчетнику" банковский счет с владельцем физ. лицо. В правиле для банковского счета стоит флаг Обновлять. В ДО у банковского счета во владельцах справочника Физ. лица нет в принципе. При обмене из-за этого возникает ошибка "ОбщийМодуль.ИнтеграцияС1СДокументооборот.Модуль(467) Значение не является значением объектного типа (name)". — по отладке это как раз момент заполнения владельца у банковского счета. Сейчас пока выключили обновление у банковского счета, но это решение временное. параллельно написали в ТП 1с.
Таких заявок оказалось крайне мало, но по мне, это недоработка документооборота.
2.3 Обмен статусами документов
В КА помимо статуса в объекте есть регистр сведений СостоянияСогласованияВДокументообороте. В процедуре получения данных из ДО в этот регистр записываются данные по статусу, если они есть в пакете. После записи в регистр вызывается процедура ИнтеграцияС1СДокументооборотПереопределяемый.ПриИзмененииСостоянияСогласования в которой на текущий момент ничего нет (процедура пустая). Я предполагаю, что данный регистр в дальнейшем нужно обрабатывать, получая статус и объект по идентификатору и далее изменять статус в самом объекте. Но мы идем немного другим путем и прописываем соответствия статусов непосредственно в правилах интеграции.
Перечь статусов в КА и ДО не соответствует, поэтому их нужно синхронизировать с помощью выражений.
Из КА в ДО:
Если Параметры.Источник.Статус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.НеСогласована Тогда
Параметры.Результат = "НеСогласован";
ИначеЕсли Параметры.Источник.Статус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.Согласована Тогда
Параметры.Результат = "Согласован";
ИначеЕсли Параметры.Источник.Статус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.КОплате Тогда
Параметры.Результат = "Согласован";
ИначеЕсли Параметры.Источник.Статус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.Отклонена Тогда
Параметры.Результат = "НеСогласован";
КонецЕсли;
ЗаписьЖурналаРегистрации("интеграция Отправка",УровеньЖурналаРегистрации.Информация,,Параметры.Результат,,);
Из ДО в КА:
пСтатус = Неопределено;
Если Параметры.Источник.statusApproval.name = "Согласован" Тогда
пСтатус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.Согласована;
ИначеЕсли Параметры.Источник.statusApproval.name = "Не согласован" Тогда
пСтатус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.НеСогласована;
ИначеЕсли Параметры.Источник.statusApproval.name = "На согласовании" Тогда
пСтатус = Перечисления.СтатусыЗаявокНаРасходованиеДенежныхСредств.НеСогласована;
КонецЕсли;
пСтатусДляЖР = "статус " + Параметры.Источник.status.name+"; объект "+Параметры.Источник.title+"; ст согл "+Параметры.Источник.statusApproval.name;
ЗаписьЖурналаРегистрации("интеграция Получение",УровеньЖурналаРегистрации.Информация,,пСтатусДляЖР,,);
Параметры.Результат = пСтатус;
Также столкнулись с такой проблемой: в КА заявку перевели в статус "К оплате", через некоторое время из ДО прилетает статус "Согласовано". Пришлось на стороне КА делать проверку, если статус "К оплате", то обмен его уже изменить не может. Такие заявки контролируются ответственным пользователем.
3. Меняем логику работы обмена.
После обсуждений с заказчиком было принято решение о том, что текущую логику работы обмена нужно поменять. А именно:
-сделать проверку на количество итераций по ошибочным пакетам при загрузке из ДО в КА;
-если ошибочный пакет грузится повторно, присваиваем ему статус обработанного с занесением ошибки в ЖР (в дальнейшем планируется отдельный регистр + рассылка ошибок по ответственным);
-под каждый объект делаем свой пакет, т.е если в очереди будет ошибочный объект, то он не повлияет на остальные пакеты в очереди;
В итоге доработки выглядят так: