При разработке отчетов в конфигурации «Зарплата и управление персоналом 3.1» программисты часто сталкиваются с ситуацией, когда запрос к виртуальной таблице СрезПоследних регистра сведений КадроваяИсторияСотрудников возвращает две или более строки для одного и того же физического лица. На первый взгляд это кажется ошибкой платформы, ведь срез последних должен возвращать только актуальную запись. Разберем подробно, почему это происходит и как правильно составить запрос для получения корректных данных.
Для начала проанализируем структуру регистра КадроваяИсторияСотрудников. В отличие от простых регистров, здесь ключевыми измерениями являются не только ФизическоеЛицо, но и Сотрудник, а также ГоловнаяОрганизация. Рассмотрим ситуацию, когда человек (одно физическое лицо) был принят на работу, затем уволен, и спустя время принят снова.
В системе 1С:ЗУП 3.1 для каждого нового трудового договора создается новый элемент в справочнике Сотрудники, даже если физическое лицо остается прежним. Таким образом, у одного физлица появляются две разные карточки сотрудников:
Когда мы обращаемся к виртуальной таблице СрезПоследних, платформа ищет последнюю запись в разрезе уникальной комбинации всех измерений. Поскольку сотрудники разные, система считает их разными объектами учета и возвращает последнюю запись для каждого из них. В итоге по запросу к ФизическоеЛицо мы получаем две строки: последнюю запись по первому сотруднику (увольнение) и последнюю запись по второму сотруднику (прием или перемещение).
Если нам необходимо получить информацию именно в разрезе физических лиц, игнорируя историю разных «сотрудников» одного человека, нам придется отказаться от прямого использования СрезПоследних по всем измерениям. Мы можем использовать пакетный запрос или вложенную таблицу для выбора максимального периода (даты события) для конкретного физлица.
Рассмотрим пример запроса, который позволяет отобрать только последнюю актуальную запись по физическому лицу:
ВЫБРАТЬ
КадроваяИстория.ФизическоеЛицо КАК ФизическоеЛицо,
МАКСИМУМ(КадроваяИстория.Период) КАК МаксПериод
ПОМЕСТИТЬ ВТ_ПоследниеДаты
ИЗ
РегистрСведений.КадроваяИсторияСотрудников КАК КадроваяИстория
ГДЕ
КадроваяИстория.Период <= &ДатаОтчета
И КадроваяИстория.ФизическоеЛицо = &ФизическоеЛицо
ГРУППИРОВАТЬ ПО
КадроваяИстория.ФизическоеЛицо;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
КадроваяИстория.ФизическоеЛицо КАК ФизическоеЛицо,
КадроваяИстория.ВидСобытия КАК ВидСобытия,
КадроваяИстория.Период КАК Период
ИЗ
ВТ_ПоследниеДаты КАК ПоследниеДаты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников КАК КадроваяИстория
ПО ПоследниеДаты.ФизическоеЛицо = КадроваяИстория.ФизическоеЛицо
И ПоследниеДаты.МаксПериод = КадроваяИстория.Период
Важный нюанс: Если в один и тот же день (период) произошло два события (например, увольнение и прием в тот же день), такой запрос все равно может вернуть две строки. В этом случае следует дополнительно анализировать ПериодСекунда или использовать Регистратор для более точного определения последовательности.
Профессиональный подход в ЗУП 3.1 подразумевает отказ от прямых запросов к регистрам кадровой истории. Разработчики конфигурации предусмотрели мощный программный механизм — программный интерфейс (API), который сам обрабатывает все сложности учета: совместительство, увольнения, перемещения и работу с интервальными регистрами.
Проанализируем метод КадровыйУчет.СоздатьВТКадровыеДанныеСотрудников(). Этот метод позволяет сформировать временную таблицу с нужными полями (должность, подразделение, вид события и т.д.) на определенную дату. Для этого в процедуру передается массив сотрудников или запрос, содержащий сотрудников.
Преимущества использования типовых функций:
В ЗУП 3.1 данные также дублируются в специальных интервальных регистрах, таких как КадроваяИсторияСотрудниковИнтервальный. Эти регистры хранят не просто записи о событиях («Прием», «Перемещение»), а периоды «от» и «до». Работа с ними позволяет гораздо проще ответить на вопрос: «Работает ли человек сейчас?».
Если мы хотим найти всех уволенных физлиц, которые не были приняты повторно, нам нужно проверить наличие записи в интервальном регистре, где дата окончания интервала равна «пустой» дате (31.12.3999). Если такого интервала нет, значит, на текущий момент у физлица нет активного трудового договора ни по одному из элементов справочника Сотрудники.
Проблема задвоения результатов — это не ошибка, а следствие сложной архитектуры учета кадров. Выясним основные правила работы с такими данными:
СрезПоследних всегда выдает результат по совокупности измерений (Физлицо + Сотрудник + Организация).КадровыйУчет.Следуя этим рекомендациям, вы сможете строить отчеты, которые корректно отображают состояние персонала без лишних строк и ошибок в данных.