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