Расширение механизма представлений под универсальный вывод иерархии подразделений
Кому полезно: любому, кто пишет отчеты в ЗУП 3.1
На данный момент веду разработку в ЗУП 3.1. В последнее время при разработке часто стал сталкиваться с необходимостью вывести в отчет или обработку иерархию подразделений в виде таблицы.
Подразделение Корень | Уровень 5 |
Подразделение 1 | Уровень 4 |
Подразделение 2 | Уровень 3 |
Подразделение 3 | Уровень 4 |
Подразделение 4 | Уровень 3 |
Подразделение 5 | Уровень 2 |
Подразделение 6 | Уровень 1 |
Подразделение | Уровень 1 | Уровень 2 | Уровень 3 | Уровень 4 | Уровень 5 |
Подразделение Корень | Подразделение Корень | ||||
Подразделение 1 | Подразделение 1 | Подразделение Корень | |||
Подразделение 2 | Подразделение 2 | Подразделение 1 | Подразделение Корень | ||
Подразделение 3 | Подразделение 3 | Подразделение Корень | |||
Подразделение 4 | Подразделение 4 | Подразделение 3 | Подразделение Корень | ||
Подразделение 5 | Подразделение 5 | Подразделение 4 | Подразделение 3 | Подразделение Корень | |
Подразделение 6 | Подразделение 6 | Подразделение 5 | Подразделение 4 | Подразделение 3 | Подразделение Корень |
Чтобы не писать каждый раз новый запрос я решил расширить механизм представлений, с которым сталкивается каждый, кто пишет отчеты в ЗУП 3. Провел анализ кода и появилось понимание, что механизм представлений очень легко расширяется.
Механизм представлений запускается функцией: ЗарплатаКадрыОбщиеНаборыДанных.ЗаполнитьОбщиеИсточникиДанныхОтчета(Объект, ДополнительныеПоляПредставлений = Неопределено, ТолькоРазрешенные = Истина), где Объект – наш отчет.
Представления заменяются конкретными запросами в функции «ПолучитьЗапросПоПредставлению» модуля «ЗарплатаКадрыОбщиеНаборыДанныхРасширенный», ее то я и доработал.
Функция обрабатывает имена временных таблиц представлений и возвращает запрос с текстом и параметрами. На данный момент существуют следующие ключевые слова используемые в механизме представлений:
- ШтатноеРасписание. Пример применения: отчет «ИзменениеШтатногоРасписания».
- ТекущаяКадроваяРасстановка. Пример применения: отчет «ОрганизационнаяСтруктура».
- ФункциональныеОпцииОрганизаций.
- ФактическиеОтпускаСотрудников. Пример применения: отчет «ФактическиеОтпускаСотрудников».
- ПлановыеНачисленияСотрудников. Пример применения: отчет «КадроваяИсторияСотрудников».
- ПлановыеУдержанияСотрудников. Пример применения: отчет «ПлановыеУдержанияСотрудников».
- СтажиСотрудников. Пример применения: отчет «СтажиСотрудников».
- СвойстваСтатейФинансирования. Пример применения: отчет «СтатистикаПерсонала».
- БухучетЗарплатыСотрудников. Пример применения: отчет «НастройкиБухучета».
- ДанныеУчетаРабочегоВремениСотрудников.
- ДанныеУчетаВремениИСостоянийСотрудников. Пример применения: отчет «УнифицированнаяФормаТ13».
- ПлановоеВремя. Пример применения: отчет «СостоянияСотрудников».
- КадровыеДанныеФизическихЛиц. Пример применения: отчет «АнализВзносовВФонды».
- КадровыеДанныеСотрудников. Пример применения: отчет «КадроваяИсторияСотрудников».
- СотрудникиОрганизации. Пример применения: отчет «НастройкиБухучета».
- НачисленныеДоходыНДФЛ. Пример применения: отчет «НачисленныеДоходыВОтчетахПоНДФЛ».
- ТаблицаРегистра, СрезПоследних, СрезПервых. Пример применения: отчет «КадроваяИсторияСотрудников»
В нашем случае параметры будут «Только разрешенные» и «Уровень». Свою временную таблицу я решил назвать «Представления_ИерархияПодразделений». Добавляем формирование запроса внутрь проверок:
Чтобы получить динамически количество колонок, не прописывая в тексте запроса СКД каждую, в функции «ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц» добавляем код:
ТекстЗапросаПриемник = ПР_ОбщегоНазначенияСервер.ВывестиВсеГруппыВИтоговомЗапросе(ТекстЗапросаПриемник, МаксУровень);
После выполнения процедуры:
В модуле же «ПР_ОбщегоНазначенияСервер» прописал следующие процедуры и функции:
Функция ЗапросПредставленияИерархияПодразделений(МассивИменВТИсточниковПараметров, ПараметрыЗапроса) Экспорт
ТолькоРазрешенные = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗапроса, "ТолькоРазрешенные", Ложь);
УровеньЗапроса = Число(ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыЗапроса, "Уровень", "0"));
Если МассивИменВТИсточниковПараметров.Количество() Тогда
ИмяТабОграничений = МассивИменВТИсточниковПараметров[0];
Иначе
ИмяТабОграничений = "";
КонецЕсли;
ТекстЗапроса = ТекстЗапросаИерархииПодразделений(УровеньЗапроса, ТолькоРазрешенные, ИмяТабОграничений);
Запрос = Новый Запрос(ТекстЗапроса);
МаксУровень = ГлубинаИерархииПодразделенийОрганизаций();
Запрос.УстановитьПараметр("МаксУровеньИерархииПодразделений", МаксУровень);
Возврат Запрос;
КонецФункции
Процедура ПолучитьВТИерархияПодразделений(МВТ, УровеньЗапроса, ТолькоРазрешенные,
ИмяВременнойТаблицы = "ВТИерархияПодразделений", ИмяТабОграничений = "") Экспорт
ТекстЗапроса = ТекстЗапросаИерархииПодразделений(УровеньЗапроса, ТолькоРазрешенные, ИмяТабОграничений);
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.МенеджерВременныхТаблиц = МВТ;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ПОМЕСТИТЬ Представления_ИерархияПодразделений",
ИмяВременнойТаблицы);
Запрос.Выполнить();
КонецПроцедуры
Функция ГлубинаИерархииПодразделенийОрганизаций() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПодчиненностьПодразделенийОрганизаций.Подразделение КАК Подразделение,
| КОЛИЧЕСТВО(ПодчиненностьПодразделенийОрганизаций.ВышестоящееПодразделение) КАК Уровень
|ПОМЕСТИТЬ ВТУровни
|ИЗ
| РегистрСведений.ПодчиненностьПодразделенийОрганизаций КАК ПодчиненностьПодразделенийОрганизаций
|
|СГРУППИРОВАТЬ ПО
| ПодчиненностьПодразделенийОрганизаций.Подразделение
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| МАКСИМУМ(ВТУровни.Уровень) КАК Уровень
|ИЗ
| ВТУровни КАК ВТУровни";
УстановитьПривилегированныйРежим(Истина);
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
УстановитьПривилегированныйРежим(Ложь);
Возврат Выборка.Уровень;
КонецФункции
Функция ВывестиВсеГруппыВИтоговомЗапросе(ТекстЗапроса, МаксУровень) Экспорт
ПоляУровней = Новый Массив;
Для Инд = 1 По МаксУровень Цикл
ПоляУровней.Добавить(СтрШаблон("
| ПредставленияИерархияПодразделений.Уровень%1 КАК Уровень_%1",
Инд));
КонецЦикла;
Возврат СтрЗаменить(ТекстЗапроса, "ПредставленияИерархияПодразделений.Уровень1 КАК Уровень_1", СтрСоединить(ПоляУровней, ","));
КонецФункции
Функция ТекстЗапросаИерархииПодразделений(УровеньЗапроса, ТолькоРазрешенные, ИмяТабОграничений = "")
ТекстЗапроса =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ПодчиненностьПодразделенийОрганизаций.Подразделение КАК Подразделение,
| &МаксУровень - КОЛИЧЕСТВО(ПодчиненностьПодразделенийОрганизаций.ВышестоящееПодразделение) КАК Уровень
|ПОМЕСТИТЬ ВТУровни
|ИЗ
| РегистрСведений.ПодчиненностьПодразделенийОрганизаций КАК ПодчиненностьПодразделенийОрганизаций
|
|СГРУППИРОВАТЬ ПО
| ПодчиненностьПодразделенийОрганизаций.Подразделение
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ПодчиненностьПодразделенийОрганизаций.Подразделение КАК Подразделение,
| МАКСИМУМ(ИСТИНА) КАК Уровень1
|ПОМЕСТИТЬ Представления_ИерархияПодразделений
|ИЗ
| РегистрСведений.ПодчиненностьПодразделенийОрганизаций КАК ПодчиненностьПодразделенийОрганизаций
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТУровни КАК ВТУровни
| ПО ПодчиненностьПодразделенийОрганизаций.ВышестоящееПодразделение = ВТУровни.Подразделение
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТОграничений КАК ВТОграничений
| ПО ПодчиненностьПодразделенийОрганизаций.Подразделение = ВТОграничений.Подразделение
|
|СГРУППИРОВАТЬ ПО
| ПодчиненностьПодразделенийОрганизаций.Подразделение
|
|ИНДЕКСИРОВАТЬ ПО
| Подразделение
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТУровни";
//Добавляем поля уровней
МаксУровень = ГлубинаИерархииПодразделенийОрганизаций();
МаксУровень = Мин(МаксУровень, УровеньЗапроса);
ПоляУровней = Новый Массив;
Для Инд = 1 По МаксУровень Цикл
ПоляУровней.Добавить(СтрШаблон("
|МАКСИМУМ(ВЫБОР
| КОГДА ВТУровни.Уровень = %1
| ТОГДА ВТУровни.Подразделение
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
| КОНЕЦ) КАК Уровень%2",
Инд-1, Инд));
КонецЦикла;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, " МАКСИМУМ(ИСТИНА) КАК Уровень1", СтрСоединить(ПоляУровней, ","));
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&МаксУровень", МаксУровень);
//Добаляем ограничения
Если ЗначениеЗаполнено(ИмяТабОграничений) Тогда
Шаблон = "
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ %1 КАК %1
| ПО ПодчиненностьПодразделенийОрганизаций.Подразделение = %1.Подразделение";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, СтрШаблон(Шаблон, "ВТОграничений"),
СтрШаблон(Шаблон, ИмяТабОграничений));
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, СтрШаблон(Шаблон, "ВТОграничений"), "");
КонецЕсли;
//Добавим Разрешенные
Если ТолькоРазрешенные Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,
"ВЫБРАТЬ
|",
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
|");
КонецЕсли;
Возврат ТекстЗапроса;
КонецФункции
Осталось понять, как этим всем пользоваться
Добавляем в текст запроса СКД код:
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Уровень1,
ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Подразделение
ПОМЕСТИТЬ Представления_ИерархияПодразделений
ИЗ
ВТВсяКадроваяИстория КАК ВТВсяКадроваяИстория
ГДЕ
"ТолькоРазрешенные" = ИСТИНА
И "Уровень" = 9
;
////////////////////////////////////////////////////////////////////////////////
Где «ВТВсяКадроваяИстория» временная таблица в которой есть поле «Подразделение». Служит для ограничения нашей таблицы подразделениями. Если мы не хотим ни какого ограничения, то можно тут указать любую существующую в конфигурации таблицу, например «Справочник.ПодразделенияОрганизаций».
Параметром «ТолькоРазрешеные» мы указываем, устанавливать ли в итоговом запросе инструкцию «Пвзрешенные» или нет. Параметр «Уровень» указывает максимальный уровень, если он больше чем текущий в базе, то обрежется до максимума по базе.
Далее используем, присоединяя в нужном месте. Если необходимо получить все уровни таблицы, при этом мы не понимаем заранее сколько уровней будет, то добавляем код выборку туда, где присоединили таблицу:
Представления_ИерархияПодразделений.Уровень1 КАК Уровень_1,
И тогда функция ВывестиВсеГруппыВИтоговомЗапросе преобразует ее в конечном запросе в вид:
ПредставленияИерархияПодразделений.Уровень1 КАК Уровень_1,
ПредставленияИерархияПодразделений.Уровень2 КАК Уровень_2,
ПредставленияИерархияПодразделений.Уровень3 КАК Уровень_3,
ПредставленияИерархияПодразделений.Уровень4 КАК Уровень_4,
ПредставленияИерархияПодразделений.Уровень5 КАК Уровень_5,
ПредставленияИерархияПодразделений.УровеньN КАК Уровень_N,
Где N максимальная глубина иерархии.
Comments
So empty here ... leave a comment!