При разработке сложных иерархических структур в среде 1С:Предприятие 7.7 разработчики часто сталкиваются с архитектурным ограничением: стандартный механизм подчинения справочников (Property Владелец) жестко ориентирован на связь «Элемент — Элемент». Попытка программно или интерактивно назначить владельцем элемента Группу (родительский узел дерева) заканчивается неудачей. Платформа просто не позволяет этого сделать на уровне ядра.
В этой статье мы подробно разберем, почему это ограничение существует, как его обойти и как реализовать гибкую систему классификации товаров (например, на основе свойств), используя альтернативные подходы к архитектуре метаданных.
Для начала проанализируем, почему штатный механизм не работает. В платформе 7.7 структура таблиц базы данных (файлы .dbf или таблицы SQL) для подчиненных справочников содержит системное поле PARENTEXT. Это поле хранит идентификатор (ID) объекта-владельца. Однако на уровне программного кода платформы зашита проверка: если объект, чей ID записывается в PARENTEXT, имеет признак IsFolder = 1 (то есть является группой), система блокирует запись или некорректно отображает данные в списках.
Проанализируем последствия этой проблемы: мы не можем стандартными средствами привязать, например, «Нормы расхода» или «Специфические свойства» сразу к целой папке номенклатуры (например, к папке «Процессоры»). Нам пришлось бы привязывать их к каждому элементу внутри папки, что порождает колоссальную избыточность данных и затрудняет поддержку.
Рассмотрим самый эффективный способ обхода — отказ от штатного механизма «Подчиненный справочник». Вместо того чтобы помечать справочник как подчиненный в конфигураторе, мы сделаем его независимым (плоским) и добавим в него необходимые связи вручную.
Разберем алгоритм действий по шагам:
Владелец в «Не определено».ВладелецГруппа.Справочник.ОсновнойСправочник (тот, группам которого мы хотим подчинять элементы).Теперь мы получили структуру, где в поле ВладелецГруппа можно записать ссылку на любой узел основного справочника — будь то конечный элемент или папка любого уровня вложенности.
Чтобы пользователю было так же удобно работать с этой структурой, как и со стандартным подчиненным справочником, нам необходимо реализовать визуальную связь. Посмотрим, как это сделать программно в форме списка.
Предположим, у нас есть форма основного справочника, и мы хотим по кнопке открывать наш «псевдо-подчиненный» справочник с фильтром по текущей группе. Проанализируем пример кода:
// В форме основного справочника (например, Номенклатура)
Процедура ОткрытьПодчиненныеСвойства()
Перем Конт;
ТекущийОбъект = ТекущийЭлемент();
// Открываем форму списка справочника "Свойства"
ОткрытьФорму("Справочник.СвойстваНоменклатуры", Конт);
// Устанавливаем фильтр по текущему элементу или группе
Конт.ИспользоватьОтбор("ВладелецГруппа", ТекущийОбъект);
КонецПроцедуры
Важный нюанс: метод ИспользоватьОтбор будет работать только в том случае, если для реквизита ВладелецГруппа в конфигураторе установлен флажок Сортировка (что создает индекс по этому полю в базе данных). Без этого индекса быстрая фильтрация в 7.7 невозможна.
Разберем практический кейс из обсуждения: автоматическое распределение товаров по папкам на основе характеристик, спарсенных с внешних ресурсов (например, Onliner.by). Когда у нас тысячи товаров, ручная сортировка невозможна. Нам нужно задать правила для групп.
Для этого создадим справочник ПравилаКлассификации со следующей структурой:
Рассмотрим логику работы автоматического классификатора. При импорте нового товара, например, «Оперативная память DDR3 8Gb», мы имеем набор формализованных данных. Нам нужно найти подходящую папку в справочнике Номенклатура.
Проанализируем пример алгоритма классификации:
// Функция поиска подходящей группы для нового товара
Функция НайтиГруппуПоСвойствам(ТаблицаСвойствТовара)
СпрПравила = СоздатьОбъект("Справочник.ПравилаКлассификации");
СпрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
// Перебираем правила классификации
СпрПравила.ВыбратьЭлементы();
Пока СпрПравила.ПолучитьЭлемент() = 1 Цикл
// Проверяем, соответствуют ли свойства товара текущему правилу
Если ТоварСоответствуетПравилу(ТаблицаСвойствТовара, СпрПравила) = 1 Тогда
// Если нашли совпадение, возвращаем группу-владельца из правила
Возврат СпрПравила.ГруппаВладелец;
КонецЕсли;
КонецЦикла;
Возврат ГруппаНераспределенные;
КонецФункции
В этом случае связка «Элемент подчиненного справочника (Правило) — Группа основного (Номенклатура)» работает идеально. Мы один раз руками прописываем в справочнике ПравилаКлассификации, что все товары со свойством «Тип памяти» равным «DDR3» и «Объем» равным «8Гб» должны попадать в конкретную папку. Программа при импорте просто считывает эти настройки.
Рассмотрим сильные стороны решения:
Проанализируем слабые стороны:
ПриОткрытии или через ИспользоватьОтбор.Выяснив причину ограничения 1С 7.7, мы пришли к выводу, что штатное подчинение элемента группе невозможно из-за архитектуры поля PARENTEXT. Однако, используя реквизиты с типом Справочник и механизм ИспользоватьОтбор, мы можем полностью эмулировать нужный функционал. Это не только решает проблему «красивого отображения», но и позволяет строить мощные системы автоматической обработки данных, такие как парсеры прайс-листов и классификаторы номенклатуры по техническим характеристикам.