Как в ЗУП 3.1 правильно получить должность и подразделение сотрудника в запросе на определенную дату или за период?

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

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

Проблема использования виртуальных таблиц СрезПоследних

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

Способ 1. Использование интервальных регистров

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

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

Рассмотрим пример условия для получения данных на конкретную дату:


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

Важный момент: в интервальных регистрах вместо поля Период используются поля ДатаНачала и ДатаОкончания. Если период является открытым (сотрудник работает по сей день), в ДатаОкончания будет записана пустая дата или значение «31.12.3999», что корректно обрабатывается условием МЕЖДУ.

Способ 2. Механизм «Замены представлений» кадровых данных

Это «золотой стандарт» разработки в ЗУП 3.1. Фирма «1С» предусмотрела специальный программный механизм, который позволяет разработчику не описывать сложные соединения с регистрами вручную. Для отладки таких алгоритмов пригодится консоль запросов с обработкой механизма представлений — есть консоль запросов с поддержкой представлений ЗУП. Мы создаем временную таблицу с нужными нам сотрудниками и датами, а система сама заполняет её актуальными кадровыми данными.

Разберем этот метод по шагам:

  1. Создаем временную таблицу (например, с именем ВТ_СотрудникиДаты), в которой обязательно должны быть колонки Сотрудник и Период.
  2. Добавляем в эту же таблицу пустые колонки для тех данных, которые хотим получить (например, Должность, Подразделение).
  3. Вызываем программный метод ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц (для удобной разработки этого шага создана специализированная консоль для работы с представлениями).

Посмотрим на пример кода, который можно использовать в обработке или отчете:


// 1. Подготовим текст запроса с использованием специальной ВТ
ТекстЗапроса = "ВЫБРАТЬ
               |    Данные.Сотрудник КАК Сотрудник,
               |    Данные.Период КАК Период,
               |    ЗНАЧЕНИЕ(Справочник.Должности.ПустаяСсылка) КАК Должность,
               |    ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка) КАК Подразделение
               |ПОМЕСТИТЬ Представления_КадровыеДанныеСотрудников
               |ИЗ
               |    &ТаблицаСотрудников КАК Данные;
               |
               |////////////////////////////////////////////////////////////////////////////////
               |ВЫБРАТЬ
               |    Результат.Сотрудник,
               |    Результат.Должность,
               |    Результат.Подразделение
               |ИЗ
               |    Представления_КадровыеДанныеСотрудников КАК Результат";

Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("ТаблицаСотрудников", ВашаТаблицаСотрудниковИДат);

// 2. Магия ЗУП: система сама перепишет запрос и заполнит данные из регистров
ЗарплатаКадрыОбщиеНаборыДанных.ЗаменитьЗапросыКПредставлениямВиртуальныхТаблиц(Запрос.Текст, Запрос);

РезультатЗапроса = Запрос.Выполнить();

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

Способ 3. Программный интерфейс модуля КадровыйУчет

Если вам не нужно строить сложный запрос, а требуется просто получить структуру кадровых данных в коде, используйте функции общего модуля КадровыйУчет. Это наиболее корректный путь с точки зрения поддержки кода.

Рассмотрим метод КадровыеДанныеСотрудников. Он позволяет получить массив структур или таблицу значений с нужной информацией.


СписокСотрудников = Новый Массив;
СписокСотрудников.Добавить(ВыбранныйСотрудник);

СписокПолей = "Должность,Подразделение,Организация,ТабельныйНомер";

// Получаем данные на текущую дату
ТаблицаДанных = КадровыйУчет.КадровыеДанныеСотрудников(Истина, СписокСотрудников, СписокПолей, ТекущаяДата());

Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
    Сообщить("Сотрудник: " + СтрокаДанных.Сотрудник + " занимает должность " + СтрокаДанных.Должность);
КонецЦикла;

Для запросов также существует метод КадровыйУчет.СоздатьВТКадровыеДанныеСотрудников. Мы передаем ему менеджер временных таблиц, и он создает в нем готовую таблицу с кадровыми данными, которую можно соединять с другими таблицами в вашем основном запросе. Это избавляет от необходимости вникать в устройство регистров КадроваяИсторияСотрудников.

Как получить данные «ДО» перевода (практический совет)

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

Проанализируем логику запроса:

  1. Выбираем события из РегистрСведений.КадроваяИсторияСотрудников с фильтром по виду события (Перемещение).
  2. Для каждой найденной записи вычисляем момент времени «до»: ДОБАВИТЬКДАТЕ(Период, СЕКУНДА, -1).
  3. Левым соединением подключаем этот же регистр (или виртуальную таблицу СрезПоследних) по сотруднику и вычисленному моменту времени.

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

Резюме

Мы рассмотрели три основных способа работы с должностями и подразделениями в ЗУП 3.1. Для простых отчетов в консоли или быстрой разработки можно использовать интервальные регистры — для масштабной аналитики пригодится инструмент выгрузки данных из 1С в BI-системы. Для серьезной разработки внутри конфигурации рекомендуется использовать механизм замены представлений или методы модуля КадровыйУчет. Это гарантирует, что ваш отчет не «сломается» после очередного обновления программы и будет показывать корректные данные даже для сотрудников, принятых «вчера».

← На главную