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