При настройке обменов между разными конфигурациями 1С часто возникает ситуация структурного несоответствия. Классический пример, который мы сегодня разберем: перенос документов из ЗУП 3.1 в УПП 1.3 (или схожие задачи для ERP/КА). В базе-источнике (ЗУП) в документе есть и поле Сотрудник, и поле ФизическоеЛицо. В базе-приемнике (УПП) аналогичный документ содержит только поле ФизическоеЛицо.
Задача состоит в том, чтобы при загрузке документа не просто заполнить Физлицо, но и гарантировать, что в базе-приемнике существует соответствующий Сотрудник, связанный с этим Физлицом. Если сотрудника нет — его нужно создать. Просто игнорировать поле Сотрудник нельзя, так как это нарушит целостность кадрового учета в приемнике.
Давайте подробно рассмотрим, как решить эту задачу с помощью инструментов 1С:Конвертация данных 2.1 (КД 2.1).
В КД 2.1 данные обычно переносятся "по реквизитам": если в ПКО (Правило Конвертации Объектов) источника есть свойство, мы ищем ему пару в приемнике. Если пары нет — свойство обычно отключают. Но в нашем случае объект Сотрудник не является "лишним", он просто не хранится в самом документе приемника, а должен существовать в справочнике СотрудникиОрганизаций.
Рассмотрим три основных подхода к решению этой задачи, от простых к более профессиональным.
Это наиболее надежный и идеологически верный способ для КД 2.1. Суть его заключается в принудительной инициации выгрузки объекта по определенному правилу, даже если этот объект не сопоставлен ни с каким реквизитом приемника.
Шаг 1. Создание ПКО для справочника Сотрудники
Сначала убедимся, что у нас есть ПКО Сотрудники (ЗУП) -> СотрудникиОрганизаций (УПП). В этом правиле обязательно настроим поля поиска (ключевые поля), чтобы не создавать дублей. Для сотрудников это обычно:
ФизическоеЛицо (поиск по ссылке).Организация.Код или ТабельныйНомер (если они синхронизированы).Шаг 2. Вызов выгрузки из ПКС документа
Перейдем в ПКО нашего документа. Найдем ПКС (Правило Конвертации Свойств) для реквизита ФизическоеЛицо или создадим фиктивное ПКС. В обработчике события ПередВыгрузкой напишем код, который принудительно отправит сотрудника в файл обмена.
// Обработчик "ПередВыгрузкой" свойства
// Источник.Сотрудник - это ссылка на сотрудника в ЗУП
// "СотрудникиОрганизаций" - имя правила конвертации для сотрудников
ВыгрузитьПоПравилу(Источник.Сотрудник, , , , "СотрудникиОрганизаций");
Как это работает:
СотрудникиОрганизаций.ФизическимЛицом, но необходимый нам сотрудник будет гарантированно существовать в базе.Этот метод часто используется, если нам нужно связать создание сотрудника непосредственно с процессом загрузки физического лица. Логика такова: "Загружаем Физлицо, и сразу проверяем, есть ли у него Сотрудник".
Шаг 1. Передача контекста из документа
В ПКО документа, в ПКС свойства ФизическоеЛицо, мы должны передать ссылку на сотрудника во ВходящиеДанные правила конвертации физлиц.
// Обработчик "ПередВыгрузкой" свойства ФизическоеЛицо в Документе
ИсходящиеДанные = Новый Структура;
ИсходящиеДанные.Вставить("ПереданныйСотрудник", Источник.Сотрудник);
Шаг 2. Обработка при загрузке Физлица
Теперь перейдем в ПКО ФизическиеЛица. В обработчике ПослеЗагрузки мы можем прочитать переданные данные и выполнить программную проверку или создание сотрудника в базе-приемнике.
// Обработчик "ПослеЗагрузки" в ПКО ФизическиеЛица
// Объект - это уже загруженное ФизЛицо в базе приемнике
Если ВходящиеДанные <> Неопределено И ВходящиеДанные.Свойство("ПереданныйСотрудник") Тогда
СотрудникИсточник = ВходящиеДанные.ПереданныйСотрудник;
// Здесь нам придется либо снова вызывать ВыгрузитьПоПравилу (что лучше сделать раньше),
// либо писать код на языке 1С для поиска сотрудника в базе приемнике.
// Например, искать по реквизиту ФизЛицо = Объект.Ссылка
// Пример поиска (упрощенно):
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.СотрудникиОрганизаций ГДЕ Физлицо = &Физлицо");
Запрос.УстановитьПараметр("Физлицо", Объект.Ссылка);
// Если результат пустой -> СоздатьНовый()
КонецЕсли;
Недостаток метода: Этот способ требует написания большого количества кода в базе-приемнике (алгоритмы поиска и создания), что противоречит идеологии КД, где логика должна описываться правилами. Поэтому первый способ предпочтительнее.
В обсуждении часто предлагают использовать параметры. Разберем нюансы этого подхода.
Если мы установим галочку "Передавать данные в параметр" в ПКС, значение не попадет в реквизит приемника, а запишется в структуру ПараметрыОбъекта, доступную при загрузке объекта.
Проблема с табличными частями:
Если Сотрудник находится в табличной части документа, использование простых параметров ПКС не сработает корректно. Параметры обычно привязываются к объекту в целом (шапке документа). Если в табличной части 10 строк с разными сотрудниками, параметр в шапке будет перезаписываться, и сохранится только последний.
Чтобы обойти это, придется передавать таблицу значений или массив структур через ИсходящиеДанные всего документа, что значительно усложняет правила.
При реализации любого из методов обратите внимание на следующие моменты:
Поскольку базы разные (ЗУП и УПП), поиск по уникальному идентификатору (UID) часто не срабатывает для созданных вручную объектов. Обязательно настройте поиск сотрудника по совокупности полей. Самый надежный вариант для УПП: Организация + Физлицо.
Если в источнике (ЗУП) данные хранятся иначе, чем в приемнике, можно использовать "виртуальную" выгрузку. В обработчике ПередВыгрузкой документа можно сформировать произвольную таблицу значений, поместить её во ВходящиеДанные и создать в ПКО приемника фиктивную табличную часть, настроив для нее правило выгрузки данных. Это позволяет трансформировать структуру документа на лету.
Если вы используете метод ВыгрузитьПоПравилу, убедитесь, что правило для Сотрудников выгружает и ссылку на Физлицо. В КД это происходит автоматически, если настроено ПКС для физлица внутри ПКО сотрудника. Если этого не сделать, сотрудник создастся "битым" (без привязки к человеку).
Для решения задачи "проверить и создать Сотрудника в УПП при загрузке документа из ЗУП, где есть только Физлицо" оптимальным алгоритмом является:
Сотрудники -> СотрудникиОрганизаций с настроенными полями поиска.ПередВыгрузкой табличной части или строки) вызвать функцию ВыгрузитьПоПравилу(Источник.Сотрудник, , , , "ИмяПКОСотрудники");.Это обеспечит наличие актуальных данных в справочнике сотрудников базы-приемника без необходимости изменять структуру документа-приемника или писать сложный код поиска при загрузке.