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