Как в Конвертации данных 2.0 организовать поиск объекта по полям поиска или по УИД в зависимости от даты

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При переносе данных между базами 1С нередко возникает ситуация, когда до определенного момента времени (например, до даты начала ведения регулярного обмена) документы в базе-приемнике уже были созданы вручную или перенесены другой обработкой. В таком случае их внутренние идентификаторы (GUID/UUID) в источниках и приемниках различаются, и сопоставлять их необходимо исключительно по реквизитам (номеру, дате, организации). Однако для всех новых документов, создаваемых после даты перехода, поиск должен происходить строго по уникальному идентификатору (УИД), чтобы исключить дублирование и ошибки сопоставления при случайном изменении номеров.

Разберем особенности стандартного механизма сопоставления в «1С:Конвертации данных 2.0» и рассмотрим практические способы решения этой задачи.

Особенности стандартного алгоритма поиска в КД 2.0

Для правильного построения логики важно понимать, в каком порядке платформа выполняет сопоставление при загрузке данных:

  1. Кэш сопоставлений: В первую очередь проверяется внутренняя таблица соответствий текущего сеанса загрузки. Если объект уже был однажды найден или создан, повторный поиск не выполняется.
  2. Поиск по УИД: Если в правиле конвертации объекта (ПКО) установлен флаг «Искать объект приемника по внутреннему идентификатору», система сразу пытается найти запись в базе приемника по ссылке. Если объект найден, поиск считается завершенным — стандартные поля поиска и обработчик ПоляПоиска не вызываются.
  3. Поля поиска: Если флаг поиска по УИД отключен или объект по УИД не найден, управление передается обработчику ПоляПоиска и стандартному поиску по реквизитам с флагом «Поиск».

Следовательно, просто добавить условие в обработчик ПоляПоиска при включенном поиске по УИД не получится — поиск по УИД сработает раньше. Рассмотрим два надежных способа реализации поставленной задачи.

Способ 1. Использование двух ПКО с динамическим переключением правила

Проанализируем наиболее прозрачный и универсальный подход. Мы создаем два отдельных правила конвертации объектов (ПКО) для одного и того же типа документа:

  1. ПКО_Документ_ПоПолям: в настройках правила отключаем флаг поиска по внутреннему идентификатору, а для ключевых реквизитов (например, Дата, Номер, Организация) включаем флаг поиска.
  2. ПКО_Документ_ПоУИД: в настройках правила оставляем включенным флаг поиска по внутреннему идентификатору, а флаги поиска на отдельных реквизитах снимаем.

Теперь настроим динамическое переключение правил при выгрузке. Рассмотрим два сценария выгрузки: прямую выгрузку по правилу выгрузки данных (ПВД) и выгрузку по ссылке из других объектов.

Для выгрузки через ПВД в обработчике «ПередВыгрузкой» соответствующего правила выгрузки данных пишем следующий код:


Если Объект.Дата >= Параметры.ГраничнаяДата Тогда
    ИмяПКО = "ПКО_Документ_ПоУИД";
Иначе
    ИмяПКО = "ПКО_Документ_ПоПолям";
КонецЕсли;

Однако этого недостаточно, если документ может выгружаться по ссылке из других связанных объектов (например, как документ-основание или ссылка в регистре). Чтобы переключение работало глобально, в основном ПКО документа в обработчике «ПередВыгрузкой» переопределяем параметр ИмяПКО:


Если Источник.Дата >= Параметры.ГраничнаяДата Тогда
    ИмяПКО = "ПКО_Документ_ПоУИД";
Иначе
    ИмяПКО = "ПКО_Документ_ПоПолям";
КонецЕсли;

При таком подходе платформа автоматически направит объект на обработку по нужному ПКО независимо от того, выгружается он по плану обмена (ПВД) или по ссылке из другого объекта.

Способ 2. Обработка поиска на стороне приемника в обработчике «ПоляПоиска»

Разберем альтернативный вариант, когда мы хотим оставить только одно ПКО и перенести всю логику сопоставления на этап загрузки данных.

Для реализации этого варианта выполним следующие шаги:

  1. В настройках ПКО снимаем флаг «Искать объект приемника по внутреннему идентификатору».
  2. В ПКС ключевых реквизитов (Дата, Номер, Организация) включаем флаг поиска, чтобы их значения гарантированно попали в коллекцию СвойстваПоиска.
  3. В обработчике ПКО «ПоляПоиска» реализуем ручной алгоритм поиска в зависимости от даты документа.

Посмотрим на пример кода в обработчике «ПоляПоиска» ПКО:


ДатаДокумента = СвойстваПоиска["Дата"];

Если ДатаДокумента >= Параметры.ГраничнаяДата Тогда
    // Ищем строго по УИД источника
    УИД_Строка = Строка(СвойстваПоиска["{УникальныйИдентификатор}"]);
    Если ЗначениеЗаполнено(УИД_Строка) Тогда
        СсылкаПоУИД = Документы[ИмяТипаОбъектаПриемника].ПолучитьСсылку(Новый УникальныйИдентификатор(УИД_Строка));
        
        // Проверяем физическое существование объекта в базе
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ Ссылка ИЗ Документ." + ИмяТипаОбъектаПриемника + " ГДЕ Ссылка = &Ссылка";
        Запрос.УстановитьПараметр("Ссылка", СсылкаПоУИД);
        
        Если НЕ Запрос.Выполнить().Пустой() Тогда
            СсылкаНаОбъект = СсылкаПоУИД;
            ПрекратитьПоиск = Истина;
        КонецЕсли;
    КонецЕсли;
Иначе
    // Ищем запросом по реквизитам поиска (с учетом периодичности нумерации)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    Ссылка
        |ИЗ
        |    Документ." + ИмяТипаОбъектаПриемника + " КАК Док
        |ГДЕ
        |    Док.Номер = &Номер
        |    И Док.Дата МЕЖДУ &НачалоГода И &КонецГода
        |    И Док.Организация = &Организация
        |    И НЕ Док.ПометкаУдаления";
        
    Запрос.УстановитьПараметр("Номер", СвойстваПоиска["Номер"]);
    Запрос.УстановитьПараметр("Организация", СвойстваПоиска["Организация"]);
    Запрос.УстановитьПараметр("НачалоГода", НачалоГода(ДатаДокумента));
    Запрос.УстановитьПараметр("КонецГода", КонецГода(ДатаДокумента));
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        СсылкаНаОбъект = Выборка.Ссылка;
        ПрекратитьПоиск = Истина;
    КонецЕсли;
КонецЕсли;

Важные нюансы и рекомендации

При настройке условного поиска обратите внимание на следующие моменты:

  1. Периодичность нумерации: При поиске по номеру обязательно ограничивайте выборку периодом действия нумерации (обычно годом), используя НачалоГода() и КонецГода(), чтобы не сопоставить документ текущего года с одноименным документом прошлого периода.
  2. Создание новых объектов: Если при поиске по УИД объект не найден (новый документ после граничной даты), система создаст новый документ и при включенной стандартной установке ссылки присвоит ему переданный GUID источника.
  3. Сравнение вариантов: Способ с двумя ПКО и переопределением ИмяПКО в ПередВыгрузкой проще в сопровождении и отладке, так как использует штатные механизмы сопоставления платформы без написания громоздких запросов в обработчиках загрузки.
← На главную