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