Как вывести отчет по вакантным должностям в 1С с помощью среза последних

Программист 1С v8.3 (Управляемые формы) Управленческий учет IT и автоматизация бизнеса
← На главную

Разработка кадровых отчетов — одна из классических задач, с которой сталкивается любой начинающий разработчик в среде «1С:Предприятие 8». На первый взгляд задача вывода вакантных должностей кажется тривиальной: достаточно создать периодический регистр сведений, записывать туда изменения и получать актуальное состояние. Однако именно здесь новичков подстерегает опасная архитектурная ловушка, связанная с неправильным проектированием измерений и ресурсов регистра сведений.

В этой статье мы подробно разберем, почему типовые подходы «в лоб» часто приводят к неверным данным в отчетах, проанализируем разницу между измерениями и ресурсами регистра, а также разработаем правильный и оптимизированный запрос для получения актуальных вакансий на любую дату.

Анализ проблемы: почему отчет выводит устаревшие или дублирующиеся данные?

Рассмотрим ситуацию, с которой часто сталкиваются начинающие разработчики. Был создан справочник Должности и периодический регистр сведений ШтатноеРасписание со следующей структурой:

При такой структуре в регистр записывались изменения. Например:

  1. 01.08.2023 — Должность «Инженер» объявляется вакантной (флаг Вакантное = ИСТИНА, сотрудник пустой).
  2. 03.08.2023 — На должность «Инженер» принимают сотрудника (флаг Вакантное = ЛОЖЬ, сотрудник «Иванов И.И.»).

При попытке построить отчет с использованием виртуальной таблицы СрезПоследних и условием отбора по флагу Вакантное = ИСТИНА система все равно выводит должность «Инженер» как вакантную на текущую дату. Выясним, почему так происходит.

Дело в том, что измерения регистра сведений определяют уникальность записей. В системе 1С уникальность записи в периодическом регистре проверяется по комбинации полей: Период + Измерение1 + Измерение2 + ....

Когда мы делаем поле Вакантное измерением, для платформы записи с разными значениями этого флага становятся абсолютно независимыми ветками истории. Система считает, что в регистре хранятся две разные сущности:

Когда виртуальная таблица СрезПоследних обрабатывает эти данные, она берет последнюю запись по каждой уникальной комбинации измерений. В результате мы получаем две актуальные строки:

Затем, когда в отчете срабатывает фильтр ГДЕ Вакантное = ИСТИНА, система просто отсекает строку за 3 августа и оставляет в результате «устаревшую» запись от 1 августа. Отчет показывает некорректную информацию.

Правильное проектирование регистра сведений

Чтобы избежать подобных ошибок, необходимо запомнить важное правило проектирования баз данных в 1С: в измерения регистра нужно выносить только те разрезы учета, по которым нам необходимо получать независимую историю изменений. Все качественные и количественные характеристики состояния (такие как статус «Вакантно», «Активно», «Заблокировано» или имя конкретного сотрудника) должны быть ресурсами или вообще вычисляться динамически.

Посмотрим на правильную структуру регистра сведений ШтатноеРасписание:

При такой структуре нам даже не нужен дополнительный флаг Вакантное. Сама бизнес-логика подсказывает: если на должности никто не работает (поле Сотрудник пустое), значит, эта должность вакантна.

История изменений в регистре теперь выглядит так:

  1. 01.08.2023 — Должность: «Инженер», Сотрудник: Пустая ссылка.
  2. 03.08.2023 — Должность: «Инженер», Сотрудник: «Иванов И.И.».

Теперь по измерению Должность («Инженер») существует строго одна цепочка событий. Срез последних на любую дату после 3 августа вернет ровно одну запись: «Инженер — Иванов И.И.».

Разработка правильного запроса для получения вакансий

Теперь разберем, как правильно написать запрос к новой структуре регистра для получения списка только вакантных должностей. Здесь тоже есть крайне важный нюанс работы с виртуальными таблицами.

Рассмотрим структуру запроса:


ВЫБРАТЬ
    ШтатноеРасписаниеСрезПоследних.Должность КАК Должность,
    ШтатноеРасписаниеСрезПоследних.Сотрудник КАК Сотрудник
ИЗ
    РегистрСведений.ШтатноеРасписание.СрезПоследних(&Период, ) КАК ШтатноеРасписаниеСрезПоследних
ГДЕ
    ШтатноеРасписаниеСрезПоследних.Sотрудник = ЗНАЧЕНИЕ(Справочник.Сотрудники.ПустаяСсылка)

Критически важный момент: Обратите внимание, где именно наложено условие отбора по пустому сотруднику. Оно находится в секции ГДЕ основного запроса, а не в параметрах виртуальной таблицы СрезПоследних.

Проанализируем, почему нельзя писать условие отбора по ресурсу внутри параметров виртуальной таблицы, например: СрезПоследних(&Период, Сотрудник = ЗНАЧЕНИЕ(Справочник.Сотрудники.ПустаяСсылка)).

Если наложить условие во втором параметре виртуальной таблицы, платформа сначала отфильтрует физическую таблицу регистра, выкинув из нее все записи, где сотрудник заполнен. И только после этой фильтрации начнет рассчитывать срез последних. В нашем примере запись от 3 августа (где указан Иванов) будет проигнорирована еще на этапе предварительного отбора, и система вернет нам срез последних на основании записи от 1 августа (где сотрудник был пустой). В итоге мы опять получим неверный результат: занятый Инженер отобразится в отчете как вакантный.

Правильный алгоритм работы запроса должен быть следующим:

  1. Сначала получить срез последних по ВСЕМ должностям без каких-либо предварительных фильтров по ресурсам. Это вернет нам исключительно актуальное состояние каждой должности на указанную дату.
  2. И только после этого, в секции ГДЕ, отсечь те записи, в которых ресурс Сотрудник оказался заполнен.

Как это работает в реальных конфигурациях (1С:ЗУП и 1С:ERP)

В реальных бизнес-приложениях учет штатных единиц устроен значительно сложнее, так как простая схема «одна должность — один сотрудник» не покрывает потребности средних и крупных предприятий. Рассмотрим основные отличия промышленной архитектуры от учебной:

Настройка гибкости отчета для пользователей

При создании отчетов на схеме компоновки данных (СКД) начинающие разработчики часто совершают ошибку, полностью отключая выбор периода, чтобы «отчет всегда показывал данные на текущий момент». Однако на практике руководству и кадровой службе регулярно требуется ретроспективный анализ (например, получить список вакансий на начало прошлого квартала).

Правильным решением будет:

  1. Оставить параметр &Период доступным в настройках запроса виртуальной таблицы.
  2. В настройках СКД на вкладке «Параметры» для параметра Период задать выражение КонецПериода(&Период, "ДЕНЬ") или установить использование по умолчанию текущей даты (функция ТекущаяДата()), чтобы при открытии отчета пользователь сразу видел актуальное состояние, но сохранял возможность выбрать любой другой день в прошлом.

Используя описанные правила проектирования и структуру запросов, вы сможете создавать надежные, быстродействующие и легко масштабируемые кадровые отчеты на платформе «1С:Предприятие 8».

← На главную