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