Как корректно получить актуальное подразделение сотрудника в ЗУП 3.1 с учетом временных переводов

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом Управленческий учет
← На главную

При разработке собственных отчетов или механизмов заполнения документов в конфигурации 1С:Зарплата и управление персоналом 3.1 программисты часто сталкиваются с ситуацией, когда стандартный запрос к виртуальной таблице СрезПоследних регистра сведений КадроваяИсторияСотрудников возвращает некорректные данные. Типичный пример: сотрудник был временно переведен в другое подразделение, срок перевода истек, но запрос всё равно показывает его в "временном" подразделении. Разберем подробно, почему так происходит и как правильно решать эту задачу в современных реалиях платформы 1С.

Проблема использования СрезПоследних в ЗУП 3.1

Проанализируем классический подход, который работал в старых версиях программ (например, ЗУП 2.5). Когда мы делаем запрос к РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(&Период, ), система ищет последнюю запись в регистре, дата которой меньше или равна &Период. В ЗУП 3.1 при оформлении документа Кадровый перевод на определенный срок (с указанием даты "по") в регистре сведений создается запись. Однако особенность архитектуры заключается в том, что по окончании срока перевода система не создает новую автоматическую запись о "возврате" сотрудника в исходное подразделение в этом же регистре.

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

Решение 1: Использование типовых процедур общего модуля

Самый правильный и надежный способ получения кадровых данных в ЗУП 3.1 — использование программного интерфейса (API), заложенного разработчиками фирмы "1С". Рассмотрим применение функции СотрудникиОрганизации из общего модуля КадровыйУчет. Этот метод автоматически учитывает все нюансы: временные переводы, совместительство, интервалы и даже периоды отсутствия.

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


ПараметрыПолученияСотрудников = КадровыйУчет.ПараметрыПолученияСотрудниковОрганизацийПоСпискуФизическихЛиц();
ПараметрыПолученияСотрудников.Организация = Объект.Организация;
ПараметрыПолученияСотрудников.Подразделение = Объект.Подразделение;
ПараметрыПолученияСотрудников.НачалоПериода = Объект.Дата;
ПараметрыПолученияСотрудников.ОкончаниеПериода = Объект.Дата;

// Получаем таблицу сотрудников с учетом всех кадровых изменений
ТаблицаСотрудников = КадровыйУчет.СотрудникиОрганизации(Истина, ПараметрыПолученияСотрудников);

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

Решение 2: Работа с интервальными регистрами в запросе

Если по каким-то причинам вам необходимо написать прямой запрос (например, внутри сложной схемы компоновки данных), следует обратить внимание на специализированные интервальные регистры. В ЗУП 3.1 для кадровой истории это РегистрСведений.КадроваяИсторияСотрудниковИнтервальный.

В отличие от обычного периодического регистра, интервальный содержит два важных поля: ДатаНачала и ДатаОкончания. Это позволяет нам точно определить состояние сотрудника на любую секунду времени. Разберем по шагам, как построить условие в таком запросе:

  1. Выбираем необходимые поля: Сотрудник, Подразделение, Должность.
  2. Устанавливаем фильтр по периоду так, чтобы искомая дата попадала внутрь интервала.
  3. Обязательно учитываем, что поле ДатаОкончания для актуальных (бессрочных) записей может содержать "пустую" дату или специализированное значение "конечной" даты (31.12.3999).

Пример структуры запроса к интервальному регистру:


ВЫБРАТЬ
    КадроваяИстория.Сотрудник,
    КадроваяИстория.Подразделение
ИЗ
    РегистрСведений.КадроваяИсторияСотрудниковИнтервальный КАК КадроваяИстория
ГДЕ
    КадроваяИстория.ДатаНачала <= &Период
    И КадроваяИстория.ДатаОкончания >= &Период
    И КадроваяИстория.Подразделение = &Подразделение

Такой подход корректно обработает ситуацию временного перевода: когда &Период выйдет за рамки ДатаОкончания временной записи, условие ГДЕ ее отсечет, и будет выбрана запись "возврата" (которая в интервальном регистре представлена отдельной строкой).

Решение 3: Использование временных таблиц через менеджер кадрового учета

Для разработчиков сложных отчетов в ЗУП 3.1 предусмотрен механизм создания временных таблиц с "представлениями" кадровых данных. Это наиболее профессиональный способ работы в рамках запроса. Мы можем вызвать метод, который подготовит временную таблицу с уже готовыми срезами на нужную дату, учитывая всю сложность кадрового учета.

Проанализируем пример использования менеджера временных таблиц:


Запрос = Новый Запрос;
МенеджерВТ = Новый МенеджерВременных Таблиц;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

// Описываем параметры получения данных
ПараметрыПериодов = КадровыйУчет.ПараметрыПериодов() ;
НоваяСтрока = ПараметрыПериодов.Добавить();
НоваяСтрока.Период = Объект.Дата;
НоваяСтрока.КлючПериода = Объект.Дата;

// Формируем ВТ "ВТКадроваяИсторияСотрудников"
КадровыйУчет.СоздатьВТКадроваяИсторияСотрудников(МенеджерВТ, Истина, ПараметрыПериодов);

// Теперь мы можем обращаться к подготовленной таблице в обычном запросе
Запрос.Текст = 
    "ВЫБРАТЬ
    |	КадроваяИстория.Сотрудник,
    |	КадроваяИстория.Подразделение
    |ИЗ
    |	ВТКадроваяИсторияСотрудников КАК КадроваяИстория";

Результат = Запрос.Выполнить();

Важные рекомендации

Важно: При написании запросов к кадровым данным всегда помните про разрез ФизическоеЛицо. В ЗУП 3.1 один и тот же человек может занимать несколько позиций (основное место и внутреннее совместительство). Если ваш запрос должен возвращать данные по конкретному рабочему месту, всегда делайте соединение по полю Сотрудник.

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

Подведем итог: для получения корректного подразделения в ЗУП 3.1 на текущую дату не используйте прямой запрос к КадроваяИсторияСотрудников.СрезПоследних. Используйте либо интервальный регистр, либо (что предпочтительнее) функции общего модуля КадровыйУчет. Это гарантирует точность данных при наличии временных переводов и будущих обновлений системы.

← На главную