В разработке на платформе 1С:Предприятие 8.3, особенно в конфигурации Зарплата и управление персоналом (ЗУП 3.1), часто возникает задача программного анализа кадрового состояния сотрудников. Одной из самых востребованных задач является получение списка людей, которые на определенную дату или в определенный период находятся в отпуске. Рассмотрим несколько способов решения этой задачи: от использования схемы компоновки данных (СКД) типовых отчетов до работы с программным интерфейсом (API) общих модулей.
Многие разработчики пытаются использовать готовые макеты компоновки данных из типовых отчетов, таких как СостоянияСотрудников. Это логичный путь, так как в этих отчетах уже настроены все связи и выборки. Однако, как показывает практика, простого получения макета и установки параметров часто недостаточно.
Разберем типичную ошибку. При программном выполнении СКД типового отчета данные могут не возвращаться, если не выполнена инициализация отчета или не заполнены настройки, которые отчет ожидает «по умолчанию». Проанализируем правильный алгоритм работы с СКД в коде:
// Получаем макет СКД из типового отчета
ОтчетОбъект = Отчеты.СостоянияСотрудников.Создать();
СхемаКомпоновки = ОтчетОбъект.СхемаКомпоновкиДанных;
// Важно использовать настройки конкретного варианта, например, "ОтсутствияСотрудников"
Настройки = СхемаКомпоновки.ВариантыНастроек.ОтсутствияСотрудников.Настройки;
// Установка параметров периода
ПараметрПериод = Настройки.ПараметрыДанных.Элементы.Найти("Период");
Если ПараметрПериод <> Неопределено Тогда
ПараметрПериод.Значение = Новый СтандартныйПериод(НачалоМесяца(ТекущаяДата()), КонецМесяца(ТекущаяДата()));
ПараметрПериод.Использование = Истина;
КонецЕсли;
// Обязательная инициализация, если отчет имеет специфическую логику в модуле объекта
// В некоторых случаях требуется вызывать экспортные методы модуля отчета для подготовки данных
// ОтчетОбъект.ИнициализироватьОтчет();
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
ДанныеТЗ = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ДанныеТЗ);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Обратите внимание на объект СтандартныйПериод. В типовых конфигурациях параметры часто сгруппированы, и простая установка НачалоПериода и КонецПериода может не сработать, если в самой схеме используется связь через комплексный параметр периода.
В конфигурации ЗУП 3.1 существует специализированный общий модуль СостоянияСотрудников, который содержит готовые инструменты для получения необходимых сведений. Это наиболее «правильный» путь с точки зрения поддержки кода, так как он использует механизмы, заложенные вендором.
Выясним, как воспользоваться экспортными функциями этого модуля. Для получения данных мы можем использовать функцию, которая возвращает таблицу состояний сотрудников на конкретный интервал времени. Рассмотрим пример использования:
// Подготовим параметры для получения состояний
ПараметрыПолучения = СостоянияСотрудников.ПараметрыПолученияСостояний();
ПараметрыПолучения.Организация = Справочники.Организации.ПустаяСсылка(); // Можно указать конкретную
ПараметрыПолучения.НачалоПериода = Дата("20250701");
ПараметрыПолучения.ОкончаниеПериода = Дата("20250831");
// Получаем таблицу состояний
ТаблицаСостояний = СостоянияСотрудников.СостоянияСотрудников(ПараметрыПолучения);
// Фильтруем таблицу по признаку отпуска
// Значения перечисления СостоянияСотрудника: Отпуск, ОтпускБезОплаты, ОтпускПоУходуЗаРебенком и т.д.
Для Каждого Строка Из ТаблицаСостояний Цикл
Если Строка.Состояние = Перечисления.СостоянияСотрудника.Отпуск
Или Строка.Состояние = Перечисления.СостоянияСотрудника.ОтпускБезОплаты Тогда
// Обработка данных сотрудника в отпуске
Сообщить("Сотрудник: " + Строка.Сотрудник + " в отпуске до " + Строка.ДействуетДо);
КонецЕсли;
КонецЦикла;
Этот метод хорош тем, что он автоматически учитывает иерархию подразделений, права доступа (если вызывается в контексте пользователя) и корректно обрабатывает наложения периодов.
Если нам нужна максимальная производительность и мы пишем запрос внутри сложного алгоритма, можно обратиться напрямую к регистру сведений СостоянияСотрудников. Проанализируем структуру этого регистра:
Сотрудник.Состояние, ДействуетДо, ДокументОснование.Важно помнить, что регистр периодический. Нам нужно получить срез последних данных, но с учетом того, что состояние «Отпуск» имеет временные границы. Рассмотрим пример запроса:
ВЫБРАТЬ
СостоянияСотрудников.Сотрудник КАК Сотрудник,
СостоянияСотрудников.Состояние КАК Состояние,
СостоянияСотрудников.Период КАК ДатаНачала,
СостоянияСотрудников.ДействуетДо КАК ДатаОкончания
ИЗ
РегистрСведений.СостоянияСотрудников КАК СостоянияСотрудников
ГДЕ
СостоянияСотрудников.Состояние В (
ЗНАЧЕНИЕ(Перечисление.СостоянияСотрудника.Отпуск),
ЗНАЧЕНИЕ(Перечисление.СостоянияСотрудника.ОтпускБезОплаты),
ЗНАЧЕНИЕ(Перечисление.СостоянияСотрудника.ОтпускНаУчебе)
)
И &НужнаяДата МЕЖДУ СостоянияСотрудников.Период И СостоянияСотрудников.ДействуетДо
Важный нюанс: при работе с регистрами состояний напрямую, мы должны учитывать привилегированный режим. Если в базе настроены ограничения прав на уровне записей (RLS), обычный запрос от имени пользователя может вернуть неполные данные или вызвать ошибку доступа. Используйте УстановитьПривилегированныйРежим(Истина) перед выполнением запроса, если это оправдано логикой задачи.
Для более сложных кадровых отчетов рекомендуется использовать методы модуля КадровыйУчет. Этот модуль позволяет получать данные в виде временных таблиц, что крайне удобно для интеграции в большие запросы.
Разберем использование метода СоздатьВременнуюТаблицуИзмененийСостоянийСотрудников. Этот подход позволяет получить не просто срез, а динамику изменений за период, что критично для формирования табелей или графиков.
Пример логики построения запроса с использованием механизмов ЗУП:
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
// Подготавливаем описание фильтров (массив сотрудников, период и т.д.)
ПараметрыПериодов = КадровыйУчет.ПараметрыПериодовСостоянийСотрудников();
ПараметрыПериодов.ДатаНачала = НачалоДня(Объект.ДатаОтчета);
ПараметрыПериодов.ДатаОкончания = КонецДня(Объект.ДатаОтчета);
// Метод создаст во временной таблице данные о состояниях
КадровыйУчет.СоздатьВременнуюТаблицуИзмененийСостоянийСотрудников(МенеджерВТ, "ВТСостояния", ПараметрыПериодов);
Запрос.Текст = "ВЫБРАТЬ * ИЗ ВТСостояния ГДЕ Состояние = &СостояниеОтпуск";
Запрос.УстановитьПараметр("СостояниеОтпуск", Перечисления.СостоянияСотрудника.Отпуск);
Результат = Запрос.Выполнить().Выгрузить();
Проанализировав ситуацию, можно сделать следующие выводы:
СостоянияСотрудников.СостоянияСотрудников.КадровыйУчет для формирования временных таблиц.Всегда проверяйте актуальность состояния. В ЗУП 3.1 состояние сотрудника фиксируется не только фактом проведения документа Отпуск, но и его утверждением (если в программе разделены права расчетчика и кадровика). Данные в регистр СостоянияСотрудников обычно попадают сразу после проведения кадрового документа.