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