31 янв. 2017 г.

Произвольная иерархия в СКД

Относительно недавно попал на доработку отчет, содержащий приличное количество кода, который в итоге был выброшен полностью, поскольку возможностей системы компоновки данных вполне хватило для получения необходимого результата. Большая часть этого кода как раз отвечала за построение иерархической структуры. К сожалению, этому разработчику продемонстрировать возможности СКД возможности нет. Но поделиться со всеми остальными коллегами, интересующимися данной темой, это всегда пожалуйста :)

В СКД можно реализовать следующие варианты построения иерархии:
- к основному набору данных достраивается иерархическая структура;
- рекурсивное построение иерархии по одному набору данных.
В этом посте я хочу рассмотреть второй вариант на примере ресурсных спецификаций в демо-базе 1С:ERP 2.


Начнем с простого, получим иерархию детальных записей. Создадим в схеме компоновки набор данных с запросом:

ВЫБРАТЬ
 Т.Ссылка КАК СпецификацияРодитель,
 Т.ПроизводитсяВПроцессе,
 Т.ИсточникПолученияПолуфабриката КАК Спецификация,
 Т.Номенклатура,
 Т.Количество
ИЗ
 Справочник.РесурсныеСпецификации.МатериалыИУслуги КАК Т
ГДЕ
 Т.Ссылка В(&СписокСпецификаций)

Настроим связь набора:
- Спецификация >> СпецификацияРодитель;
- параметр связи СписокСпецификаций, как список параметров;
- условие связи ПроизводитсяВПроцессе
- начальное значение связи - параметр Спецификация, необходимо будет добавить на вкладке "Параметры".


Производим настройки схемы компоновки, добавляем группировку детальных записей.


Проверяем результат:


Для начала неплохо, теперь сделаем так, чтобы в качестве корневого элемента выступала выбранная спецификация. Переделаем запрос, добавим данные начальной спецификации:

ВЫБРАТЬ
 Т.Ссылка КАК СпецификацияРодитель,
 Т.ПроизводитсяВПроцессе,
 Т.ИсточникПолученияПолуфабриката КАК Спецификация,
 Т.Номенклатура,
 Т.Количество
ИЗ
 Справочник.РесурсныеСпецификации.МатериалыИУслуги КАК Т
ГДЕ
 Т.Ссылка В(&СписокСпецификаций)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
 ЗНАЧЕНИЕ(Справочник.РесурсныеСпецификации.ПустаяСсылка),
 ИСТИНА,
 &Спецификация,
 &Спецификация,
 1

Так же переделаем настройки связей, в качестве начального значения связей теперь выступает ЗНАЧЕНИЕ(Справочник.РесурсныеСпецификации.ПустаяСсылка).


Уже лучше:


Теперь сделаем так, чтобы можно было получить в отчете реальное количество материалов. Для этого необходимо ввести второй параметр связи КоличествоСпецификации, через который будет передаваться количество верхнего уровня.

ВЫБРАТЬ
 Т.Ссылка КАК СпецификацияРодитель,
 Т.ПроизводитсяВПроцессе,
 Т.ИсточникПолученияПолуфабриката КАК Спецификация,
 Т.Номенклатура,
 Т.Количество * &КоличествоСпецификации КАК Количество,
 Т.Количество КАК КоличествоНормативное,
 &КоличествоСпецификации КАК КоличествоСпецификации
ИЗ
 Справочник.РесурсныеСпецификации.МатериалыИУслуги КАК Т
ГДЕ
 Т.Ссылка В (&СписокСпецификаций)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
 ЗНАЧЕНИЕ(Справочник.РесурсныеСпецификации.ПустаяСсылка),
 ИСТИНА,
 &Спецификация,
 &Спецификация,
 1,
 1,
 1
Настроим связи наборов, добавим еще одну строку:
- Количество >> КоличествоСпецификации;
- начальное значение 1.


Проверяем результат, получилось то, что надо и без единой строчки кода.


Теперь добавим вариант настроек для получения списка используемых материалов. Здесь особенность в том, что отбор используется для группировки "Номенклатура", а не для отчета в целом.



Ну и напоследок продемонстрирую отчет о входимости спецификации.

ВЫБРАТЬ
 Т.ИсточникПолученияПолуфабриката КАК СпецификацияПриемник,
 Т.Ссылка КАК Спецификация
ИЗ
 Справочник.РесурсныеСпецификации.МатериалыИУслуги КАК Т
ГДЕ
 Т.ПроизводитсяВПроцессе
 И Т.ИсточникПолученияПолуфабриката В(&СписокСпецификаций)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
 
 ЗНАЧЕНИЕ(Справочник.РесурсныеСпецификации.ПустаяСсылка),
 &Спецификация 



Стоит учесть, что с точки зрения производительности данного запроса структура метаданных конфигурации не является оптимальной, поскольку в типовой конфигурации поле ИсточникПолученияПолуфабриката таблицы МатериалыИУслуги не имеет индекса. В следствии чего операции чтения будут приводить к сканированию данных.


Варианты решения:
- добавить индексацию для поля ИсточникПолученияПолуфабриката и отслеживать это изменение при обновлении;
- добавить свой критерий отбора, что так же приведет к созданию необходимого индекса.




Скачать пример отчета



6 комментариев:

  1. Отличное решение, очень помогло построить дерево, только по плановым калькуляциям

    ОтветитьУдалить
  2. Совсем не понятно. Как рекурсивно строится иерархия? Где что и почему необходимо указывать в СКД.
    Пусть на входе таблица (источник не важен): Элемент, Родитель элемента.
    Как СКД для каждого элемента найдет всех подчиненных, а для каждого из подчиненных найдет их подчиненных.
    Пробовал по аналогии. Что бы посмотреть результат выгружал в дерево значений на форме - получаю плоский список.

    ОтветитьУдалить
  3. Этот комментарий был удален автором.

    ОтветитьУдалить
  4. Спасибо, автору. Получилось сделать отчет по вхождению материалов в изделия.

    ОтветитьУдалить
  5. Отличное решение, спасибо. Есть интересный вопрос. Если добавить поле "Вес" для каждой номенклатуры, кроме полуфабрикатов в специи указать вес. Как посчитать итоги по каждой специи в колонке "Вес". На момент вывода специи по полуфабрикату СКД не знает все вложенные специи, как их просуммировать? Если говорить о вашем примере как посчитать итоги по количеству номенклатуры по каждой специи?

    ОтветитьУдалить
  6. Спасибо автору, помог разобраться с этим магическим способом построения иерархии. Испытывал на примере "Иерархия подчиненности документов". В итоге сделал чуть по другому.
    Запрос в наборе данных такой:

    ВЫБРАТЬ
    ЗаказНаПроизводство.ДокументОснование,
    ЗаказНаПроизводство.Ссылка КАК ЗаказНаПроизводство
    ИЗ
    Документ.ЗаказНаПроизводство КАК ЗаказНаПроизводство
    ГДЕ
    ЗаказНаПроизводство.ДокументОснование В(&СписокСсылок)

    На закладке связи настройка: https://drive.google.com/file/d/1S9Wko7iJW7O-z7HFVqm6E95bG2qTtGak/view?usp=sharing

    И отличительный момент: в обработчике ПриКомпоновкеРезультата() в модуле отчета заполнил отдельным запросом параметр СписокСсылок списком документов не имеющих документов-оснований (нулевой уровень иерархии). Это у меня служит начальным списком для дальнейшего раскручивания иерархии в СКД.

    ОтветитьУдалить