Постановка задачи переноса одного объекта в два разных
Нередко бывает: один исходный документ нужно выгрузить сразу в два разных на приемнике. Например, придёт «Реализация» из старой БД и надо создать и «Реализацию» в приёмнике, и отдельно документ «Счет-фактуру». Типовой КД–обмен по умолчанию обрабатывает каждый объект лишь один раз, так что для разделения придётся «манипулировать» правилами. Задача ясна: настроить конвертацию так, чтобы из одного объекта-источника одновременно получились два объекта-приёмника разных видов.
Два подхода выгрузки: два ПВД или ВыгрузитьПоПравилу()
Есть два распространённых варианта решения. Первый — создать два правила выгрузки данных (ПВД) с одинаковыми условиями отбора (один и тот же запрос на источник) и разными правилами конвертации объектов (ПКО): каждое ПВД «посылает» объект в своё ПКО-правило. Второй — использовать функцию ВыгрузитьПоПравилу в обработчике события: после выгрузки первого объекта программно запустить выгрузку второго. Оба способа работают. MoscowSoft в гайдах прямо упоминает вызов ВыгрузитьПоПравилу для конвертации одного объекта сразу в два, например при переносе УПП→ERP.
Два правила выгрузки данных (ПВД)
В первом варианте вы просто дублируете настройку. Создаёте два ПВД: и первый, и второй отбивают один и тот же документ-источник (например, ТорговыйДокумент). В первом ПВД указываете ПКО «ПервыйДокумент», во втором — «ВторойДокумент» (или что там нужно). При выгрузке движок КД найдет два правила и сгенерирует два блока XML – по одному для каждого приёмника. Это похоже на два почти одинаковых обмена. Минус этого метода: сложнее настраивать фильтры и параметры по разным случаям, дублируются настройки выборки. Зато такой приём наглядный и полностью «стандартный»: вы на уровне конфигуратора обошли ограничения. Например, делали-то вы два ПВД с одним и тем же запросом (вместо простого «каждый объект»), и в итоге нужный объект «поймался» два раза.
Функция ВыгрузитьПоПравилу () в КД2
Второй подход чуть более программный. Допустим, вы создали одно ПВД с нужным запросом и привязали его к ПКО «ПервыйДокумент». В коде этого ПКО, в обработчике «ПослеВыгрузкиОбъекта», после стандартной конвертации первого объекта напишите вызов ВыгрузитьПоПравилу, указывая второе ПКО. Например:
Процедура ПослеВыгрузкиОбъекта(Источник, Приемник, Правило) // Первое ПКО – работаем как обычно, ничего не пишем или пишем нужную логику. // Теперь вызываем второе ПКО для того же исходника: ВыгрузитьПоПравилу(Источник, , , , "ПравилоПКО_ВторогоДокумента"); КонецПроцедуры
Здесь Источник – это объект из первой базы, а "ПравилоПКО_ВторогоДокумента" – имя второго правила конвертации (ПКО), ответственного за создание другого типа документа. Таким образом мы вручную инициируем дополнительную выгрузку из того же объекта. Этот приём прямо описан в рекомендациях: в ситуации «один в два» конвертации вызывают вторую выгрузку через ВыгрузитьПоПравилу. Стоит учесть: функция может экспортировать только один объект за вызов, но мы её вызываем явно, а не в цикле по выборке, поэтому это нормально. Параметры Приемник, ВходящиеДанные и т.д. при необходимости можно использовать или оставлять пустыми, главное – задать имя ПКО.
Пример реализации выгрузки одного объекта в два через правила конвертации данных XML
Вот пошаговый пример, иллюстрирующий второй подход:
1. Создайте ПКО и ПВД. Пусть источник – документ ИсточникДокумент, и в первой базе выборка при переходе по ПВД найдёт нужный документ. По умолчанию конвертация по первому ПКО перенесёт все общие реквизиты.
2. Напишите код в ПКО. Откройте правило конвертации объекта «ИсточникДокумент» (ПКО). На вкладке Алгоритмы добавьте обработчик события ПослеВыгрузкиОбъекта.
3. Вызовите второе правило. В теле процедуры вставьте код примерно такой:
Процедура ПослеВыгрузкиОбъекта(Источник, Приемник, Правило) // Формируем данные для второго документа, если нужно: Исходящие = Новый Структура("Реквизит1, Реквизит2", Источник.Реквизит1, Источник.Реквизит2); // Вызываем второе ПКО, которое создаст нужный объект: ВыгрузитьПоПравилу(Источник, , Исходящие, , "ПравилоПКО_ВторогоДокумента"); КонецПроцедуры
Здесь Исходящие – это структура для передачи специфичных данных во второе правило (например, какие строки табличной части включить). Если дополнительных данных не нужно, можно передать Неопределено или пустую структуру. Главное – имя второго правила в последнем параметре.
4. Настройте второе ПКО. Создайте правило конвертации «ВторойДокумент» (тот тип, который не создавался первым). Опишите в нём соответствие реквизитов или заполнение свойств. Убедитесь, что настроено «сопоставление источника и приёмника» и никакие фильтры не помешают загрузке. Вы также можете в этом втором ПКО в обработчике «При записи» присвоить реквизиту «ДокументОснование» значение Источник или ВходящиеДанные, чтобы связать документ с первым. Например:
// В обработчике ПриЗаписи второго документа Если ЗначениеЗаполнено(Приемник.ДокументОснование) Тогда Приемник.ДокументОснование = Источник; КонецЕсли;
Это обеспечит связь между «Первым» и «Вторым» документом.
5. Выполните выгрузку. Запустите процесс конвертации. При обработке исходного документа система сперва выполнит стандартный алгоритм первого ПКО, а затем ваш код с вызовом ВыгрузитьПоПравилу. В результате в XML-файле обмена появятся узлы для обоих объектов: и для первого документа, и для второго.
Проверка и отладка
Проверьте полученный XML-файл: в нём должны быть две секции <Документ> разного типа. Если приёмник не получил вторую запись, посмотрите журнал обмена и включите вывод отладочной информации в коде (например, через Сообщить). Убедитесь, что во втором правиле конвертации нет фильтров, запрещающих загрузку, и что у каждого документа корректно заполняются UUID и ссылки. Помните: если в «Настройках правила» стоит «Не запоминать выгруженные объекты» (неактивна галочка «Запомнить»), объекты могут выгрузиться повторно. На совместимость: данный подход работает как в «конвертации 2.0», так и в «2.1» (8.3), требования к коду практически те же. Главное – тестировать на данных и смотреть, как склеились документы при загрузке. В сложных случаях помогает промежуточное логирование или просмотр XML в текстовом редакторе.
Итог
Таким образом, задача разделения одного объекта на два решается: создаём либо два ПВД, либо программно вызываем второе ПКО через ВыгрузитьПоПравилу. Это довольно гибкое решение, хотя на первый взгляд кажется нетривиальным. А что вы думаете: стоит ли портить «чистую архитектуру» ещё одним ПКО, или «искусственный вызов» — оправданный обход лимитов? Попробуйте сами настроить пример, расскажите о своих подходах или вопросах – и давайте обсудим!













































