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