Хочу сразу обратить внимание уважаемых коллег на то, что статья представляет собой учебный материал по работе с регистрами сведений, имеющими ресурс «Период завершения», и вряд ли будет интересна и полезна гуру (хотя, как знать). Вопросы и конструктивная критика приветствуются
Кадровая история сотрудников организации хранится в регистре сведений «РаботникиОрганизаций» (в пользовательском режиме – «Кадровая история сотрудников (по юрлицам)» или «Сотрудники организации»). Регистраторами для данного регистра являются документы приема в организацию, кадрового перемещения, увольнения из организации и переноса данных.
Регистр «РаботникиОрганизаций», как и многие другие, такие как «ПлановыеНачисленияРаботниковОрганизаций», «ПлановыеУдержанияРаботниковОрганизаций», «СостояниеРаботниковОрганизаций» и т.п.) в своем составе имеют одноименный ресурс с добавлением постфикса «Завершения». Приведем примеры (в конфигурации их гораздо больше):
№ п/п | Регистр сведений | Ресурс (основной) | Ресурс завершения |
1 | РаботникиОрганизаций | ПодразделениеОрганизации | ПодразделениеОрганизацииЗавершения |
Должность | ДолжностьЗавершения | ||
ГрафикРаботы | ГрафикРаботыЗавершения | ||
2 | ПлановыеНачисленияРаботниковОрганизаций | ВидРасчета | ВидРасчетаЗавершения |
Показатель1 | Показатель1Завершения | ||
3 | СостояниеРаботников | Состояние | СостояниеЗавершения |
И, кроме этого, для измерения «Период» имеется ресурс «ПериодЗавершения». Эти два свойства записи определяют состояние объекта на временной оси.
Ресурс «ПериодЗавершения» показывает, что запись характеризуется еще и концом своего действия (в случае, если ресурс заполнен). В этом случае с даты, указанной в ресурсе «ПериодЗавершения», актуальными становятся ресурсы с постфиксом «Завершения» («ДолжностьЗавершения», «ГрафикРаботыЗавершения» и т.д.)
Для того, чтобы понимать, почему была разработана именно такая архитектура периодических регистров сведений, характеризующихся окончанием периода действия, рекомендую ознакомиться со статьей ИТС Регистрация изменений на некоторый промежуток времени с возвратом в исходное состояние. Также в статье Запросы к регистрам сведений с реквизитом "ПериодЗавершения" обсуждаются плюсы и минусы такого решения.
Лирическое отступление закончим. Перейдем непосредственно к задаче получения кадровой истории сотрудника организации (далее, сотрудника). Для того, чтобы не загромождать статью кодом, в запросе будем получать только подразделение сотрудника. Чтобы получить должность, график работы и подобные ресурсы, нужно использовать точно такие же конструкции с «ВЫБОР», которые применяются в приведенных ниже запросах. Но для того, чтобы наглядно показать откуда, почему и какие данные получаются (в целях обучения), в результат запросов помещены дополнительные поля, которые можно не использовать в своих разработках в будущем.
Постановка задачи:
Необходимо получить кадровую историю сотрудника в следующем виде (с отбором по периоду):
Следует учесть тот момент, что документом «Кадровое перемещение организаций АР000000002 от 14.01.2015 15:27:05» сотрудник был переведен в Отдел продаж с 14.01.15 по 04.03.15 (для других кадровых перемещений период завершения не заполнялся):
Последовательность решения:
1. Находим подразделение сотрудника на дату начала периода (пусть это будет 01.01.15 г.). Для этого используем виртуальную таблицу среза последних регистра сведений «РаботникиОрганизаций», параметризованную по сотруднику и дате начала периода
ВЫБРАТЬ
"1" КАК НомерПодзапроса,
РаботникиОрганизацийСрезПоследних.Сотрудник КАК Сотрудник,
ВЫБОР
КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения <= &НачалоПериода
И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
ТОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения
ИНАЧЕ РаботникиОрганизацийСрезПоследних.Период
КОНЕЦ КАК Период,
ВЫБОР
КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения <= &НачалоПериода
И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
ТОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения
ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизации
КОНЕЦ КАК ПодразделениеОрганизации,
ВЫБОР
КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения <= &НачалоПериода
И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
ТОГДА РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостоянияЗавершения
ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния
КОНЕЦ КАК ПричинаИзмененияСостояния,
РаботникиОрганизацийСрезПоследних.Регистратор
ИЗ
РегистрСведений.РаботникиОрганизаций.СрезПоследних(&НачалоПериода, Сотрудник = &Сотрудник) КАК РаботникиОрганизацийСрезПоследних
Результат подзапроса № 1:
В подзапросе № 1 используется конструкция «ВЫБОР» с проверкой значения ресурса «ПериодЗавершения». Если период завершения заполнен и наступил этот период, возвращаем ресурс с постфиксом «Завершения», иначе возвращаем обычный ресурс (или измерение «Период»). Повторюсь, что данную конструкцию необходимо использовать для получения любых ресурсов, характеризующихся датой окончания действия (Должность, ГрафикРаботы и т.п.)
Также можно увидеть, что в подзапрос включено поле «Номер подзапроса» для визуального отображения в будущем, какой подзапрос какие данные вернул (напомню, что это поле для решения поставленной задачи необязательно).
2. Находим подразделения сотрудника с даты, следующей за датой начала периода, и по дату окончания периода (пусть это будет 31.12.15 г.) Для этого используем физическую таблицу регистра сведений «РаботникиОрганизаций» с отбором по сотруднику и датам начала и окончания периода
ВЫБРАТЬ
"2" КАК НомерПодзапроса,
РаботникиОрганизаций.Сотрудник КАК Сотрудник,
РаботникиОрганизаций.Период КАК Период,
РаботникиОрганизаций.ПодразделениеОрганизации КАК ПодразделениеОрганизации,
РаботникиОрганизаций.ПричинаИзмененияСостояния КАК ПричинаИзмененияСостояния,
РаботникиОрганизаций.Регистратор
ИЗ
РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
ГДЕ
РаботникиОрганизаций.Сотрудник = &Сотрудник
И РаботникиОрганизаций.Период > &НачалоПериода
И РаботникиОрганизаций.Период <= &КонецПериода
Результат подзапроса № 2:
3. Находим подразделения сотрудника по датам завершения событий с даты, следующей за датой начала периода, и по дату окончания периода
ВЫБРАТЬ
"3" КАК НомерПодзапроса,
РаботникиОрганизаций.Сотрудник КАК Сотрудник,
РаботникиОрганизаций.ПериодЗавершения КАК Период,
РаботникиОрганизаций.ПодразделениеОрганизацииЗавершения КАК ПодразделениеОрганизации,
РаботникиОрганизаций.ПричинаИзмененияСостоянияЗавершения КАК ПричинаИзмененияСостояния,
РаботникиОрганизаций.Регистратор
ИЗ
РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
ГДЕ
РаботникиОрганизаций.Сотрудник = &Сотрудник
И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
И РаботникиОрганизаций.ПериодЗавершения > &НачалоПериода
И РаботникиОрганизаций.ПериодЗавершения <= &КонецПериода
Результат подзапроса № 3:
4. Объединим подзапросы конструкцией «ОБЪЕДИНИТЬ ВСЕ» и поместим во временную таблицу
ВЫБРАТЬ
"1" КАК НомерПодзапроса,
РаботникиОрганизацийСрезПоследних.Сотрудник КАК Сотрудник,
ВЫБОР
КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения <= &НачалоПериода
И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
ТОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения
ИНАЧЕ РаботникиОрганизацийСрезПоследних.Период
КОНЕЦ КАК Период,
ВЫБОР
КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения <= &НачалоПериода
И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
ТОГДА РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизацииЗавершения
ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПодразделениеОрганизации
КОНЕЦ КАК ПодразделениеОрганизации,
ВЫБОР
КОГДА РаботникиОрганизацийСрезПоследних.ПериодЗавершения <= &НачалоПериода
И РаботникиОрганизацийСрезПоследних.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
ТОГДА РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостоянияЗавершения
ИНАЧЕ РаботникиОрганизацийСрезПоследних.ПричинаИзмененияСостояния
КОНЕЦ КАК ПричинаИзмененияСостояния,
РаботникиОрганизацийСрезПоследних.Регистратор
ПОМЕСТИТЬ ВТ_ДатыСобытий
ИЗ
РегистрСведений.РаботникиОрганизаций.СрезПоследних(&НачалоПериода, Сотрудник = &Сотрудник) КАК РаботникиОрганизацийСрезПоследних
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"2",
РаботникиОрганизаций.Сотрудник,
РаботникиОрганизаций.Период,
РаботникиОрганизаций.ПодразделениеОрганизации,
РаботникиОрганизаций.ПричинаИзмененияСостояния,
РаботникиОрганизаций.Регистратор
ИЗ
РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
ГДЕ
РаботникиОрганизаций.Сотрудник = &Сотрудник
И РаботникиОрганизаций.Период > &НачалоПериода
И РаботникиОрганизаций.Период <= &КонецПериода
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"3",
РаботникиОрганизаций.Сотрудник,
РаботникиОрганизаций.ПериодЗавершения,
РаботникиОрганизаций.ПодразделениеОрганизацииЗавершения,
РаботникиОрганизаций.ПричинаИзмененияСостоянияЗавершения,
РаботникиОрганизаций.Регистратор
ИЗ
РегистрСведений.РаботникиОрганизаций КАК РаботникиОрганизаций
ГДЕ
РаботникиОрганизаций.Сотрудник = &Сотрудник
И РаботникиОрганизаций.ПериодЗавершения <> ДАТАВРЕМЯ(1, 1, 1)
И РаботникиОрганизаций.ПериодЗавершения > &НачалоПериода
И РаботникиОрганизаций.ПериодЗавершения <= &КонецПериода
Временная таблица ВТ_ДатыСобытий будет содержать следующие данные:
Как видно, для того, чтобы получить все даты начала нахождения сотрудника в каком-либо подразделении, нам необходимо было формировать три подзапроса (если устанавливать разные даты начала и окончания периода, то можно увидеть что кадровую историю сотрудника за период можно получить с помощью одного или двух подзапросов, чего будет явно недостаточно для общего случая).
5. Получаем итоговую таблицу (текст получения временной таблицы ВТ_ДатыСобытий не повторяю). Для этого временную таблицу с датами наступления событий соединяем саму с собой по сотруднику и условию того, что дата начала события должна быть меньше даты его окончания.
Если сотрудник работает и дата окончания меньше даты события очередного кадрового документа, «Дату по» ставим равной дате окончания.
Если сотрудника уволили, дату начала данного события устанавливаем на следующую дату за последним рабочим днем, а дату окончания устанавливаем в NULL (нет там уже никакой протяженности во времени).
Подразделение после увольнения оставляем равным последнему подразделению сотрудника.
//получили ВТ_ДатыСобытий в п. 4
;
ВЫБРАТЬ
ДатыНачала.Сотрудник,
ДатыНачала.ПодразделениеОрганизации,
ДатыНачала.Период КАК ДатаС,
ВЫБОР
КОГДА МИНИМУМ(ДатыОкончания.Период) ЕСТЬ NULL
ТОГДА ВЫБОР
КОГДА ДатыНачала.ПричинаИзмененияСостояния = ЗНАЧЕНИЕ(Перечисление.ПричиныИзмененияСостояния.Увольнение)
ТОГДА NULL
ИНАЧЕ &КонецПериода
КОНЕЦ
ИНАЧЕ ДОБАВИТЬКДАТЕ(МИНИМУМ(ДатыОкончания.Период), ДЕНЬ, -1)
КОНЕЦ КАК ДатаПо,
ДатыНачала.Регистратор
ИЗ
ВТ_ДатыСобытий КАК ДатыНачала
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ДатыСобытий КАК ДатыОкончания
ПО ДатыНачала.Сотрудник = ДатыОкончания.Сотрудник
И ДатыНачала.Период < ДатыОкончания.Период
СГРУППИРОВАТЬ ПО
ДатыНачала.Сотрудник,
ДатыНачала.Период,
ДатыНачала.ПодразделениеОрганизации,
ДатыНачала.Регистратор,
ДатыНачала.ПричинаИзмененияСостояния
УПОРЯДОЧИТЬ ПО
ДатаС
Результат запроса:
Таким образом, мы получили кадровую историю сотрудника (периодами).
P.S. В файле находится архив с данной статьей в формате MS Word и файл запроса.