Как переопределить номенклатуру при загрузке в КД 2.0, если объект уже найден по идентификатору

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

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

Почему стандартный поиск по УИД блокирует ваши изменения?

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

  1. Программа считывает GUID из файла выгрузки.
  2. Выполняется попытка найти объект в базе-приемнике по этому GUID.
  3. Внимание: Если объект найден, алгоритм поиска немедленно прекращается. Система считает задачу выполненной.
  4. Событие ПоляПоиска (или ПКС «Поля поиска»), в котором разработчики часто пишут свою логику, в этом случае вообще не вызывается.

Проанализируем ситуацию: вы написали прекрасный код в «Полях поиска», надеясь подменить СсылкаНаОбъект, но загрузка проходит в штатном режиме, игнорируя ваши условия. Это происходит потому, что поиск по УИД имеет приоритет «первого удачного выстрела».

Способ 1: Отказ от стандартного флага в пользу ручного управления

Это самый надежный и «чистый» способ решения задачи. Мы отключим автоматику и возьмем управление поиском на себя. Рассмотрим этот метод пошагово:

Во-первых, в ПКО Номенклатура необходимо снять галочку «Искать объект по уникальному идентификатору». Это заставит систему всегда заходить в обработчик Поля поиска.

Во-вторых, в самом обработчике Поля поиска мы напишем код, который сначала имитирует поиск по УИД, а затем применяет нашу кастомную логику переопределения. Проанализируем пример кода:


// ПКО Номенклатура -> Обработчик Поля поиска
// Пытаемся найти объект по GUID вручную, если он передан
Если СвойстваПоиска.Свойство("{УникальныйИдентификатор}") Тогда
    СтрокаУИД = СвойстваПоиска["{УникальныйИдентификатор}"];
    СсылкаПоУИД = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаУИД));
    
    // Проверяем, существует ли объект в базе
    ОбъектМетаданных = Метаданные.НайтиПоТипу(Тип("СправочникСсылка.Номенклатура"));
    Если СсылкаПоУИД.ПолучитьОбъект() <> Неопределено Тогда
        // Здесь ваша логика: нужно ли переопределять?
        Если НужнаЗаменаНаДругуюНоменклатуру Тогда 
            СсылкаНаОбъект = Справочники.Номенклатура.НайтиПоКоду("00001"); // Пример переопределения
        Иначе
            СсылкаНаОбъект = СсылкаПоУИД;
        КонецЕсли;
        
        // Обязательно сообщаем системе, что поиск завершен успешно
        ПрекратитьПоиск = Истина;
    КонецЕсли;
КонецЕсли;

В этом случае во все документы, которые ссылаются на данную номенклатуру, попадет именно та ссылка, которую вы определили в переменной СсылкаНаОбъект. Выясним причину, почему это лучше: поиск происходит до того, как ссылка будет закэширована в контексте загрузки документа-владельца.

Способ 2: Переопределение в событии «При загрузке»

Если вы по каким-то причинам не хотите отключать флаг поиска по УИД, можно попытаться «перехватить» объект в событии ПриЗагрузке. Однако здесь кроется подвох, о котором часто забывают. Рассмотрим ситуацию: объект найден по УИД, и система уже инициализировала переменную Объект.

Если вы просто напишете Объект = НужнаяСсылка.ПолучитьОбъект(), то данные из файла (наименование, артикул и прочее) начнут записываться в этот «новый» объект. Но главная проблема в том, что ссылка в документе (который вызвал загрузку этой номенклатуры) может остаться старой.

Чтобы подмена сработала, нужно использовать следующий подход:


// ПКО Номенклатура -> При загрузке
Если ОбъектНайден Тогда
    Если УсловиеДляЗамены Тогда
        // Получаем ссылку на правильный объект
        НоваяСсылка = Справочники.Номенклатура.НайтиПоНаименованию("Услуга по умолчанию");
        
        // Подменяем Объект, чтобы реквизиты из файла (если нужно) легли в него
        Объект = НоваяСсылка.ПолучитьОбъект();
        
        // Важно! Пытаемся подменить СсылкаНаОбъект, если обработка это позволяет
        СсылкаНаОбъект = НоваяСсылка;
    КонецЕсли;
КонецЕсли;

Важное замечание: Метод с ПриЗагрузке может не сработать для реквизитов документов в некоторых версиях обработок обмена (например, V8Exchan82.epf), так как ссылка на найденный по УИД объект передается в документ раньше, чем отрабатывает тело события ПриЗагрузке для самого объекта. Именно поэтому Способ 1 является приоритетным.

Проблема кэширования ссылок в документах

Разберем ситуацию, описанную в сообщениях форума: «В документ все равно попадает старый объект». Посмотрим на это глазами системы:

  1. Загружается ДокументОбъект.РеализацияТоваровУслуг.
  2. Система доходит до реквизита Номенклатура.
  3. Вызывается поиск по УИД для номенклатуры.
  4. Объект найден! Ссылка тут же помещается в табличную часть документа.
  5. Только ПОСЛЕ этого система может начать загрузку свойств самой номенклатуры (если она еще не была загружена в этом сеансе).

Если вы меняете Объект или СсылкаНаОбъект на этапе, когда документ уже «держит» старую ссылку, ваши изменения не повлияют на реквизит документа. Выходом является либо программная обработка ТЧ документа в событии ПослеЗагрузки документа (что трудозатратно, если документов много), либо использование первого способа с ручным поиском в ПКО Номенклатуры.

Рекомендации по реализации

Проанализируем лучшие практики для решения подобных задач в КД 2.0:

Подводя итог, можно сказать: если вам нужно гарантированное переопределение ссылки, отключайте стандартный поиск по УИД и реализуйте его программно в обработчике Поля поиска. Это дает вам полный контроль над тем, какая именно ссылка вернется в вызывающий объект, будь то документ, другой справочник или регистр сведений. Если такую настройку нужно изменить сразу у нескольких объектов конвертации, можно использовать обработку для отключения поиска по внутреннему идентификатору у объектов КД.

← На главную