Почему перестал заполняться регистр сведений «Текущие кадровые данные сотрудников» в ЗУП 3.1 и как теперь правильно получать кадровые данные

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

Многие разработчики и администраторы систем на базе «1С:Зарплата и управление персоналом 3.1» (а также 1С:ERP и 1С:Комплексная автоматизация) сталкиваются с неприятной ситуацией: после очередного обновления конфигурации (начиная с версий 3.1.6/3.1.7) во внешних отчетах, печатных формах или обработках обмена начинают пропадать данные о сотрудниках. При детальном анализе выясняется, что популярный и очень удобный ранее регистр сведений ТекущиеКадровыеДанныеСотрудников заполняется лишь частично. В нем остаются заполненными поля сотрудника, даты приема и увольнения, но колонки Подразделение, Должность, ТекущийВидЗанятости и ОсновноеРабочееМесто остаются абсолютно пустыми для новых кадровых документов.

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

Официальная позиция «1С» и суть изменений

Для начала проанализируем причины такого поведения системы. Разработчики «1С» официально подтвердили, что частичное заполнение регистра сведений ТекущиеКадровыеДанныеСотрудников — это не баг, а задуманное поведение (by design). Логика развития подсистемы кадрового учета ЗУП 3.1 привела к отказу от дублирования оперативной информации в плоских непериодических таблицах.

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

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

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

Ниже мы подробно рассмотрим три основных метода решения этой проблемы в зависимости от ваших задач: от простых прямых запросов до использования профессионального программного интерфейса и механизмов СКД.

Способ №1. Прямое соединение таблиц в запросе (быстрый, но не рекомендуемый путь)

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

Рассмотрим пример запроса, который собирает актуальные кадровые данные на определенную дату:


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

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

Способ №2. Использование программного интерфейса общего модуля «КадровыйУчет»

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

Для получения актуальных данных по списку сотрудников используется экспортный метод КадровыеДанныеСотрудников общего модуля КадровыйУчет. Проанализируем, как с ним работать.

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


// 1. Формируем массив сотрудников, по которым нужны данные
СписокСотрудников = Новый Массив;
СписокСотрудников.Добавить(ВыбранныйСотрудник); // Ссылка на Справочник.Сотрудники

// 2. Строкой через запятую перечисляем только те поля, которые нам необходимы
ПоляКадровыхДанных = "Организация,Подразделение,Должность,ВидЗанятости,ДатаПриема,ДатаУвольнения";

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

// 4. Обходим полученную таблицу значений с результатами
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
    ТекущееПодразделение = СтрокаДанных.Подразделение;
    ТекущаяДолжность     = СтрокаДанных.Должность;
    ТекущийВидЗанятости  = СтрокаДанных.ВидЗанятости;
    
    // Выполняем полезную работу с полученными переменными
КонецЦикла;

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

Способ №3. Использование механизма представлений для отчетов на СКД

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

Разберем по шагам, как интегрировать кадровые данные в отчет на СКД без прямых запросов к регистрам:

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

Рассмотрим пример запроса-пустышки, который необходимо поместить в ваш набор данных СКД:


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Представления_КадровыеДанныеСотрудников.Сотрудник,
    Представления_КадровыеДанныеСотрудников.Организация,
    Представления_КадровыеДанныеСотрудников.Подразделение,
    Представления_КадровыеДанныеСотрудников.Должность,
    Представления_КадровыеДанныеСотрудников.ВидЗанятости,
    Представления_КадровыеДанныеСотрудников.ДатаПриема,
    Представления_КадровыеДанныеСотрудников.ДатаУвольнения
ИЗ
    Представления_КадровыеДанныеСотрудников КАК Представления_КадровыеДанныеСотрудников

После того как схема компоновки подготовлена, в модуле отчета (в процедуре ПриКомпоновкеРезультата) или в коде инициализации формы отчета необходимо написать вызов процедуры, выполняющей подмену:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // Инициализируем настройки компоновщика
    НастройкиОтчета = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Вызываем механизм автоматического заполнения общих источников данных ЗКБ
    ЗарплатаКадрыОбщиеНаборыДанных.ЗаполнитьОбщиеИсточникиДанныхОтчета(ЭтотОбъект, НастройкиОтчета);
    
    // Выполняем стандартную компоновку с уже измененными запросами
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиОтчета, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

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

Возможные проблемы и неочевидные ошибки при переходе

Отказ от классического ведения регистра ТекущиеКадровыеДанныеСотрудников может спровоцировать появление скрытых ошибок, о которых важно знать заранее:

1. Ошибка «Сотрудник не принят на работу» в расчетах среднего заработка. Иногда при расчете отпусков или командировок программа выдает ошибку о том, что сотрудник не принят на работу, хотя кадровый документ проведения существует. Это происходит из-за того, что в РС ТекущиеКадровыеДанныеСотрудников не установился флаг ОформленПоТрудовомуДоговору. Решается перепроведением документа приема или программной перезаписью этого флага.

2. Проблемы с подбором договорников (ГПХ). При заполнении ведомостей на выплату через форму подбора договорники ГПХ могут неожиданно исчезнуть из списков. Это происходит в тех случаях, когда при обновлении или переносе данных из старых баз некорректно заполнился регистр РолиСотрудников, который теперь работает в связке с кадровыми данными. Рекомендуется запустить тестирование и исправление базы данных или выполнить пересохранение карточек проблемных сотрудников.

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

← На главную