Перенос дополнительных реквизитов и свойств номенклатуры из одной базы в другую через COM-соединение — частая задача при интеграции или синхронизации баз на платформе 1С:Предприятие 8. Однако при реализации такого механизма разработчики часто сталкиваются с ситуацией, когда свойства создаются корректно, но их значения теряют подчиненность, не привязываются к категориям или не отображаются в карточках номенклатуры приемника.
Рассмотрим подробно, почему возникают эти ошибки при переносе дополнительных реквизитов в конфигурации «Управление торговлей» редакции 10.3 и как правильно написать алгоритм переноса.
Разберем основные причины, по которым свойства или их значения переносятся некорректно:
ЗначенияСвойствОбъектов является подчиненным по отношению к плану видов характеристик СвойстваОбъектов. Если при поиске или создании элементов этого справочника не заполнять реквизит Владелец, значения становятся «сиротами» и не привязываются к конкретному свойству.Число, Строка, Дата, Булево), так и ссылка на элемент справочника ЗначенияСвойствОбъектов. При переносе необходимо строго разделять эти типы.СвойстваОбъектов задает лишь перечень доступных дополнительных реквизитов. Чтобы свойство отображалось в форме номенклатуры или конкретной группы номенклатуры, должна присутствовать соответствующая запись в регистре сведений НазначенияСвойствОбъектов.Проанализируем получение исходных данных. Сначала соберем из регистра сведений ЗначенияСвойствОбъектов все установленные значения дополнительных реквизитов для номенклатуры из выбранного каталога:
Если КорневойКаталог.Пустая() Тогда
Сообщить("Не выбран Корневой Каталог!");
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗначенияСвойствОбъектов.Объект КАК Номенклатура,
| ЗначенияСвойствОбъектов.Свойство КАК Свойство,
| ЗначенияСвойствОбъектов.Значение КАК Значение,
| ЗначенияСвойствОбъектов.Свойство.НазначениеСвойства КАК НазначениеСвойства
|ИЗ
| РегистрСведений.ЗначенияСвойствОбъектов КАК ЗначенияСвойствОбъектов
|ГДЕ
| ЗначенияСвойствОбъектов.Объект В ИЕРАРХИИ(&ВыбКаталог)";
Запрос.УстановитьПараметр("ВыбКаталог", КорневойКаталог);
СписокСвойств = Запрос.Выполнить().Выгрузить();
Рассмотрим алгоритм обхода выгруженных данных. Для каждого элемента необходимо найти объект-приемник по УИД, сопоставить само свойство (элемент ПВХ), создать или найти элемент значения свойства с указанием его владельца и записать результат в регистр сведений ЗначенияСвойствОбъектов.
Для каждого СтрНомен из СписокСвойств Цикл
// 1. Поиск номенклатуры в приемнике по УИД
УидВЭтойБазе = СтрНомен.Номенклатура.УникальныйИдентификатор();
УидВоВнешнейБазе = БазаОткрыта.NewObject("УникальныйИдентификатор", Строка(УидВЭтойБазе));
Справочник = БазаОткрыта.Справочники.Номенклатура;
СправочникОбъект = Справочник.ПолучитьСсылку(УидВоВнешнейБазе).ПолучитьОбъект();
Если СправочникОбъект = Неопределено Тогда
Сообщить("Не нашли номенклатуру: " + СтрНомен.Номенклатура);
Продолжить;
КонецЕсли;
// 2. Поиск или создание самого свойства (ПВХ СвойстваОбъектов)
Свойство = БазаОткрыта.ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоНаименованию(СокрЛП(СтрНомен.Свойство.Наименование));
Назн = БазаОткрыта.ПланыВидовХарактеристик.НазначенияСвойствКатегорийОбъектов.НайтиПоНаименованию(СокрЛП(СтрНомен.НазначениеСвойства.Наименование));
Если Назн.Наименование = "" Тогда
Сообщить("Не нашли назначение свойства: " + СтрНомен.НазначениеСвойства.Наименование);
Продолжить;
КонецЕсли;
Если Свойство.Наименование = "" Тогда
СвойствоОб = БазаОткрыта.ПланыВидовХарактеристик.СвойстваОбъектов.СоздатьЭлемент();
СвойствоОб.НазначениеСвойства = Назн;
СвойствоОб.Наименование = СтрНомен.Свойство.Наименование;
СвойствоОб.Записать();
Свойство = СвойствоОб.Ссылка;
КонецЕсли;
// 3. Обработка значения свойства с учетом его типа и владельца
Если ТипЗнч(СтрНомен.Значение) = Тип("Число") Или ТипЗнч(СтрНомен.Значение) = Тип("Строка") Или ТипЗнч(СтрНомен.Значение) = Тип("Булево") Тогда
НовЗнач = СтрНомен.Значение;
ИначеЕсли ТипЗнч(СтрНомен.Значение) = Тип("СправочникСсылка.ЗначенияСвойствОбъектов") Тогда
// Поиск/создание владельца значения (самого свойства)
Владелец = БазаОткрыта.ПланыВидовХарактеристик.СвойстваОбъектов.НайтиПоКоду(СтрНомен.Значение.Владелец.Код);
Если СокрЛП(Владелец.Код) = "" Тогда
ВладелецОб = БазаОткрыта.ПланыВидовХарактеристик.СвойстваОбъектов.СоздатьЭлемент();
ВладелецОб.Код = СтрНомен.Значение.Владелец.Код;
ВладелецОб.Наименование = СтрНомен.Значение.Владелец.Наименование;
ВладелецОб.НазначениеСвойства = Назн;
ВладелецОб.Записать();
Владелец = ВладелецОб.Ссылка;
КонецЕсли;
// Поиск значения с указанием владельца
НовЗнач = БазаОткрыта.Справочники.ЗначенияСвойствОбъектов.НайтиПоКоду(СтрНомен.Значение.Код);
Если СокрЛП(НовЗнач.Код) = "" Тогда
НовЗначОб = БазаОткрыта.Справочники.ЗначенияСвойствОбъектов.СоздатьЭлемент();
Иначе
НовЗначОб = НовЗнач.ПолучитьОбъект();
КонецЕсли;
НовЗначОб.Код = СтрНомен.Значение.Код;
НовЗначОб.Наименование = СтрНомен.Значение.Наименование;
НовЗначОб.Владелец = Владелец; // Обязательное указание владельца!
НовЗначОб.Записать();
НовЗнач = НовЗначОб.Ссылка;
Иначе
Сообщить("Пропущен неизвестный тип значения: " + СтрНомен.Значение);
Продолжить;
КонецЕсли;
// 4. Запись значения свойства для объекта
МенеджерЗаписи = БазаОткрыта.РегистрыСведений.ЗначенияСвойствОбъектов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Объект = СправочникОбъект.Ссылка;
МенеджерЗаписи.Свойство = Свойство;
МенеджерЗаписи.Значение = НовЗнач;
МенеджерЗаписи.Записать();
Сообщить("Записано свойство: " + СтрНомен.Свойство.Наименование);
КонецЦикла;
Выясним причину, почему перенесенное свойство может не отображаться в диалоговом окне номенклатуры в базе-приемнике. В УТ 10.3 привязка свойства к объектам (или папкам номенклатуры) хранится отдельно в регистре сведений НазначенияСвойствОбъектов.
Чтобы свойство стало доступным для конкретной группы номенклатуры или объекта, необходимо добавить запись в этот регистр сведений:
ЗаписьНазначения = БазаОткрыта.РегистрыСведений.НазначенияСвойствОбъектов.СоздатьМенеджерЗаписи();
ЗаписьНазначения.Объект = ГруппаНоменклатурыВПриемнике; // Ссылка на папку номенклатуры или тип объектов
ЗаписьНазначения.Свойство = Свойство; // Ссылка на ПВХ СвойстваОбъектов
ЗаписьНазначения.Записать(Истина);
После заполнения этого регистра перенесенные свойства будут правильно отображаться во вкладке «Свойства» карточки номенклатуры и ее групп в базе-приемнике.