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