Почему в отчете СКД для 1С:ЗУП не появляется или исчезает поле «Текущая должность»?

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

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

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

Причина 1. Влияние настроек штатного расписания в программе

В конфигурации ЗУП 3.1 логика заполнения регистра сведений ТекущиеКадровыеДанныеСотрудников напрямую зависит от настроек ведения штатного расписания:

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

Если штатное расписание отключено: в регистре заполняется и используется именно ресурс ТекущаяДолжность.

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

Причина 2. Использование «Текущих» данных для периодических отчетов

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

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

Ниже мы рассмотрим три практических и правильных способа решения проблемы с получением должности в СКД.

Решение 1. Использование встроенного механизма представлений ЗУП 3.1

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

Рассмотрим, как правильно использовать этот механизм:

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

Пример кода в модуле объекта отчета:


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

Решение 2. Программное получение кадровых данных через API и передача ТЗ в СКД

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

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

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

Пример программной реализации в модуле объекта отчета:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Получаем базовые данные по отработанному времени
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ОтработанноеВремя.Сотрудник КАК Сотрудник,
        |   ОтработанноеВремя.Подразделение КАК Подразделение,
        |   СУММА(ОтработанноеВремя.ОтработаноЧасов) КАК ОтработаноЧасов,
        |   СУММА(ОтработанноеВремя.ОтработаноДней) КАК ОтработаноДней
        |ИЗ
        |   РегистрНакопления.ОтработанноеВремяПоСотрудникам КАК ОтработанноеВремя
        |ГДЕ
        |   ОтработанноеВремя.ПериодДействия = &ПериодДействия
        |   И ОтработанноеВремя.Начисление В (&СписокНачислений)
        |ГРУППИРОВАТЬ ПО
        |   ОтработанноеВремя.Сотрудник,
        |   ОтработанноеВремя.Подразделение";
    
    // Получаем параметры из настроек компоновщика
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    ПараметрПериод = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ПериодДействия"));
    
    // Для примера зададим параметры напрямую или извлечем их из СКД
    ПериодДействия = ?(ПараметрПериод <> Неопределено, ПараметрПериод.Значение, ТекущаяДата());
    СписокНачислений = Новый Массив; // Заполните актуальными начислениями
    
    Запрос.УстановитьПараметр("ПериодДействия", ПериодДействия);
    Запрос.УстановитьПараметр("СписокНачислений", СписокНачислений);
    
    ТаблицаВремени = Запрос.Выделать().Выгрузить();
    
    // 2. Формируем массив уникальных сотрудников для получения кадровых данных
    МассивСотрудников = ТаблицаВремени.ВыгрузитьКолонку("Сотрудник");
    ОбщегоНазначенияКлиентСервер.СвернутьМассив(МассивСотрудников);
    
    // 3. Используем официальный программный интерфейс кадрового учета ЗУП 3.1
    // Данный метод вернет актуальные должности на указанную дату с учетом всех срезов и штатного расписания
    КадровыеДанные = КадровыйУчет.КадровыеДанныеСотрудников(Истина, МассивСотрудников, "Подразделение, Должность", ПериодДействия);
    
    // Создаем результирующую таблицу для СКД
    ТаблицаДляВывода = Новый ТаблицаЗначений;
    ТаблицаДляВывода.Колонки.Добавить("Сотрудник", Новый ОписаниеТипов("СправочникСсылка.Сотрудники"));
    ТаблицаДляВывода.Колонки.Добавить("Подразделение", Новый ОписаниеТипов("СправочникСсылка.ПодразделенияОрганизаций"));
    ТаблицаДляВывода.Колонки.Добавить("Должность", Новый ОписаниеТипов("СправочникСсылка.Должности"));
    ТаблицаДляВывода.Колонки.Добавить("ОтработаноЧасов", Новый ОписаниеТипов("Число"));
    ТаблицаДляВывода.Колонки.Добавить("ОтработаноДней", Новый ОписаниеТипов("Число"));
    
    // Заполняем результирующую таблицу связыванием данных
    Для Каждого СтрокаВремени Из ТаблицаВремени Цикл
        НоваяСтрока = ТаблицаДляВывода.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаВремени);
        
        // Ищем кадровые данные сотрудника на дату проведения расчетов
        ПараметрыОтбора = Новый Структура("Сотрудник", СтрокаВремени.Сотрудник);
        НайденныеКадровыеСтроки = КадровыеДанные.НайтиСтроки(ПараметрыОтбора);
        Если НайденныеКадровыеСтроки.Количество() > 0 Тогда
            НоваяСтрока.Должность = НайденныеКадровыеСтроки[0].Должность;
            // При необходимости можно переопределить подразделение историческим значением
            НоваяСтрока.Подразделение = НайденныеКадровыеСтроки[0].Подразделение;
        КонецЕсли;
    КонецЦикла;
    
    // 4. Передаем таблицу в СКД через внешние наборы данных
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("ТаблицаОтработанногоВремени", ТаблицаДляВывода);
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки, Истина);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Решение 3. Устранение технических причин на уровне настроек СКД и платформы

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

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

← На главную