Иерархию подразделений в отчёте ЗУП 3 удобнее всего получать не новым запросом в каждом отчёте, а собственным представлением в механизме общих наборов данных ЗарплатаКадрыОбщиеНаборыДанных. Уровень подразделения считается по регистру сведений ПодчиненностьПодразделенийОрганизаций как количество вышестоящих подразделений, а предки раскладываются по колонкам Уровень1…УровеньN. После этого в любом отчёте на СКД достаточно сослаться на временную таблицу Представления_ИерархияПодразделений и соединиться с ней по подразделению.
Ниже: как устроен механизм представлений, запрос иерархии, подключение своего представления расширением и использование в СКД.
Задача: структура по уровням в одной строке
Руководители почти всегда хотят видеть не только подразделение сотрудника, но и всю цепочку: дирекция → департамент → отдел → группа. В справочнике это дерево, а в отчёте нужна плоская таблица:
| Подразделение | Уровень 1 | Уровень 2 | Уровень 3 | Уровень 4 |
|---|---|---|---|---|
| Дирекция | Дирекция | |||
| Коммерческий департамент | Дирекция | Коммерческий департамент | ||
| Отдел продаж | Дирекция | Коммерческий департамент | Отдел продаж | |
| Группа опта | Дирекция | Коммерческий департамент | Отдел продаж | Группа опта |
Тогда в СКД можно группировать по любому уровню и строить сводные по департаментам независимо от того, на какой глубине числится сотрудник.
Как работает механизм представлений ЗУП
Кто писал отчёты в ЗУП 3, видел в схемах запросы к таблицам вида Представления_КадровыеДанныеСотрудников или Представления_ПлановыеНачисленияСотрудников. Таких таблиц в базе нет: перед выполнением отчёт вызывает
ЗарплатаКадрыОбщиеНаборыДанных.ЗаполнитьОбщиеИсточникиДанныхОтчета(ЭтотОбъект);и механизм заменяет каждую «представленческую» временную таблицу настоящим запросом. Параметры представлению передаются прямо в тексте запроса СКД — условиями вида "ИмяПараметра" = Значение в ГДЕ. Подбор запроса по имени представления выполняет функция ПолучитьЗапросПоПредставлению модуля ЗарплатаКадрыОбщиеНаборыДанныхРасширенный.
В типовой поставке уже есть представления для штатного расписания, текущей кадровой расстановки, фактических отпусков, плановых начислений и удержаний, стажей, кадровых данных сотрудников и физлиц, данных учёта времени, начисленных доходов НДФЛ, а также универсальные ТаблицаРегистра, СрезПоследних, СрезПервых. Иерархии подразделений среди них нет — добавим.
Запрос иерархии подразделений
Регистр ПодчиненностьПодразделенийОрганизаций хранит для каждого подразделения всех его вышестоящих. Значит, глубина подразделения — это количество записей с ним в измерении Подразделение.

// 1. Глубина каждого подразделения: 0 — корень
ВЫБРАТЬ
Подразделения.Ссылка КАК Подразделение,
КОЛИЧЕСТВО(Подчиненность.ВышестоящееПодразделение) КАК Глубина
ПОМЕСТИТЬ ВТГлубина
ИЗ
Справочник.ПодразделенияОрганизаций КАК Подразделения
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПодчиненностьПодразделенийОрганизаций КАК Подчиненность
ПО Подчиненность.Подразделение = Подразделения.Ссылка
СГРУППИРОВАТЬ ПО
Подразделения.Ссылка
;
// 2. Все предки подразделения плюс оно само
ВЫБРАТЬ
Подчиненность.Подразделение КАК Подразделение,
Подчиненность.ВышестоящееПодразделение КАК Предок
ПОМЕСТИТЬ ВТПредки
ИЗ
РегистрСведений.ПодчиненностьПодразделенийОрганизаций КАК Подчиненность
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Подразделения.Ссылка,
Подразделения.Ссылка
ИЗ
Справочник.ПодразделенияОрганизаций КАК Подразделения
;
// 3. Раскладываем предков по колонкам уровней
ВЫБРАТЬ
Предки.Подразделение КАК Подразделение,
МАКСИМУМ(ВЫБОР КОГДА Глубина.Глубина = 0 ТОГДА Предки.Предок КОНЕЦ) КАК Уровень1,
МАКСИМУМ(ВЫБОР КОГДА Глубина.Глубина = 1 ТОГДА Предки.Предок КОНЕЦ) КАК Уровень2,
МАКСИМУМ(ВЫБОР КОГДА Глубина.Глубина = 2 ТОГДА Предки.Предок КОНЕЦ) КАК Уровень3
ПОМЕСТИТЬ Представления_ИерархияПодразделений
ИЗ
ВТПредки КАК Предки
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТГлубина КАК Глубина
ПО Предки.Предок = Глубина.Подразделение
СГРУППИРОВАТЬ ПО
Предки.Подразделение
ИНДЕКСИРОВАТЬ ПО
ПодразделениеПеред использованием проверьте на своей базе, не хранит ли регистр запись подразделения «на само себя»: если хранит, глубину нужно уменьшить на единицу, а второй блок ОБЪЕДИНИТЬ ВСЕ убрать.
Колонки уровней генерируются кодом — так их число задаётся параметром:
// Возвращает текст полей Уровень1..УровеньN для запроса иерархии.
Функция ТекстПолейУровней(КоличествоУровней)
Поля = Новый Массив;
Для НомерУровня = 1 По КоличествоУровней Цикл
Поля.Добавить(СтрШаблон(
"МАКСИМУМ(ВЫБОР КОГДА Глубина.Глубина = %1 ТОГДА Предки.Предок КОНЕЦ) КАК Уровень%2",
Формат(НомерУровня - 1, "ЧН=0; ЧГ="), Формат(НомерУровня, "ЧГ=")));
КонецЦикла;
Возврат СтрСоединить(Поля, "," + Символы.ПС);
КонецФункцииДля ограничения по правам добавьте РАЗРЕШЕННЫЕ в первый запрос пакета, если представление вызвано с параметром ТолькоРазрешенные.
Подключаем представление расширением
Типовой модуль править не нужно — делаем расширение, заимствуем общий модуль ЗарплатаКадрыОбщиеНаборыДанныхРасширенный и перехватываем функцию подбора запроса аннотацией &Вместо. Логика перехвата:
- Если имя временной таблицы —
Представления_ИерархияПодразделений, собираем свойЗапросс текстом из предыдущего раздела, параметры читаем из переданной структуры (ТолькоРазрешенные,Уровень) черезОбщегоНазначенияКлиентСервер.СвойствоСтруктуры. - Иначе вызываем
ПродолжитьВызов(...)с теми же параметрами — работает типовая реализация.
Сигнатуру перехватчика копируйте из функции своего релиза ЗУП один в один: состав параметров между релизами может отличаться, а расширение с несовпадающей сигнатурой не подключится.
Сам текст запроса и генерацию полей держу в отдельном общем модуле расширения — так их можно вызвать и вне механизма представлений, например в обработке, поместив результат в менеджер временных таблиц.
Использование в отчёте на СКД
В запрос набора данных добавляем «заглушку» представления с параметрами в условии:
ВЫБРАТЬ
ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Подразделение,
ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Уровень1,
ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Уровень2,
ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Уровень3
ПОМЕСТИТЬ Представления_ИерархияПодразделений
ИЗ
Справочник.ПодразделенияОрганизаций КАК Подразделения
ГДЕ
"ТолькоРазрешенные" = ИСТИНА
И "Уровень" = 3
;Дальше соединяем основную выборку с Представления_ИерархияПодразделений по полю Подразделение, выводим Уровень1…Уровень3 и группируем по ним в настройках СКД. В модуле отчёта перед компоновкой вызываем ЗаполнитьОбщиеИсточникиДанныхОтчета — в типовых отчётах ЗУП это уже сделано, в своих не забудьте.
Сколько колонок закладывать
Можно генерировать колонки динамически под фактическую глубину структуры, но тогда придётся править и функцию замены представлений в тексте запроса — ещё одна точка перехвата. На практике я закладываю фиксированное число уровней с запасом (шесть–восемь) и в настройках отчёта не вывожу пустые колонки. Структуры глубже восьми уровней в реальных организациях почти не встречаются.
Типичные ошибки
- Корневые подразделения выпадают. Глубину считают только по регистру, без левого соединения со справочником: у корня записей в регистре нет.
- Сдвиг уровней на единицу. Регистр в вашем релизе может включать подразделение в его собственных вышестоящих — проверьте на данных.
- Представление не подменяется. Имя временной таблицы в СКД не совпадает с обрабатываемым в расширении или отчёт не вызывает
ЗаполнитьОбщиеИсточникиДанныхОтчета. - Расширение не применяется после обновления. Изменилась сигнатура типовой функции — сверяйте её при каждом обновлении ЗУП.
Такие отчёты для кадровиков и руководства я делаю в рамках доработки ЗУП; общий подход к построению сложных схем описан на странице отчётов на СКД.
Итог
- Иерархию подразделений в ЗУП выгодно оформить как своё представление механизма общих наборов данных.
- Уровень считается по регистру
ПодчиненностьПодразделенийОрганизаций, предки раскладываются по колонкам черезВЫБОРпо глубине. - Подключение — расширением с
&ВместоиПродолжитьВызовдля остальных представлений. - В СКД достаточно «заглушки»
Представления_ИерархияПодразделенийс параметрами вГДЕи соединения по подразделению. - Фиксированное число уровней с запасом проще в сопровождении, чем динамические колонки.




