Как получить кадровые данные сотрудника до кадрового перевода в 1С:ЗУП 3.1

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

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

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

Архитектура кадрового учета в 1С:ЗУП 3.1

Прежде чем перейти к программному коду, кратко разберем, как система хранит и обрабатывает кадровые сведения. В отличие от старых версий (например, ЗУП 2.5), где многие данные хранились непосредственно в периодических регистрах сведений и выбирались простым запросом среза последних, в ЗУП 3.1 реализована более сложная и производительная схема.

Кадровая история сотрудников распределена по нескольким регистрам:

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

Разбор типичных ошибок при вызове функции

Рассмотрим детально ошибки, с которыми столкнулся автор темы на форуме, и выясним причины их возникновения.

Ошибка №1: Передача ссылки на сотрудника вместо массива

В самом первом сообщении автор пытается вызвать функцию следующим образом:


КадровыеДанныеСотрудников = КадровыйУчет.КадровыеДанныеСотрудников(Истина, СсылкаНаДокумент.Сотрудник, "Должность, Подразделение", ДатаМинусДень);

Функция КадровыеДанныеСотрудников спроектирована для массовой обработки информации. Ее вторым параметром должен выступать строго **Массив** ссылок на справочник Справочники.Сотрудники. Если передать туда одиночную ссылку, внутренний построитель запросов 1С не сможет корректно сформировать условие В (ВТ_СписокСотрудников), что приведет к аварийному завершению работы программы.

Ошибка №2: Поле объекта не обнаружено (ЛевоеЗначение)

Эта ошибка — классическое следствие нарушения структуры параметра ПоляОтбораПериодическихДанных. Когда разработчик передает в функцию этот параметр, система ожидает увидеть строго типизированную структуру определенного формата:

  1. Ключ структуры — имя физической таблицы периодического регистра (например, "КадроваяИсторияСотрудников").
  2. Значение ключа — Массив, состоящий из Структур отборов.
  3. Каждая структура отбора обязана иметь три конкретных свойства: "ЛевоеЗначение", "ВидСравнения" и "ПравоеЗначение".

Если этот параметр передан некорректно (или в него по ошибке попало значение другого типа, как это произошло у автора из-за путаницы в параметрах вызова), внутренний парсер запросов общего модуля ЗарплатаКадрыПериодическиеРегистры падает при попытке обратиться к свойству СтрокаОтбора.ЛевоеЗначение.

Важное правило: Если дополнительные отборы по регистрам не требуются, данный параметр нужно либо вообще опустить (он имеет значение по умолчанию Неопределено), либо передать явное значение Неопределено.

Ошибка №3: Индекс находится за пределами массива или пустой результат

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

Представим ситуацию: сотрудник принимается на работу 10 октября, и этим же числом оформляется кадровый перевод (например, исправление ошибки или перевод внутри дня). Если вычесть из даты документа ровно одни сутки (86 400 секунд), мы получим дату 9 октября. На этот момент времени сотрудник в организации еще официально не работал, кадровых записей по нему в базе данных нет. Функция вернет пустую таблицу значений. При попытке получить первую строку через КадровыеДанныеСотрудников[0] система выбросит исключение Индекс находится за пределами массива.

Решение проблемы: Правильный алгоритм работы

Проанализируем оптимальный и безопасный вариант решения этой задачи. Разберем его по шагам.

Шаг 1. Формирование массива сотрудников

Для создания массива из одного элемента лучше всего использовать стандартную функцию библиотеки стандартных подсистем (БСП):


МассивСотрудников = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(СсылкаНаДокумент.Сотрудник);

Это лаконично и гарантирует, что мы передаем именно коллекцию с нужным типом данных.

Шаг 2. Расчет даты среза кадровых данных

Для получения состояния сотрудника непосредственно перед проведением текущего документа «Кадровый перевод» правильнее вычитать не целые сутки (день), а всего одну секунду. Периодичность кадровых регистров в ЗУП 3.1 составляет одну секунду. Вычитание одной секунды позволит получить последнее актуальное состояние прямо перед моментом изменения:

ДатаПолученияДанных = СсылкаНаДокумент.Дата - 1;

Если документ кадрового перевода оформлен началом дня (00:00:00), вычитание секунды вернет 23:59:59 предыдущего дня, что также является абсолютно верным результатом.

Шаг 3. Безопасный вызов функции и обработка результата

Теперь соберем готовый код вызова функции кадрового учета и обязательно добавим проверку на то, что таблица результатов не пуста:


// 1. Формируем массив
МассивСотрудников = ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(СсылкаНаДокумент.Сотрудник);

// 2. Рассчитываем дату (минус 1 секунда от даты документа)
ДатаПолученияДанных = СсылкаНаДокумент.Дата - 1;

// 3. Запрашиваем данные. Лишние параметры опускаем, они примут значения по умолчанию
КадровыеДанные = "Подразделение, Должность";
ТаблицаДанных = КадровыйУчет.КадровыеДанныеСотрудников(Истина, МассивСотрудников, КадровыеДанные, ДатаПолученияДанных);

// 4. Безопасно извлекаем значения
Если ТаблицаДанных.Количество() > 0 Тогда
    СтрокаДанных = ТаблицаДанных[0];
    
    ОбластьРаботник.Параметры.ДолжностьПрежняя = СтрокаДанных.Должность;
    ОбластьРаботник.Параметры.ПодразделениеПрежнееНаПечать = СтрокаДанных.Подразделение;
Иначе
    // Если на дату «До перевода» данных не найдено (например, перевод в день приема)
    ОбластьРаботник.Параметры.ДолжностьПрежняя = "Не найдена";
    ОбластьРаботник.Параметры.ПодразделениеПрежнееНаПечать = "Не найдено";
КонецЕсли;

Альтернативный и более элегантный вариант: КадровыеДанныеСотрудника

Мало кто из начинающих разработчиков знает, что в программном интерфейсе общего модуля КадровыйУчет существует специальная облегченная функция, предназначенная для работы с **одним** сотрудником. Она называется КадровыеДанныеСотрудника.

Эта функция избавляет нас от необходимости вручную создавать массив, а самое главное — она возвращает не таблицу значений, а **Структуру**. Это значительно упрощает синтаксис кода и снижает вероятность возникновения ошибок индексации.

Рассмотрим пример реализации с использованием этого метода:


// Определяем дату получения прежних сведений
ДатаПолученияДанных = СсылкаНаДокумент.Дата - 1;

// Запрашиваем структуру кадровых данных на одного сотрудника
СтруктураДанных = КадровыйУчет.КадровыеДанныеСотрудника(
    Истина, 
    СсылкаНаДокумент.Сотрудник, 
    "Должность, Подразделение", 
    ДатаПолученияДанных
);

// Заполняем параметры печатной формы с проверкой на Неопределено
Если СтруктураДанных <> Неопределено Тогда
    ОбластьРаботник.Параметры.ДолжностьПрежняя = СтруктураДанных.Должность;
    ОбластьРаботник.Параметры.ПодразделениеПрежнееНаПечать = СтруктураДанных.Подразделение;
КонецЕсли;

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

Резюме

Мы успешно разобрали механизмы получения кадровых данных в 1С:ЗУП 3.1. Для предотвращения ошибок всегда соблюдайте следующие правила:

  1. При использовании массовой функции КадровыеДанныеСотрудников всегда передавайте список сотрудников в виде Массива.
  2. Для получения данных до кадрового события вычитайте из даты документа 1 секунду, а не 1 день (86400 секунд).
  3. Не заполняйте параметр отборов ПоляОтбораПериодическихДанных, если в этом нет реальной необходимости — оставляйте его в состоянии Неопределено.
  4. При работе с одиночными объектами используйте более удобную функцию программного интерфейса — КадровыйУчет.КадровыеДанныеСотрудника.
← На главную