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

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

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

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

Архитектура хранения плановых начислений и окладов в 1С:ЗУП 3.1

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

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

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

Обращение к этим таблицам напрямую через запросы таит в себе серьезные опасности.

Почему прямые запросы к регистрам — это «мина замедленного действия»?

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

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

Программный интерфейс получения кадровых данных

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

Давайте подробно разберем ключевые параметры этой функции:

  1. ТолькоРазрешенные (тип Булево) — если передать значение Истина, система выберет данные только по тем сотрудникам, к которым у текущего пользователя есть права доступа. Это исключает возникновение ошибок безопасности.
  2. МассивСотрудников (тип Массив) — список ссылок на элементы справочника Сотрудники, по которым необходимо получить информацию. Даже если нам нужен только один сотрудник, его необходимо предварительно поместить в массив.
  3. КадровыеДанные (тип Строка) — перечень запрашиваемых полей, разделенных запятыми. Для получения размера оклада используется системное имя свойства "ТарифнаяСтавка" (или в некоторых контекстах "ТекущаяТарифнаяСтавка").
  4. ДатаСрезаИнформации (тип Дата) — момент времени, на который необходимо получить актуальное значение показателя.

Главная хитрость: Как получить именно «Предыдущий» оклад

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

Проанализируем ситуацию: документ изменения оплаты труда устанавливает новые значения начислений с определенной даты. Эта дата хранится в реквизите документа (например, ДатаИзменения или ДатаНачалаДействия). Если мы передадим в функцию КадровыеДанныеСотрудников эту дату, то система вернет нам уже *новый* оклад, установленный этим документом.

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

ДатаСреза = ДатаИзменения - 1;

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

Пошаговый пример реализации кода

Рассмотрим практический пример кода, который можно использовать в модуле менеджера или в модуле объекта внешней печатной формы для документа «Изменение оплаты труда» (или «Изменение плановых начислений»).


// Предположим, что СсылкаНаОбъект — это ссылка на печатаемый документ изменения оплаты.
// Шаг 1. Получаем необходимые реквизиты документа-основания
РеквизитыДокумента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаОбъект, "Сотрудник, ДатаИзменения");

Если Не ЗначениеЗаполнено(РеквизитыДокумента.Сотрудник) Тогда
    Возврат; // Если сотрудник не заполнен, продолжать бессмысленно
КонецЕсли;

// Шаг 2. Формируем массив сотрудников для передачи в программный интерфейс
МассивСотрудников = Новый Массив;
МассивСотрудников.Добавить(РеквизитыДокумента.Сотрудник);

// Шаг 3. Рассчитываем точную дату среза информации (минус 1 секунда от даты изменений)
ДатаСрезаИнформации = РеквизитыДокумента.ДатаИзменения - 1;

// Шаг 4. Указываем кадровое свойство, отвечающее за размер оклада (тарифной ставки)
КадровыеДанные = "ТарифнаяСтавка";

// Шаг 5. Вызываем функцию программного интерфейса 1С:ЗУП 3.1
ТолькоРазрешенные = Истина;
ТаблицаКадровыхДанных = КадровыйУчет.КадровыеДанныеСотрудников(
    ТолькоРазрешенные, 
    МассивСотрудников, 
    КадровыеДанные, 
    ДатаСрезаИнформации
);

// Шаг 6. Обрабатываем результат и получаем значение предыдущего оклада
ПредыдущийОклад = 0;
Если ТаблицаКадровыхДанных.Количество() > 0 Тогда
    СтрокаДанных = ТаблицаКадровыхДанных[0];
    
    // Проверим наличие колонки в таблице во избежание непредвиденных ошибок
    Если ТаблицаКадровыхДанных.Колонки.Найти("ТарифнаяСтавка") <> Неопределено Тогда
        ПредыдущийОклад = СтрокаДанных.ТарифнаяСтавка;
    КонецЕсли;
КонецЕсли;

// Теперь переменную ПредыдущийОклад можно выводить в макет печатной формы
// Например: ОбластьМакета.Параметры.ПредыдущийОклад = ПредыдущийОклад;

Интеграция алгоритма в структуру внешней печатной формы (ВПФ)

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

  1. В модуле объекта внешней печатной формы найдем процедуру, отвечающую за формирование табличного документа (обычно это функция Печать(...) или специализированный экспортный метод).
  2. Перед формированием области макета, в которой выводится информация по сотруднику, выполним описанный выше расчет предыдущего оклада.
  3. В самом макете печатной формы (табличном документе) добавим параметр, например, ПредыдущийОклад, задав ему соответствующий формат (например, ЧЦ=15; ЧДЦ=2 для корректного отображения копеек).
  4. Передадим полученное значение в параметры заполняемой области макета.

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


// Пример заполнения параметров макета при обходе документов
Для Каждого ТекущийДокумент Из МассивОбъектов Цикл
    
    // Получаем данные конкретного документа
    ДанныеДокумента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ТекущийДокумент, "Сотрудник, ДатаИзменения, НовыйОклад");
    
    // Сдвигаем время на секунду назад для получения старых данных
    ДатаСреза = ДанныеДокумента.ДатаИзменения - 1;
    
    МассивОдногоСотрудника = Новый Массив;
    МассивОдногоСотрудника.Добавить(ДанныеДокумента.Сотрудник);
    
    // Запрос к программному интерфейсу
    ТаблицаДанных = КадровыйУчет.КадровыеДанныеСотрудников(Истина, МассивОдногоСотрудника, "ТарифнаяСтавка", ДатаСреза);
    
    СтарыйОклад = 0;
    Если ТаблицаДанных.Количество() > 0 Тогда
        СтарыйОклад = ТаблицаДанных[0].ТарифнаяСтавка;
    КонецЕсли;
    
    // Выводим данные в строку табличного документа
    ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
    ОбластьСтрока.Параметры.ФИОСотрудника = ДанныеДокумента.Сотрудник.Наименование;
    ОбластьСтрока.Параметры.СтарыйОклад  = СтарыйОклад;
    ОбластьСтрока.Параметры.НовыйОклад   = ДанныеДокумента.НовыйОклад;
    
    ТабличныйДокумент.Вывести(ОбластьСтрока);
    
КонецЦикла;

Важные технологические нюансы и исключения

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

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

← На главную