При разработке подсистем шаблонизации часто возникает задача: в нетиповом справочнике шаблонов необходимо настроить и сохранить значения дополнительных реквизитов, а затем при формировании нового элемента типового справочника перенести их в целевой объект. Проанализируем архитектуру подсистемы «Свойства» Библиотеки стандартных подсистем (БСП) и разберем по шагам варианты реализации такого механизма без дублирования элементов планов видов характеристик и поиска по наименованию.
Основная ошибка при проектировании подобного механизма — попытка завести отдельные дубли свойств для справочника шаблонов и затем программно сопоставлять их по строковому наименованию. В БСП план видов характеристик ДополнительныеРеквизитыИСведения устроен универсально: один и тот же элемент ПВХ может входить в состав различных наборов справочника НаборыДополнительныхРеквизитовИСведений. Соответственно, сопоставление всегда должно строиться на прямых ссылках на свойства.
Рассмотрим подробнее классический подход, при котором справочник шаблонов становится полноправным владельцем дополнительных реквизитов в рамках типовой подсистемы свойств.
ВладелецДополнительныхРеквизитов (в некоторых редакциях БСП — ВладелецДополнительныхРеквизитовИСведений) и добавляем в список типов наш нетиповой справочник шаблонов.ДополнительныеРеквизиты со стандартными реквизитами:
Свойство (тип ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения);Значение (тип Характеристика.ДополнительныеРеквизитыИСведения);ТекстоваяСтрока (тип Строка).ПриСозданииНаСервере и ПередЗаписьюНаСервере общего модуля УправлениеСвойствами.УправлениеСвойствамиПереопределяемый в процедуре ЗаполнитьНаборыСвойствОбъекта переопределяем логику так, чтобы для объекта шаблона возвращался набор свойств выбранного вида целевого объекта.Перенос данных в целевой объект в этом случае выглядит максимально просто, так как структуры табличных частей и ссылки на свойства полностью идентичны:
// Заполняем целевой объект из шаблона
ОбъектПриемник = Справочники.Номенклатура.СоздатьЭлемент();
// Заполнение типовых реквизитов
ОбъектПриемник.Заполнить(ШаблонСсылка);
// Перенос дополнительных реквизитов
ОбъектПриемник.ДополнительныеРеквизиты.Загрузить(ШаблонСсылка.ДополнительныеРеквизиты.Выгрузить());
ОбъектПриемник.Записать();
Если мы не хотим модифицировать типовые определяемые типы и внедрять логику динамического построения элементов управления БСП в форму шаблона, разберем альтернативный путь: хранение настроек в собственной табличной части.
Посмотрим на пример структуры: в справочнике шаблонов создаем табличную часть НастройкиРеквизитов с реквизитами Свойство (тип ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения) и Значение (тип Характеристика.ДополнительныеРеквизитыИСведения). Для реквизита Значение в свойствах обязательно настраиваем Связь по типу с колонкой Свойство. Это обеспечит корректный выбор типа значения прямо в строке таблицы.
При выборе целевого вида в шаблоне заполняем состав доступных реквизитов напрямую из состава соответствующего набора БСП:
&НаСервере
Процедура ЗаполнитьРеквизитыПоНабору(НаборСвойствСсылка)
Объект.НастройкиРеквизитов.Очистить();
// Получаем реквизиты, входящие в состав набора
НаборОбъект = НаборСвойствСсылка.ПолучитьОбъект();
Для Каждого Стр Из НаборОбъект.Состав Цикл
Если Не Стр.Свойство.ПометкаУдаления Тогда
НоваяСтрока = Объект.НастройкиРеквизитов.Добавить();
НоваяСтрока.Свойство = Стр.Свойство;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
При создании нового целевого объекта выполняем перенос строк в типовую табличную часть ДополнительныеРеквизиты:
&НаСервере
Функция СоздатьОбъектПоШаблону(ШаблонСсылка)
НовыйОбъект = Справочники.Номенклатура.СоздатьЭлемент();
НовыйОбъект.Наименование = ШаблонСсылка.Наименование;
Для Каждого Стр Из ШаблонСсылка.НастройкиРеквизитов Цикл
// Пропускаем незаполненные в шаблоне свойства
Если Не ЗначениеЗаполнено(Стр.Значение) Тогда
Продолжить;
КонецЕсли;
СтрокаДопРеквизита = НовыйОбъект.ДополнительныеРеквизиты.Добавить();
СтрокаДопРеквизита.Свойство = Стр.Свойство;
СтрокаДопРеквизита.Значение = Стр.Значение;
КонецЦикла;
НовыйОбъект.Записать();
Возврат НовыйОбъект.Ссылка;
КонецФункции
Выясним причину возможных ошибок, с которыми можно столкнуться при переносе значений дополнительных свойств:
УправлениеСвойствами.ОбработкаПроверкиЗаполнения может выдать ошибку незаполненных зависимых полей.УправлениеСвойствами.ЗначенияСвойств(Ссылка) вместо прямых запросов к табличной части.