При решении производственных задач разузлования номенклатуры разработчики часто сталкиваются со сложным поведением Системы компоновки данных (СКД). Когда требуется сформировать многоуровневое дерево состава изделия, стандартная иерархия по номенклатуре начинает работать некорректно: одинаковые материалы, входящие в состав разных полуфабрикатов, схлопываются в одну ветку либо многократно суммируют свои числовые показатели на вышестоящих узлах.
Разберем природу этой проблемы и рассмотрим несколько способов ее решения.
Проанализируем структуру данных дерева спецификаций. В отличие от стандартной иерархии справочников 1С (где каждый элемент имеет только одного строго заданного родителя по отношению 1:N), разузлование спецификаций представляет собой ориентированный граф. Один и тот же материал или узел может входить сразу в несколько разных полуфабрикатов одного и того же готового изделия.
Если в схеме компоновки данных в качестве ключа связи или поля группировки указано поле Номенклатура, механизм СКД не может различить контексты вхождения одной и той же позиции в разные узлы. В результате платформа объединяет одинаковые элементы, что приводит к искажению структуры отчета и неверному подсчету итоговых количественных и суммовых ресурсов.
Рассмотрим наиболее гибкий способ вывода произвольной иерархии через СКД. Чтобы система четко различала каждое вхождение номенклатуры в дерево, каждой строке присваивается уникальный идентификатор.
ИД_Узла и ИД_Родителя:
ТЗДанные = Новый ТаблицаЗначений;
ТЗДанные.Колонки.Добавить("ИД_Узла", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(36)));
ТЗДанные.Колонки.Добавить("ИД_Родителя", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(36)));
ТЗДанные.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗДанные.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Строка(Новый УникальныйИдентификатор) или строковый номер узла, а в ИД_Родителя записываем идентификатор родительской ветки. Для корневого элемента значение ИД_Родителя остается пустым.ИД_Узла.ИД_Родителя.ИД_Узла.ИД_Узла задаем свойство Выражение представления: Номенклатура.Посмотрим на альтернативный подход, который упрощает логику отчета за счет предварительной обработки данных во внешней функции. Этот способ отлично подходит для производственного учета, где важно видеть переделы.
Продукция, УровеньПередела, Передел (спецификация узла), Материал и ресурсные поля.Продукция.УровеньПередела.Передел.Материал.При такой структуре исключаются коллизии с циклическими ссылками и объединением одинаковых материалов, а итоги по каждому переделу и изделию в целом рассчитываются СКД по стандартным правилам суммирования ресурсов.
Если иерархия строится запросом непосредственно внутри схемы компоновки, связь следует настраивать не по номенклатуре, а по спецификациям узлов.
ВЫБРАТЬ
Спецификация.Ссылка КАК СпецификацияРодитель,
Спецификация.Номенклатура КАК Полуфабрикат,
ИсходныеКомплектующие.Номенклатура КАК Материал,
ИсходныеКомплектующие.Количество КАК Количество
ИЗ
Справочник.СпецификацииНоменклатуры.ИсходныеКомплектующие КАК ИсходныеКомплектующие
ГДЕ
Спецификация.Ссылка В (&СписокРодителей)
&СписокРодителей для рекурсивного разузлования на каждом последующем шаге.При использовании рекурсивных иерархий обратим внимание на вкладку «Ресурсы» схемы компоновки данных. По умолчанию СКД пытается сложить значения всех родительских и дочерних строк. Чтобы исключить некорректный двойной счет:
ВычислитьВыражение() с указанием контекста "Группировка" или "Иерархия".