При долгой эксплуатации крупных корпоративных систем на базе 1С (таких как 1С:Управление холдингом, 1С:Бухгалтерия предприятия и 1С:Зарплата и управление персоналом) разработчики часто сталкиваются с ситуацией, когда типовой обмен данными на базе формата EnterpriseData превращается в абсолютно неуправляемый монолит. Сотни изменений «внутри» процедур менеджера обмена, измененные напрямую XDTO-пакеты и отсутствие документации превращают каждое обновление конфигурации в персональный кошмар для отдела сопровождения.
В этой статье мы подробно разберем, как полностью спроектировать архитектуру обмена заново, отказаться от практики модификации типового кода, перенести все доработки «вбок» (в расширения конфигурации) и сделать систему легко обновляемой. Мы пройдем весь путь: от анализа существующего хаоса до применения современных механизмов БСП (Библиотеки стандартных подсистем).
Когда перед нами лежат 46 000 строк запутанного кода, написанного разными разработчиками за последние 5 лет, пытаться построчно анализировать каждую процедуру — это путь к выгоранию и потере времени. Нам нужно применить метод анализа результатов работы системы.
Для этого мы выполним следующие действия:
Чтобы вернуть конфигурацию к полностью обновляемому состоянию, мы должны полностью отказаться от изменений в основной конфигурации. Все правила конвертации объектов (ПКО), правила обработки данных (ПОД) и правила регистрации объектов (ПРО) должны быть вынесены в расширения.
При этом забудьте про директиву #ИзменениеИКонтроль для модулей менеджера обмена. Модули обмена БСП активно развиваются, их структура меняется от релиза к релизу. Вместо этого мы будем использовать событийную модель БСП и перехватывать выполнение процедур с помощью аннотаций &После и &Перед.
Один из самых изящных способов передать нетиповые реквизиты без изменения структуры XDTO-пакета — это использование стандартного свойства AdditionalInfo. Почти все типы объектов в формате EnterpriseData наследуются от базового типа Object, который уже содержит данное необязательное поле.
Рассмотрим, как программно упаковать кастомные реквизиты на стороне источника и распаковать их на стороне приемника с помощью расширения.
На стороне источника перехватываем процедуру отправки объекта в расширении менеджера обмена:
&После("ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных")
Процедура Расш1_ПКО_Справочник_Номенклатура_Отправка_ПриОтправкеДанных(ДанныеИБ, ДанныеXDTO, КомпонентыОбмена)
// Создаем структуру с нашими нетиповыми реквизитами
СтруктураДопДанных = Новый Структура;
СтруктураДопДанных.Вставить("УникальныйИдентификаторИсточника", Строка(ДанныеИБ.Ссылка.УникальныйИдентификатор()));
СтруктураДопДанных.Вставить("КастомноеСвойствоНоменклатуры", ДанныеИБ.НашКастомныйРеквизит);
// Сериализуем структуру в JSON для передачи в текстовом поле AdditionalInfo
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураДопДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Записываем данные в стандартное поле XDTO
ДанныеXDTO.AdditionalInfo = СтрокаJSON;
КонецПроцедуры
На стороне приемника в расширении перехватываем процедуру получения данных, извлекаем информацию из JSON и заполняем реквизиты объекта ИБ:
&После("ПКО_Справочник_Номенклатура_Получение_ПриИмпорте")
Процедура Расш1_ПКО_Справочник_Номенклатура_Получение_ПриИмпорте(ДанныеXDTO, ПолученныеДанные, КомпонентыОбмена)
Если ДанныеXDTO.Свойство("AdditionalInfo") И ЗначениеЗаполнено(ДанныеXDTO.AdditionalInfo) Тогда
Попытка
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ДанныеXDTO.AdditionalInfo);
СтруктураДопДанных = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Заполняем реквизиты в объекте приемника
Если СтруктураДопДанных.Свойство("КастомноеСвойствоНоменклатуры") Тогда
ПолученныеДанные.НашКастомныйРеквизитПриемника = СтруктураДопДанных.КастомноеСвойствоНоменклатуры;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("ОбменДанными.ОшибкаРазбораДопДанных",
УровеньЖурналаРегистрации.Предупреждение, , ,
ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Этот способ позволяет передавать любые связанные данные, таблицы и структуры без необходимости прикасаться к схеме XSD.
Если бизнес-логика требует передачи больших табличных частей или новых кастомных справочников/документов, которых нет в стандартной схеме EnterpriseData, механизма AdditionalInfo может не хватить. В этом случае мы воспользуемся возможностями платформы 1С по расширению пакетов XDTO.
Разберем этот процесс по шагам:
http://www.yourcompany.ru/integration/custom.EnterpriseData нужной вам версии.ОбменДаннымиПереопределяемый.Пример программной регистрации расширения формата XDTO:
&После("ПриПолученииДоступныхРасширенийФормата")
Процедура Расш1_ПриПолученииДоступныхРасширенийФормата(МассивРасширений)
НовоеРасширение = Новый Структура;
НовоеРасширение.Вставить("ПространствоИмен", "http://www.yourcompany.ru/integration/custom");
НовоеРасширение.Вставить("Префикс", "cust");
НовоеРасширение.Вставить("ВерсияФормата", "1.15.1"); // Указываем версию базового ED
МассивРасширений.Добавить(НовоеРасширение);
КонецПроцедуры
После регистрации расширения формата платформа автоматически научится валидировать и обрабатывать новые свойства при сериализации и десериализации XML.
Вместо того чтобы вручную менять таблицы правил обмена в модуле менеджера обмена, мы можем программно модифицировать их в расширении при инициализации правил. Это гарантирует, что при обновлении типовой конфигурации ваши правила не затрутся.
Для добавления или изменения правил используем аннотацию &После для процедур заполнения правил:
&После("ЗаполнитьПравилаКонвертацииОбъектов")
Процедура Расш1_ЗаполнитьПравилаКонвертацииОбъектов(НаправлениеОбмена, ПравилаКонвертации)
// Находим существующее правило для документа Реализация товаров и услуг
Правило = ПравилаКонвертации.Найти("Документ_РеализацияТоваровУслуг_Отправка", "ИмяПравила");
Если Правило <> Неопределено Тогда
// Добавляем новое кастомное свойство в структуру конвертации
НовоеСвойство = Правило.Свойства.Добавить();
НовоеСвойство.ИмяСвойстваXDTO = "CustomProperty";
НовоеСвойство.ИмяСвойстваИБ = "НашКастомныйРеквизит";
КонецЕсли;
КонецПроцедуры
Помимо правил конвертации данных, кастомизация часто затрагивает правила регистрации объектов (ПРО) — алгоритмы, определяющие, какие именно документы должны уходить в обмен. Чтобы не править модуль менеджера регистрации, мы можем переопределить логику в расширении.
Для этого в расширении перехватываем процедуру инициализации правил регистрации:
&После("ИнициализацияПравилРегистрации")
Процедура Расш1_ИнициализацияПравилРегистрации(ПравилаРегистрации)
// Переопределяем правила отбора для выгрузки документов
ПравилоРегистрации = ПравилаРегистрации.Найти("Документ_РеализацияТоваровУслуг", "ИмяОбъекта");
Если ПравилоРегистрации <> Неопределено Тогда
// Устанавливаем программный фильтр (например, не регистрировать документы по определенной организации)
ПравилоРегистрации.СпособВыбораОбъектов = "СОтбором";
// Программно добавляем условия отбора
КонецЕсли;
КонецПроцедуры
Перевод сильно кастомизированного обмена на обновляемые рельсы — задача сложная, но вполне решаемая при системном подходе. Использование событийной модели БСП, передача данных через AdditionalInfo и программная донастройка правил регистрации и конвертации позволяют полностью отказаться от доработок в основной конфигурации.
Благодаря такому подходу вы получите: