При разработке внешних печатных форм для кадровых документов в программе 1С:Зарплата и управление персоналом 3.1 (например, для документов «Изменение оплаты труда», «Изменение плановых начислений» или «Кадровый перевод») часто возникает задача вывести не только новые показатели расчета, но и те, которые действовали непосредственно до момента изменения. Подобные требования со стороны кадровой службы или бухгалтерии помогают наглядно сопоставить изменения условий труда сотрудника.
В этой статье мы подробно разберем, как правильно решить эту задачу с точки зрения стандартов разработки фирмы «1С». Мы выясним, почему прямые запросы к регистрам сведений крайне нежелательны, изучим устройство программного интерфейса конфигурации и реализуем надежный алгоритм получения предыдущего оклада сотрудника.
Прежде чем переходить к написанию программного кода, проанализируем, как система хранит сведения об окладах. В отличие от старых версий (например, ЗУП 2.5), где оклад был жестко привязан к конкретному начислению, в ЗУП 3.1 применяется более гибкая схема. Оклад сотрудника является значением периодического показателя расчета зарплаты.
Данные показатели и их значения на определенные периоды времени регистрируются в специализированных регистрах:
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников — базовый регистр, в котором фиксируются движения документов изменений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковИнтервальный) — вспомогательные таблицы, разработанные для оптимизации построения отчетов. Вместо классического поиска среза последних на каждую дату, система обращается к интервальным таблицам, где для каждой записи уже рассчитаны точные даты начала и окончания действия значения (ДатаНачала и ДатаОкончания).Обращение к этим таблицам напрямую через запросы таит в себе серьезные опасности.
Рассмотрим причины, по которым профессиональные разработчики 1С избегают написания собственных запросов к таблицам показателей окладов:
Решением всех этих проблем является использование официального программного интерфейса (API) конфигурации, а именно функций общего модуля КадровыйУчет.
Для разработчиков конфигурация ЗУП 3.1 предоставляет мощный и оптимизированный инструмент — функцию КадровыеДанныеСотрудников общего модуля КадровыйУчет. Этот метод берет на себя всю рутину по формированию запросов к сложным периодическим и интервальным регистрам, автоматически учитывает права доступа текущего пользователя и гарантирует работоспособность кода после обновлений.
Давайте подробно разберем ключевые параметры этой функции:
ТолькоРазрешенные (тип Булево) — если передать значение Истина, система выберет данные только по тем сотрудникам, к которым у текущего пользователя есть права доступа. Это исключает возникновение ошибок безопасности.МассивСотрудников (тип Массив) — список ссылок на элементы справочника Сотрудники, по которым необходимо получить информацию. Даже если нам нужен только один сотрудник, его необходимо предварительно поместить в массив.КадровыеДанные (тип Строка) — перечень запрашиваемых полей, разделенных запятыми. Для получения размера оклада используется системное имя свойства "ТарифнаяСтавка" (или в некоторых контекстах "ТекущаяТарифнаяСтавка").ДатаСрезаИнформации (тип Дата) — момент времени, на который необходимо получить актуальное значение показателя.Основной вопрос автора темы на форуме заключался в том, как вытащить данные, которые были *до* проведения текущего документа.
Проанализируем ситуацию: документ изменения оплаты труда устанавливает новые значения начислений с определенной даты. Эта дата хранится в реквизите документа (например, ДатаИзменения или ДатаНачалаДействия). Если мы передадим в функцию КадровыеДанныеСотрудников эту дату, то система вернет нам уже *новый* оклад, установленный этим документом.
Для того чтобы заглянуть в прошлое и узнать предыдущую тарифную ставку, нам необходимо сместить дату среза назад. Достаточно вычесть одну секунду из даты начала действия новых начислений. Математически это выглядит следующим образом:
ДатаСреза = ДатаИзменения - 1;
Поскольку периодичность регистров сведений, хранящих оклады, составляет секунду, этот сдвиг гарантированно вернет состояние плановых начислений сотрудника на последнее мгновение перед вступлением в силу новых изменений.
Рассмотрим практический пример кода, который можно использовать в модуле менеджера или в модуле объекта внешней печатной формы для документа «Изменение оплаты труда» (или «Изменение плановых начислений»).
// Предположим, что СсылкаНаОбъект — это ссылка на печатаемый документ изменения оплаты.
// Шаг 1. Получаем необходимые реквизиты документа-основания
РеквизитыДокумента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаОбъект, "Сотрудник, ДатаИзменения");
Если Не ЗначениеЗаполнено(РеквизитыДокумента.Сотрудник) Тогда
Возврат; // Если сотрудник не заполнен, продолжать бессмысленно
КонецЕсли;
// Шаг 2. Формируем массив сотрудников для передачи в программный интерфейс
МассивСотрудников = Новый Массив;
МассивСотрудников.Добавить(РеквизитыДокумента.Сотрудник);
// Шаг 3. Рассчитываем точную дату среза информации (минус 1 секунда от даты изменений)
ДатаСрезаИнформации = РеквизитыДокумента.ДатаИзменения - 1;
// Шаг 4. Указываем кадровое свойство, отвечающее за размер оклада (тарифной ставки)
КадровыеДанные = "ТарифнаяСтавка";
// Шаг 5. Вызываем функцию программного интерфейса 1С:ЗУП 3.1
ТолькоРазрешенные = Истина;
ТаблицаКадровыхДанных = КадровыйУчет.КадровыеДанныеСотрудников(
ТолькоРазрешенные,
МассивСотрудников,
КадровыеДанные,
ДатаСрезаИнформации
);
// Шаг 6. Обрабатываем результат и получаем значение предыдущего оклада
ПредыдущийОклад = 0;
Если ТаблицаКадровыхДанных.Количество() > 0 Тогда
СтрокаДанных = ТаблицаКадровыхДанных[0];
// Проверим наличие колонки в таблице во избежание непредвиденных ошибок
Если ТаблицаКадровыхДанных.Колонки.Найти("ТарифнаяСтавка") <> Неопределено Тогда
ПредыдущийОклад = СтрокаДанных.ТарифнаяСтавка;
КонецЕсли;
КонецЕсли;
// Теперь переменную ПредыдущийОклад можно выводить в макет печатной формы
// Например: ОбластьМакета.Параметры.ПредыдущийОклад = ПредыдущийОклад;
Для того чтобы встроить данный код во внешнюю печатную форму, выполним несколько последовательных шагов интеграции:
Печать(...) или специализированный экспортный метод).ПредыдущийОклад, задав ему соответствующий формат (например, ЧЦ=15; ЧДЦ=2 для корректного отображения копеек).Рассмотрим пример интеграции в цикле по сотрудникам, если печатная форма поддерживает групповую печать из списка документов:
// Пример заполнения параметров макета при обходе документов
Для Каждого ТекущийДокумент Из МассивОбъектов Цикл
// Получаем данные конкретного документа
ДанныеДокумента = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ТекущийДокумент, "Сотрудник, ДатаИзменения, НовыйОклад");
// Сдвигаем время на секунду назад для получения старых данных
ДатаСреза = ДанныеДокумента.ДатаИзменения - 1;
МассивОдногоСотрудника = Новый Массив;
МассивОдногоСотрудника.Добавить(ДанныеДокумента.Сотрудник);
// Запрос к программному интерфейсу
ТаблицаДанных = КадровыйУчет.КадровыеДанныеСотрудников(Истина, МассивОдногоСотрудника, "ТарифнаяСтавка", ДатаСреза);
СтарыйОклад = 0;
Если ТаблицаДанных.Количество() > 0 Тогда
СтарыйОклад = ТаблицаДанных[0].ТарифнаяСтавка;
КонецЕсли;
// Выводим данные в строку табличного документа
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.ФИОСотрудника = ДанныеДокумента.Сотрудник.Наименование;
ОбластьСтрока.Параметры.СтарыйОклад = СтарыйОклад;
ОбластьСтрока.Параметры.НовыйОклад = ДанныеДокумента.НовыйОклад;
ТабличныйДокумент.Вывести(ОбластьСтрока);
КонецЦикла;
При использовании данного метода необходимо учитывать несколько важных практических моментов:
0). В коде желательно предусмотреть обработку этой ситуации (например, выводить прочерк или текст "Нет предыдущих данных").ТарифнаяСтавка возвращает числовое значение. Но помните, что у сотрудника оклад может быть как месячным, так и часовым (часовая тарифная ставка). Если в организации используются разные формы оплаты труда, рекомендуется дополнительно запрашивать параметр СпособРасчетаСтавки или контролировать плановые начисления, чтобы понимать, в чем измеряется оклад (в рублях за месяц или рублях за час).Использование официального API ЗУП 3.1 через вызов КадровыйУчет.КадровыеДанныеСотрудников делает вашу разработку отказоустойчивой, быстрой и полностью совместимой с будущими обновлениями программных продуктов фирмы «1С».