Top.Mail.Ru
онлайн-митап
19 декабря в 17:00 МСК
Матрица компетенций: как инструмент для развития разработчика

Расширение механизма представлений под универсальный вывод иерархии подразделений

Кому полезно: любому, кто пишет отчеты в ЗУП 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!

Добавить комментарий

Sidebar