I. Теоретическая часть
В Конвертации данных 2 (далее, КД 2) отсутствует возможность полноценного добавления в правила своих процедур и функций. Существует некоторое подобие функций — Алгоритмы, которые представляют собой сохраненные отдельно куски кода, вызываемые в нужных местах. Но алгоритмы не позволяют реализовать возможности процедурного программирования в полной мере.
Для того, чтобы вызвать свою функцию или процедуру из КД 2, можно описать её за пределами правил обмена. Например, где-нибудь в коде базы источника и/или приемника, или написать обработку с нужной функцией и вызывать её в одном из обработчиков событий. Но данный подход не всегда удобен и уместен. Обработку перемещать вместе с правилами неудобно, а в код базы вообще лучше не лезть без необходимости.
Как раз для решения этой проблемы и предназначены Подключаемые обработки. Найти их можно на вкладке Конвертация/Подключаемые обработки.
В штатной справке по КД2 о подключаемых обработках написано следующее:
На закладке "Подключаемые обработки" могут быть загружены произвольные внешние обработки, используемые в процессе обмена. Можно выделить два основных варианта использования подключаемых обработок.
Вариант 1: Подключаемая обработка является своего рода библиотекой экспортируемых процедур / функций, используемых в процессе обмена.
Вариант 2: Подключаемая обработка поставляет форму интерфейсной настройки параметров обмена. Например, пользователю в удобном виде может быть предоставлена возможность настроить отбор выгружаемых / загружаемых данных.
Подключаемых обработок для обоих вариантов может быть произвольное количество. Для интерфейсных обработок необходимо установить флажок "Это обработка формы настройки". В этом случае в обработке "Универсальный обмен данными", после загрузки правил обмена, становиться доступной кнопка настройки, по нажатию на которую, либо открывается форма настройки, либо выпадает меню (если подключено несколько интерфейсных обработок). При настройке интерфейсной обработки, могут быть указаны параметры обработки, связанные с параметрами конвертации. В этом случае необходимые параметры конвертации инициализируются автоматически. Указанные параметры, должны совпадать с одноименными реквизитами обработки или реквизитами основной формы обработки. Инициализация параметров конвертации происходит, если при закрытии формы настройки возвращается значение отличное от Неопределено, в противном случае считается, что пользователь нажал кнопку "Отмена", т.е. закрыл форму без сохранения изменений.
Доступ к подключаемым обработкам в обработчиках событий обмена осуществляется так:
ДопОбработки.<ИмяОбработки>.<ИмяЭкспортируемойПроцедурыИлиФункции()>
Аналогично производится и обращение к форме обработки (если обработка является интерфейсной)
ДопОбработки.<ИмяОбработки>.ПолучитьФорму("<ИмяФормы>")
Для того, чтобы передать параметры из КД2 в форму и обратно, необходимо заполнить таблицу параметров обработки.
К сожалению, для возврата каких-либо параметров из формы придётся открывать её только модально. Пример передачи параметров в форму и обратно:
ФормаОбработки = ДопОбработки.<ИмяОбработки>.ПолучитьФорму("<ИмяФормы>");
//передача параметров
Для Каждого Параметр Из ПараметрыДопОбработок["<ИмяОбработки>"] Цикл
ФормаОбработки[Параметр] = Параметры[Параметр];
КонецЦикла;
РезультатОткрытияФормы = ФормаОбработки.ОткрытьМодально();
//возврат параметров
Если РезультатОткрытияФормы <> Неопределено Тогда
Для Каждого Параметр Из ПараметрыДопОбработок["<ИмяОбработки>"] Цикл
Параметры[Параметр] = ФормаОбработки[Параметр];
КонецЦикла;
КонецЕсли;
Подключаемые обработки включаются в файл правил обмена (кодируются в base64). Если обработки используются для загрузки, то помещаются и в файл с выгруженными данными. Это может замедлить процесс обмена и увеличить файл выгрузки, если обработки имеют большой размер.
В обработке Универсальный обмен данными в формате XML (V8Exchan83) убрали возможность использования подключаемых доп. обработок. В обработке V8Exchan82 такая возможность осталась. Для того, чтобы вернуть возможность поддержки подключаемых обработок, необходимо перенести текст процедуры ЗагрузитьОбработку из V8Exchan82 в V8Exchan83.
Теперь завершим теоретическую часть и перейдем к практике.
II. Практическая часть
Осуществляется переход с УПП на ERP. В УПП был реализован нетиповой функционал, связанный с отборами на форме выбора характеристики номенклатуры. Основу данного функционала составляют отборы компоновки данных, с помощью которых ограничивается видимость свойств и значений на форме. Сделано это для того, чтобы пользователь не вносил заранее ошибочные или несовместимые значения при создании заказа. Более подробно об использовании отборов СКД можно почитать тут.
На рисунке представлена форма выбора характеристики для наглядности. Аналогичный функционал был реализован и в ERP.
Непосредственно сама задача: В УПП есть регистр сведений, в котором хранятся отборы компоновки данных, помещенные в ХранилищеЗначений. Необходимо их перенести в ERP.
Логика решения задачи следующая:
1) Выполняется обход дерева отбора компоновки данных и собираются все объекты ссылочных типов;
2) Найденные объекты ссылочных типов выгружаются с помощью команды ВыгрузитьПоПравилу();
3) Сериализуется ОтборКомпоновкиДанных в XML-строку. Далее подменяются типы данных источника на типы данных приемника в строке;
4) ОтборКомпоновкиДанных помещается в параметр и выгружается в базу-приемник. В приемнике уже десериализуется.
Данный подход работает только в случае, когда поиска всех объектов ссылочных типов, входящих в отбор, происходит в базе-приемнике по внутреннему идентификатору (UUID).
Код ПВД:
Регистр = "pll_ОграниченияОтображенияСвойств";
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| pll_ОграниченияОтображенияСвойств.Номенклатура КАК Источник,
| pll_ОграниченияОтображенияСвойств.Номенклатура.ЭтоГруппа КАК ЭтоГруппа,
| pll_ОграниченияОтображенияСвойств.Свойство,
| pll_ОграниченияОтображенияСвойств.УникальныйИдентификатор,
| pll_ОграниченияОтображенияСвойств.Условие
|ИЗ
| РегистрСведений.pll_ОграниченияОтображенияСвойств КАК pll_ОграниченияОтображенияСвойств";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
ХранилищеУсловий = Выборка.Условие.Получить();
ОтборКомпоновки = ХранилищеУсловий.НастройкиКомпоновкиДанных.Отбор;
//проверка на заполненность отбора компоновки
Если НЕ ОтборКомпоновки.Элементы.Количество() Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Пустой отбор компоновки! Выгрузка отменена. Регистр: " + Регистр + ", номенклатура: " + Выборка.Источник +
", свойство: " + Выборка.Свойство+", УИД строки: "+Выборка.УникальныйИдентификатор;
Сообщение.Сообщить();
Продолжить;
КонецЕсли;
//Вызов доп. обработки по обходу дерева
РезультатОбхода = ДопОбработки.ОбходДерева.ОбойтиДерево(ОтборКомпоновки, Параметры.ВыгруженныеОбъекты);
//ВыгруженныеОбъекты - массив ссылочных объектов
Параметры.ВыгруженныеОбъекты = РезультатОбхода.ВыгруженныеОбъекты;
ОтборКомпоновки = РезультатОбхода.ОтборКомпоновки;
//Выгружаем ссылочные объекты
Для каждого Элемент из Параметры.ВыгруженныеОбъекты Цикл
ВыгрузитьПоПравилу(Элемент);
КонецЦикла;
//Преобразовываем отбор компоновки в XML-строку
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОтборКомпоновки);
СтрокаXML = ЗаписьXML.Закрыть();
//подменяем типы данных в XML-строке
СоответствиеОбъектов = Новый Соответствие;
СоответствиеОбъектов.Вставить("pll_ЦветПолимерногоПокрытия", "ЗначенияСвойствОбъектов");
//...
//...
//СоответствиеОбъектов.Вставить("", "");
//здесь описываются какие типы данных нужно подменить
// где Ключ - Тип данных УПП, значение - Тип данных ERP
Для каждого Элемент Из СоответствиеОбъектов Цикл
СтрокаXML = СтрЗаменить(СтрокаXML, "d3p1:CatalogRef."+Элемент.Ключ, "d3p1:CatalogRef."+Элемент.Значение);
КонецЦикла;
ИсходящиеДанные = Новый Структура("Источник, Свойство, ЭтоГруппа, ОтборКомпоновки, УникальныйИдентификатор");
ЗаполнитьЗначенияСвойств(ИсходящиеДанные,Выборка);
ИсходящиеДанные.ОтборКомпоновки = СтрокаXML;
ВыгрузитьПоПравилу(,,ИсходящиеДанные,,"КВСХ_ОграниченияВводаСвойств");
КонецЦикла;
Код модуля обработки по обходу дерева при выгрузке:
Функция ОбойтиДерево(Знач ОтборКомпоновки, Знач ВыгруженныеОбъекты) Экспорт
Для каждого ЭлементОтбора из ОтборКомпоновки.Элементы Цикл
ВыгрузитьЭлементОтбора(ЭлементОтбора, ВыгруженныеОбъекты);
КонецЦикла;
РезультатФункции = Новый Структура("ОтборКомпоновки, ВыгруженныеОбъекты",ОтборКомпоновки, ВыгруженныеОбъекты);
Возврат РезультатФункции;
КонецФункции
Процедура ВыгрузитьЭлементОтбора(ЭлементОтбора, ВыгруженныеОбъекты) Экспорт
Если ТипЗнч(ЭлементОтбора) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
//формируем наименования свойства из поля компоновки данных
ИсходнаяСтрока= Строка(ЭлементОтбора.ЛевоеЗначение);
КонечнаяСтрока =Лев(ИсходнаяСтрока,1);
Для Индекс=2 По СтрДлина(ИсходнаяСтрока) Цикл
Символ=Сред(ИсходнаяСтрока,Индекс,1);
КонечнаяСтрока=КонечнаяСтрока+?(ВРег(Символ)=Символ," "+НРег(Символ),Символ);
КонецЦикла;
//находим элемент по наименованию
СсылкаНаЭлемент = ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию(КонечнаяСтрока,Истина);
//добавляем свойство
ДобавитьВМассив(СсылкаНаЭлемент, ВыгруженныеОбъекты);
//формируем новое поле компоновки данных
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка.["+КонечнаяСтрока+"]");
//добавляем значения
Если ТипЗнч(ЭлементОтбора.ПравоеЗначение) = Тип("СписокЗначений") Тогда
Для каждого Элемент из ЭлементОтбора.ПравоеЗначение Цикл
ДобавитьВМассив(Элемент.Значение, ВыгруженныеОбъекты)
КонецЦикла;
ИначеЕсли НЕ ЗначениеЗаполнено(ЭлементОтбора.ПравоеЗначение) Тогда
//Ничего не делаем
Иначе
ДобавитьВМассив(ЭлементОтбора.ПравоеЗначение, ВыгруженныеОбъекты)
КонецЕсли;
ИначеЕсли ТипЗнч(ЭлементОтбора) = Тип("ГруппаЭлементовОтбораКомпоновкиДанных") Тогда
Для каждого Элемент из ЭлементОтбора.Элементы Цикл
//рекурсивно вызываем процедуру
ВыгрузитьЭлементОтбора(Элемент, ВыгруженныеОбъекты);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Процедура ДобавитьВМассив(Объект, ВыгруженныеОбъекты)
Если ОбщегоНазначения.ЗначениеСсылочногоТипа(Объект) И ВыгруженныеОбъекты.Найти(Объект) = Неопределено Тогда
ВыгруженныеОбъекты.Добавить(Объект);
КонецЕсли;
КонецПроцедуры
Послесловие
Подключаемые внешние обработки позволяют расширить функционал КД2, добавив в него полноценные возможности процедурного программирования. К сожалению, в сети я не нашел статьи, в которой бы разбирались все моменты, касающиеся использования доп. обработок, потому решил написать самостоятельно.
К сожалению, для использования доп. обработок в правилах обмена необходимо дорабатывать функционал обработки "Универсальный обмен данными в формате XML".
Также к минусам использования подключаемых доп. обработок необходимо отнести возможности только модального открытия формы доп. обработки.
Правила обмена разрабатывались в системе Конвертация данных, редакция 2.1 (2.1.8.2) для конфигураций 1С:ERP Управление предприятием 2 (2.4.10.62) и Управление производственным предприятием, редакция 1.3 (1.3.86.3). Справочник pll_ЦветПолимерногоПокрытия и регистр сведений pll_ОграниченияОтображенияСвойств являются самостоятельно добавленными объектами и отсутствуют в типовой версии Управление производственным предприятием.