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