Как правильно работать с датами в интервальном регистре Кадровая история сотрудников в 1С:ЗУП 3.0

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

При переходе на разработку в конфигурации 1С:Зарплата и управление персоналом 3.0 многие программисты сталкиваются с непривычным поведением дат в интервальных регистрах, в частности в регистре КадроваяИсторияСотрудниковИнтервальный. Основная сложность заключается в том, что границы периодов (поля ДатаНачала и ДатаОкончания) часто содержат «лишние» секунды, из-за чего интервалы кажутся перекрывающими друг друга или «залезающими» на следующий день. В этой статье мы подробно разберем, почему так происходит, как устроена внутренняя логика системы и какими способами можно корректно получать данные о кадровых состояниях сотрудников за произвольный период.

Причина возникновения «лишних» секунд в интервалах

Для начала проанализируем ситуацию, когда перевод сотрудника в другое подразделение 1 октября приводит к тому, что предыдущий интервал заканчивается не 30 сентября в 23:59:59, а, например, 1 октября в 00:00:05. На первый взгляд это кажется ошибкой, но на самом деле это фундаментальная особенность архитектуры ЗУП 3.0.

Основным источником данных является обычный периодический регистр КадроваяИсторияСотрудников. В нем поле Период входит в ключ уникальности. Если по одному сотруднику в один день проводится несколько документов (например, кадровый перевод и изменение графика), система не может записать их на одну и ту же секунду. Чтобы обеспечить уникальность записей и сохранить их хронологический порядок, программный код системы принудительно добавляет секунды к каждой последующей записи в рамках одного дня.

Интервальный регистр является «зеркалом» основного регистра, но рассчитанным для быстрого построения отчетов. Его логика подчиняется правилу «линейки времени»:

  1. Дата начала: Всегда в точности соответствует полю Период из основной кадровой истории.
  2. Дата окончания: Рассчитывается как Дата начала следующей записи минус 1 секунда.

Таким образом, если следующее событие по сотруднику началось 1 октября в 00:00:06, то предыдущее обязано закончиться в 00:00:05. Это гарантирует отсутствие «дырок» в истории: сотрудник ни на одну секунду не остается без определенного кадрового состояния. Рассмотрим, как с этим работать в запросах.

Метод 1: Правильное использование условий пересечения периодов

Разберем типичную ошибку: попытку «очистить» даты с помощью функций НАЧАЛОПЕРИОДА или КОНЕЦДНЯ. Делать этого категорически не рекомендуется, так как это нарушает целостность интервалов и может привести к дублированию или потере данных при соединениях.

Для того чтобы определить, попадает ли запись в нужный нам период (например, месяц), мы должны использовать классическую формулу пересечения отрезков. Допустим, нам нужно найти всех, кто работал в подразделении в сентябре (&НачалоПериодаЗапроса = 01.09, &КонецПериодаЗапроса = 30.09). Правильное условие в запросе будет выглядеть так:

Условие: ДатаНачала <= &КонецПериодаЗапроса И ДатаОкончания >= &НачалоПериодаЗапроса

Даже если ДатаОкончания равна 01.10.2023 00:00:05, условие 01.10.2023 00:00:05 >= 01.09.2023 00:00:00 отработает корректно. Система поймет, что интервал захватывает искомый период.

Метод 2: Получение данных через программный интерфейс (API) конфигурации

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

Если данные нужны на конкретную дату, идеально подходит функция КадровыеДанныеСотрудников. Пример вызова:


СписокСотрудников = Новый Массив;
СписокСотрудников.Добавить(ВыбранныйСотрудник);

Свойства = "Организация,Подразделение,Должность,ДатаПриема";
Данные = КадровыйУчет.КадровыеДанныеСотрудников(Истина, СписокСотрудников, Свойства, ТекущаяДата);

Однако, как было отмечено в обсуждении, эта функция возвращает данные только на одну дату. Если ваша задача — получить данные за период (например, для отчета по движению персонала), следует обратить внимание на метод СоздатьВТКадровойИсторииСотрудников того же модуля.

Этот метод программно формирует временную таблицу (ВТ), которая уже учитывает все нюансы интервального регистра, включая исправления (сторнирования) и смещения времени. Это «золотой стандарт» разработки в ЗУП 3.0, так как именно этот механизм используется в типовых отчетах.

Метод 3: Использование регистра СостоянияСотрудников

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

Важное ограничение: Этот регистр хранит только «статусы» (Работает, Отпуск, Болезнь), но не содержит информацию о структуре предприятия. Если вам нужно знать именно где работал человек, этот метод не подойдет.

Метод 4: Работа с основным периодическим регистром (обходной путь)

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


ВЫБРАТЬ
    Период,
    ФизЛицо,
    Сотрудник,
    Подразделение
ИЗ
    РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(&НачалоПериода) КАК Срез
ГДЕ
    НЕ ВидСобытия = ЗНАЧЕНИЕ(Перечисление.ВидыКадровыхСобытий.Увольнение)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Период,
    ФизЛицо,
    Сотрудник,
    Подразделение
ИЗ
    РегистрСведений.КадроваяИсторияСотрудников КАК История
ГДЕ
    Период МЕЖДУ &НачалоПериода И &КонецПериода

Выясним причину, почему это работает: первая часть запроса берет состояние на начало периода (тех, кто уже работал), а вторая часть добавляет все изменения, произошедшие внутри периода (приемы, переводы). Но стоит учитывать, что в этом регистре также присутствуют секундные смещения периодов при записи нескольких документов в один день.

Подведение итогов и рекомендации

Проанализировав все способы, мы можем сделать следующие выводы для эффективной работы с кадровой историей в ЗУП 3.0:

  1. Не бойтесь секунд: Появление секунд в полях ДатаНачала и ДатаОкончания — это нормальное поведение системы для обеспечения уникальности записей в один день.
  2. Используйте правильную логику запроса: Всегда сравнивайте интервалы по принципу пересечения (Начало1 <= Конец2 И Конец1 >= Начало2). Это универсальный способ, не требующий округления дат.
  3. Приоритет типовым методам: Если есть возможность, используйте КадровыйУчет.СоздатьВТКадровойИсторииСотрудников. Это сэкономит время на отладку сложных случаев с исправлениями документов.
  4. Учитывайте открытые интервалы: Помните, что у работающих сотрудников ДатаОкончания часто заполнена значением 31.12.3999 23:59:59. В запросах это значение нужно обрабатывать корректно, чтобы не отсечь актуальных сотрудников.

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

← На главную