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