Как правильно работать с интервальным регистром «Кадровая история сотрудников» в ЗУП 3.1 и почему в датах появляются лишние секунды?

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

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

В этой статье мы подробно разберем, откуда берутся эти секунды, почему они необходимы и как правильно строить запросы к кадровым данным, чтобы избежать ошибок при формировании табелей или списков сотрудников за период.

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

Проанализируем ситуацию: в системе 1С:Предприятие период является частью уникального ключа записи регистра. Если по одному сотруднику в один и тот же день проводится несколько кадровых документов (например, сначала «Кадровый перевод», а затем «Увольнение»), система не может записать их на одно и то же время 00:00:00. Если бы это произошло, одна запись просто перезаписала бы другую.

Для решения этой проблемы в ЗУП 3.1 реализован механизм автоматического сдвига времени. Каждому документу при проведении назначается определенный приоритет и время в пределах суток. Рассмотрим, как это работает:

  1. При проведении документа вызывается функция ЗарплатаКадрыРасширенный.ЗначениеСдвигаПериодаЗаписиРегистра.
  2. Система анализирует тип документа. Например, «Прием на работу» обычно записывается на самое начало дня, а «Увольнение» — на последние секунды или с определенным смещением относительно начала.
  3. Эти секунды (00:00:01, 00:00:05 и т.д.) попадают в основной регистр КадроваяИсторияСотрудников.
  4. Интервальный регистр, будучи производным, просто копирует эти моменты времени, чтобы обеспечить непрерывность цепочки состояний.

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

Типичные ошибки при работе с запросами

Посмотрим на типичную ошибку начинающих разработчиков. Попытка получить данные на конкретный день через условие «равно» или через КонецДня часто приводит к потере данных или их некорректному дублированию. Если мы используем стандартное сравнение дат без учета времени, мы рискуем «выпасть» из интервала, который закончился в начале дня (например, в 5 секунд первого).

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

Решение №1: Использование типового программного интерфейса (API)

Самый правильный и надежный способ — отказаться от прямых запросов к интервальному регистру и использовать функции, которые разработчики 1С специально создали для решения этой задачи. Основным инструментом здесь является метод СоздатьВТКадровыеДанныеСотрудников. Для поиска и правильного применения встроенных функций пригодится справочник методов конфигурации Зарплата и кадры 3.1.

Рассмотрим алгоритм действий для получения данных за период (например, для заполнения табеля):

  1. Подготовим таблицу сотрудников и дат, на которые нам нужны данные.
  2. Воспользуемся механизмом формирования временных таблиц.

Пример использования типовой функции в коде:


// 1. Сначала подготавливаем менеджер временных таблиц и таблицу периодов
МенеджерВТ = Новый МенеджерВременныхТаблиц;

// Используем типовую функцию для создания таблицы дат за период
ЗарплатаКадрыОбщиеНаборыДанных.СоздатьВТПериоды(МенеджерВТ, ДатаНачала, ДатаОкончания);

// 2. Вызываем функцию формирования кадровых данных
// Она сама обработает все сдвиги секунд и вернет актуальные подразделения, должности и т.д.
КадровыйУчет.СоздатьВТКадровыеДанныеСотрудников(МенеджерВТ, Истина, "Подразделение, Должность, ГрафикРаботы");

Этот метод хорош тем, что он инкапсулирует в себе всю сложную логику работы с интервалами, проверку на «живых» (неуволенных) сотрудников и актуальность данных на каждую секунду времени.

Решение №2: Правильное построение условия в запросе

Если по каким-то причинам использование типового API невозможно (например, в сложном динамическом списке или в специфическом отчете на СКД), проанализируем, как правильно написать условие соединения или фильтрации по датам.

Вместо того чтобы пытаться «поймать» секунды, используйте логику пересечения периодов. Чтобы понять, работал ли сотрудник в определенный день (НужнаяДата), условие должно выглядеть так:


ГДЕ
    ИнтервальныйРегистр.ДатаНачала <= КОНЕЦПЕРИОДА(&НужнаяДата, ДЕНЬ)
    И ИнтервальныйРегистр.ДатаОкончания >= НАЧАЛОПЕРИОДА(&НужнаяДата, ДЕНЬ)

Важный момент: если вам нужно состояние на конкретный день для кадрового учета, в 1С принято считать состояние на КОНЕЦ этого дня (23:59:59). Это позволяет учесть все переводы и изменения, произошедшие в течение суток.

Решение №3: Обработка данных для выгрузки в Excel (шаблон табеля)

Если задача стоит в получении списка всех сотрудников, которые работали в подразделении хотя бы один день из периода, запрос к КадроваяИсторияСотрудниковИнтервальный будет выглядеть следующим образом:


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

В этом случае «лишние» секунды в начале дня (например, 00:00:05) не помешают, так как условие ДатаНачала <= КонецПериодаОтчета все равно будет истинным. Проблема «перехлеста» решается тем, что мы берем состояние за весь период, а не пытаемся разрезать его на атомарные секунды.

Выясним причину, почему нельзя просто игнорировать время

Рассмотрим ситуацию: сотрудник переведен из подразделения А в подразделение Б с 1 октября. В регистре мы увидим:

Если вы будете искать данные на 01.10.2023 00:00:00 (начало дня), вы получите подразделение А. Но фактически человек с 1-го числа уже в Б. Именно поэтому типовые функции 1С всегда делают срез на 23:59:59. Если вы пишете свой запрос, всегда помните об этом правиле кадрового учета.

Резюме

Подведем итоги нашего анализа:

  1. Секунды в интервалах — это не мусор, а технический инструмент для упорядочивания нескольких документов в пределах одного дня.
  2. Прямые запросы к интервальным регистрам опасны. Рекомендуется использовать функции модуля КадровыйУчет, такие как СоздатьВТКадровыеДанныеСотрудников.
  3. При работе с датами в кадровых отчетах всегда ориентируйтесь на конец дня или используйте границы НАЧАЛОПЕРИОДА / КОНЕЦПЕРИОДА для приведения технических секунд к календарным датам.
  4. Для табеля и подобных отчетов за период используйте условие пересечения интервалов (ДатаНачала <= КонецПериода И ДатаОкончания >= НачалоПериода), что гарантированно исключит ошибки, связанные с микро-сдвигами времени.
← На главную