Конвертация 2.0. Перенос независимого справочника в подчиненный (пример).









Пример переноса независимого справочника в подчиненный с помощью Конвертации 2.0.

Пример. Необходимо Конвертировать справочник Контрагенты, у которого контактное лицо является ссылкой на независимый справочник КонтактныеЛица, в одноименный справочник имеющий в подчинении справочник КонтактныеЛица. То есть, в Источнике контактное лицо является ссылкой на независимый справочник, а в Приемнике оно является ссылкой на подчиненный справочник. В источнике ссылка на справочник находится в реквизите Контактные лица, а в приемнике в реквизите Основное контактное лицо. Таким образом при переносе справочника Контрагенты нам нужно будет так же и перенести справочник КонтактныеЛица, который из независимого становится подчиненным.

Решение. Создадим Правило конвертации объектов(ПКО) для справочников Контрагенты, для Правила конвертации свойств(ПКС) КонтактноеЛицо создадим (если не создалось автоматически) ПКО указав в качестве объекта – источника и объекта – приемника справочник КонтактныеЛица и проверим заполнение нужных нам свойств. Так как в базе Источнике у нас справочник Контактные лица является независимым, то нам необходимо предать Владельца в Приемник. Для этого в ПКО Контрагенты в ПКС КонтактноеЛицо в обработчике Перед выгрузкой нам нужно получить исходящие данные, а именно, Владельца для передачи в входящие данные ПКО КонтактныеЛица. Запишем код:

ИсходящиеДанные = Новый Структура;

ИсходящиеДанные.Вставить("Владелец",Источник);

Где Источник является ссылкой на контрагента.

Стоит заметить, что если  Ключ структуры будет совпадать с Наименованием ПКС Приемника в ПКО куда передаются данные, то для переноса значения будет достаточно поставить флаг  Получить из входящих данных.

Если сейчас произвести перенос данных, то на первый взгляд данные справочника Контрагенты перенесутся корректно.

 

И если контактное лицо не будет повторятся для нескольких элементов справочника, то перенос будет верным. Но, на практике, такая ситуация практически невозможна. Если мы посмотрим контагентов с однаковым контактным лицом, то контактное лицо будет указано верно, но если перейдем по ссылке в справочник КонтактныеЛица, то увидим, что контактное лицо есть лишь для одного из контрагентов.

 

Поэтому получается, что в реквизит Основное контактное лицо передается ссылка на «чужой» элемент. А элемент с нужным владельцем попросту не создается.

Почему так происходит?

Первая причина – система при выгрузке запоминает объекты по ключу выгружаемых данных (по умолчанию — ссылка) и при появлении следующего объекта с таким же ключом, она не создает еще один объект с этим ключом, пускай у него даже отличаются реквизиты, а отсылает к созданному. В нашем примере это выглядит следующим образом:

  1. Создается объект Контрагент, у него в правиле конвертации свойств стоит ссылка на правило конвертации объекта КонтактныеЛица, по нему создается контактное лицо, согласно правилу конвертации, с реквизитами Ссылка (ключ выгружаемых данных), Наименование, Код и Владелец (Контрагент который вызвал ПКО).
  2. Создается следующий объект Контрагент, он так же ссылается на КонтактныеЛица, и если контактное лицо уже встречалась при выгрузке ранее, то, так как ссылка (ключ выгружаемых данных) у этих элементов одинаковая – объект не выгружается, а ссылается на первый созданный объект. То есть, в этом случае, текущий Контрагент имеет ссылку на объект, у которого в качестве Владельца будет указан первый выгруженный Контрагент.

По умолчанию система считает, что в базе в пределах одной таблицы не может быть элементов с одинаковой ссылкой, исходя из этого, при конвертации с стандартными настройками, если правила выгрузки обращаются к элементам с одинаковым ключом выгрузки данных (по умолчанию – ссылка), то система, считает, что обращение идет к одному и тому же объекту и выгружать его дополнительно не нужно, а нужно лишь сослаться на элемент, который уже выгружен.

Отключить возможность запоминания объекта можно, если в Правиле конвертации объектов поставить флаг Не запоминать выгруженные объекты. В нашем случае это будет означать, что для каждого Контрагента будет выгружен контакт в независимости от того повторяется он или нет.

Если поставить флаг Не запоминать выгруженные объекты, то в нашем случае проблема все-равно не решится. Ситуация будет аналогична предыдущей, только теперь в качестве Владельца, организация будет иметь последнего выгруженного контрагента, то есть ООО «Гамма». И мы подходим ко второй причине.

Вторая причина – система, в настройках по умолчанию, ищет объект Приемника по внутреннему идентификатору, то есть GUID. Если уникальный идентификатор найден, то перезаписываются данные переданные из конвертации, если элемента с таким идентификатором нет, то создается новый объект с уникальным идентификатором из Источника. То есть, хотя мы и получили для каждого контрагента контактное лицо, каждый последующий выгруженный объект с совпадающим уникальным идентификатором перезаписывает предыдущий. Отличие заключается в следующем, в первом случае для каждого совпадения контактных лиц у контрагентов выгружался один объект, во втором при совпадениях выгружаются все объекты. Получается данных передано больше, а результат все равно аналогичен предыдущему.

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

Правила конвертации объектов и Правила конвертации свойств у нас уже созданы, а так же в контактном лице получен владелец. Проверим настройки. Зайдем в Правило конвертации объектов Контактные лица, в вкладке Настройки проверим отсутствие флагов у Искать объект приемника по внутреннему идентификатору объекта источника и  Не запоминать выгруженные объекты.

В этом же правиле конвертации в обработчике Перед выгрузкой напишем код для создания ключа:

КлючВыгружаемыхДанных = ЗначениеВСтрокуВнутр(Источник)+ЗначениеВСтрокуВнутр(ВходящиеДанные.Владелец);

 

Где Источник – ссылка на объект справочника КонтактныеЛица , а ВходящиеДанные.Владелец ссылка владельца, то есть ссылка на объект справочника Контрагенты.

Далее установим свойства поиска, можно как мы и говорили ранее установить по свойству Наименование (вместо Наименования или в дополнение можно выбрать Код) и Владелец.

Теперь можно делать обмен данными. И посмотрим на результат.

Конвертация прошла успешно.

6 Comments

  1. wowik

    если есть возможность, прикрепите к статье правила.

    Reply
  2. dmitrit

    Если знать по какому принципу определять «Владельца» в приемнике то все довольно просто: нужно создать ПКО СпрИсточник — СпрПриемник

    в котором ПКС «Владелец» будет определяться в источнике по заданному алгоритму. Соответственно предварительно надо создать ПКО для передачи объекта

    «Владелец».

    Еще вариант — это задавать Владельца на этапе загрузки. Например в обработчике «После загрузки»

    [ Объект.Владелец = ФункцияПолученияВлдельца() ]

    Reply
  3. dmitrit

    В моем случае я сделал так: см вложенный файл

    Reply
  4. Lyubogradov.P

    Правила обмена для примера

    Reply
  5. tusv

    Ну если выгружаем из Бухгалтерии 3.0, то сопоставляем свойства источник и применика: ОбъектВладелец — Владелец. ПКО пустое

    В ПКС пишем

    Если ТипЗнч(Источник.ОбъектВладелец) = Тип(«СправочникСсылка.Организации») Тогда
    ИмяПКО=»Организации»;
    ИначеЕсли ТипЗнч(Источник.ОбъектВладелец) = Тип(«СправочникСсылка.Контрагенты») Тогда
    ИмяПКО=»Контрагенты»;
    ///Бла бла бла
    КонецЕсли;
    Reply
  6. burgomister

    Ошибка при выгрузке данных: {ВнешняяОбработка.УниверсальныйОбменДаннымиXML.МодульОбъекта(1577)}: Ошибка в обработчике события ПередВыгрузкойОбъекта

    ПКО = КонтактныеЛица (Справочник: Контактные лица)

    Объект = Иванов Николай Иванович, Генеральный директор (Контактное лицо)

    Обработчик = ПередВыгрузкойОбъекта

    ОписаниеОшибки = Значение не является значением объектного типа (Владелец)

    ПозицияМодуля = (1)

    КодСообщения = 41

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *