Как построить отчет по кадровым перемещениям сотрудников с выводом предыдущей и новой должности в 1С:ЗУП?

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

Разработка кадровых отчетов — одна из самых частых задач при работе с конфигурацией 1С:Зарплата и Управление Персоналом 3.1. Одной из классических проблем является необходимость вывести в одной строке данные о текущем назначении сотрудника (должность, подразделение) и информацию о том, где он работал до этого перемещения. В этой статье мы подробно разберем, как реализовать такой отчет с помощью языка запросов 1С, проанализируем типичные ошибки новичков и рассмотрим современные профессиональные подходы, используемые в типовых решениях. Для этой задачи можно использовать готовый отчет по перемещениям сотрудников с выводом предыдущей должности.

Постановка задачи и выбор источника данных

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

Основным источником данных для таких задач в ЗУП 3.1 является периодический регистр сведений КадроваяИсторияСотрудников. Рассмотрим основные сложности:

  1. Данные в регистре хранятся «вертикально»: каждая запись — это новое состояние. Чтобы получить предыдущее состояние, нужно найти запись с максимальной датой, которая меньше даты текущего события.
  2. В отчет не должны попадать приемы на работу (так как у них нет «предыдущей» должности) и увольнения (так как это не перемещение).
  3. Необходимо корректно обрабатывать ситуацию, когда в выбранном периоде у сотрудника было несколько перемещений.

Вариант 1: Использование вложенного запроса для поиска предыдущего периода

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

Проанализируем пример кода, который позволяет получить данные о перемещениях:


ВЫБРАТЬ
    Тек.Сотрудник КАК Сотрудник,
    Тек.Должность КАК Должность,
    Тек.Подразделение КАК Подразделение,
    Пред.Должность КАК ПредДолжность,
    Пред.Подразделение КАК ПредПодразделение,
    Тек.Период КАК Период,
    Тек.Регистратор КАК Регистратор
ИЗ
    (ВЫБРАТЬ
        Тек.Сотрудник КАК Сотрудник,
        Тек.Должность КАК Должность,
        Тек.Подразделение КАК Подразделение,
        Тек.Период КАК Период,
        МАКСИМУМ(Пред.Период) КАК ПредПериод,
        Тек.Регистратор КАК Регистратор
    ИЗ
        РегистрСведений.КадроваяИсторияСотрудников КАК Тек
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников КАК Пред
        ПО Пред.Сотрудник = Тек.Сотрудник
            И Пред.Период < Тек.Период
    ГДЕ
        Тек.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
    СГРУППИРОВАТЬ ПО
        Тек.Сотрудник,
        Тек.Должность,
        Тек.Период,
        Тек.Подразделение,
        Тек.Регистратор) КАК Тек
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников КАК Пред
    ПО Пред.Сотрудник = Тек.Сотрудник
        И Пред.Период = Тек.ПредПериод

Разберем, что происходит в этом запросе. Во вложенном запросе мы берем таблицу Тек (текущие записи) и соединяем ее с таблицей Пред (все записи того же сотрудника, которые были раньше). С помощью функции МАКСИМУМ(Пред.Период) мы находим дату самого последнего события перед текущим. Затем, во внешнем запросе, мы снова соединяемся с регистром, чтобы «вытащить» должность и подразделение, соответствующие этой найденной дате.

Вариант 2: Фильтрация по типу документа и виду события

Часто новички сталкиваются с тем, что в отчет попадают лишние данные. Например, записи об увольнении. Чтобы этого избежать, можно наложить фильтр на тип документа-регистратора. Выясним причину, почему это не всегда эффективно: в 1С:ЗУП перемещение может быть оформлено не только документом Кадровый перевод, но и, например, Изменение оплаты труда (если там меняется позиция штатного расписания) или техническими документами при переносе данных.

Тем не менее, если мы хотим ограничиться только кадровыми переводами, условие в запросе (секция ГДЕ или параметры виртуальной таблицы) будет выглядеть так:


ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.КадровыйПеревод)
ИЛИ ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.КадровыйПереводСписком)

Однако более правильным подходом считается анализ поля ВидСобытия. Рассмотрим, как исключить увольнения и пустые записи более изящно. Мы можем добавить условие, что предыдущая должность должна быть заполнена (это отсечет приемы на работу), а текущая должность также не должна быть пустой (это поможет отсечь записи увольнения в некоторых редакциях, где должность при увольнении очищается).

Профессиональный подход: Интервальные регистры

В современных версиях ЗУП 3.1 разработчики 1С упростили нам жизнь, внедрив интервальные регистры. Вместо того чтобы мучительно искать «максимальный предыдущий период», мы можем обратиться к регистру КадроваяИсторияСотрудниковИнтервальный. В нем каждая запись уже содержит два поля: ДатаНачала и ДатаОкончания.

Рассмотрим преимущество этого метода: чтобы найти предыдущее состояние, нам достаточно соединить записи по условию Тек.ДатаНачала = Пред.ДатаОкончания + 1 секунда. Это работает гораздо быстрее и стабильнее на больших базах данных.

Использование механизмов СКД и временных таблиц

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

  1. Учет исправлений: Кадровые документы могут быть исправлены документами «сторно». Обычный запрос к регистру может выдать неактуальные данные, в то время как типовые механизмы умеют фильтровать «перекрытые» записи.
  2. Разграничение прав: СКД автоматически применяет ограничения прав доступа на уровне записей (RLS).

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

Типичные ошибки при разработке

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

Также помните о совместителях. В 1С:ЗУП один человек может занимать несколько ставок. Всегда делайте соединение по полю Сотрудник, а не по физическому лицу, чтобы не смешивать историю перемещений по разным рабочим местам одного человека.

Подводя итог, можно сказать, что разработка отчета по кадровым перемещениям требует внимательного отношения к логике временных периодов. Рассмотренный нами метод со вложенными запросами является базовым и поможет вам понять принципы работы с регистрами сведений в 1С. В дальнейшем мы рекомендуем изучить работу с виртуальными таблицами кадрового учета, которые предоставляет сама платформа ЗУП для построения более сложных и производительных отчетов.

← На главную