Как запросом получить фактические периоды отпуска при наличии пересечений с больничными в ЗУП 2.5?

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

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

Понимаем природу данных в регистрах расчета

Прежде чем приступать к написанию кода, давайте проанализируем, как 1С работает с пересечениями периодов. Система хранит данные в разрезе ПериодРегистрации и ПериодДействия. Когда вводится больничный лист, даже если он регистрируется в следующем месяце, система создает корректирующую запись (сторно). Это необходимо для правильного расчета налогов и взносов. Таким образом, обращаясь к виртуальной таблице ФактическийПериодДействия, вы всегда будете видеть исходный период и «минусовую» запись, перекрывающую пересечение. «Чистого» интервала в базе данных не существует — его нужно вычислить.

Разбираем метод «Событий» для вычисления периодов

Чтобы избежать перегрузки системы таблицами значений и сложными циклами, мы воспользуемся методом, основанным на логике математического пересечения интервалов. Этот способ позволяет получить «чистые» даты полностью на стороне СУБД. Суть метода заключается в представлении границ периодов как набора событий.

  1. Выберем все даты начала и конца отпусков, присвоив началу признак +1, а концу — -1.
  2. Добавим к ним аналогичным образом границы больничных листов.
  3. Отсортируем все полученные события по дате.
  4. Используя нарастающий итог (функция СУММА() в окне данных), определим моменты, когда отпуск остается «активным» и не перекрыт больничным.

Реализация алгоритма через временные таблицы

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


ВЫБРАТЬ 
    ДатаНачала КАК ДатаСобытия, 1 КАК Тип
ПОМЕСТИТЬ ВТ_События
ИЗ Документ.Отпуска
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 
    ДатаКонца, -1
ИЗ Документ.Отпуска
// Аналогично добавляем больничные с инвертированными признаками (например, -1 для начала и +1 для конца, чтобы вычесть период)

После формирования таблицы событий, мы используем оператор ВЫБРАТЬ с использованием оконных функций (если версия платформы позволяет) или классического приема с коррелирующим запросом для вычисления нарастающего итога. В 1С:ЗУП 2.5, работающей на базе 1С:Предприятие 8.2/8.3, можно использовать вложенные запросы для подсчета суммы состояний на каждую дату события.

Альтернативный подход: работа с графиками работы

Если ваша задача требует получения точного списка календарных дней, свободных от больничных, воспользуйтесь регистром ГрафикиРаботыПоВидамВремени. Это гораздо более простой путь, если вам не критично получение именно интервалов «дата начала - дата конца» в одном запросе.

Действуйте следующим образом:

Этот метод хорош тем, что вы получаете на выходе набор дат. Если вам принципиально получить интервалы, полученные даты можно «сгруппировать», анализируя разницу между соседними записями — если разница равна 1 дню, значит, это единый непрерывный интервал.

Почему не стоит использовать циклы?

Многие начинающие разработчики пытаются обойти регистры в цикле Пока, однако в 1С это ведет к критическому падению производительности при больших объемах данных. Использование временных таблиц и механизмов запросов 1С — это стандарт индустрии, который позволяет переложить тяжелые вычисления на SQL-сервер, который оптимизирован для таких операций. Используя предложенный алгоритм событий, вы получите «чистые» периоды быстро и с соблюдением всех правил работы с регистрами расчета в 1С:ЗУП 2.5.

← На главную