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