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