Почему периодический показатель расчета зарплаты в 1С:ЗУП возвращает 0 в последний день месяца?

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

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

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

Описание проблематики

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

?(ОплатаВыходногоДня = 1, ВремяВДняхЧасах * СтоимостьДняЧаса, 0)

Где ОплатаВыходногоДня — это созданный пользователем показатель расчета зарплаты.

Работа механизма организована следующим образом:

  1. В документе «Работа в выходные и праздники» добавлен специальный флажок, используя дополнительные реквизиты табличных частей.
  2. При проведении документа, если флажок установлен, программно создается запись в регистр сведений ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.
  3. Запись формируется со следующими параметрами:
    • Показатель: ОплатаВыходногоДня
    • Значение: 1
    • Период: 31.05.2024 0:00:00
    • Действует до: 31.05.2024

Симптомы проблемы: При расчете заработной платы за май, строка с начислением оказывается пустой или равной нулю, несмотря на то, что сотрудник реально работал 31 мая, и запись в регистре присутствует. Если же аналогичная ситуация происходит в середине месяца, расчет выполняется корректно.

Анализ технической причины: «Проблема границ»

Чтобы понять, почему начисление не видит показатель, нам необходимо изучить то, как платформа 1С и механизм расчета зарплаты (движок ЗУП) работают с периодическими данными.

Регистр сведений ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников хранит историю изменений значений, по аналогии с тем, как ведется кадровая история сотрудников интервальный. Когда мы указываем дату окончания действия («Действует до»), система должна определить интервал, в котором показатель активен.

В описанном случае период записи (начало действия) — 31.05.2024 0:00:00. Дата окончания действия («Действует до») также установлена как 31.05.2024. Здесь возникает коллизия, которую можно трактовать двояко:

  1. Нулевая длительность: Если алгоритм получения данных (виртуальная таблица среза последних или запрос внутри модуля расчета) воспринимает дату окончания строго как момент времени (31.05.2024 0:00:00), то интервал действия показателя схлопывается в ноль. Он начал действовать и тут же закончил.
  2. Исключение границы: В многих алгоритмах 1С правая граница интервала может не включаться в выборку. При расчете зарплаты за 31 число система пытается получить значение показателя, действующее на этот день. Из-за совпадения дат начала и "сброса" значения, движок считает, что значение уже неактуально.

Особенно остро это проявляется именно в последний день месяца, так как это граничная дата периода регистрации документа «Начисление зарплаты». В середине месяца (например, 15-го числа) следующий день (16-е) еще принадлежит текущему периоду расчета, и алгоритмы могут «прощать» неточности в часах/секундах, но на стыке месяцев логика становится строже.

Решение 1: Корректировка периода действия (Программный метод)

Если мы хотим сохранить текущую архитектуру («велосипед») и заставить показатель работать, нам необходимо явно указать системе, что показатель действует весь день 31 мая.

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

Давайте посмотрим, как следует изменить логику заполнения набора записей:


// Неправильный подход, который приводит к ошибке:
НаборЗаписей.ДействуетДо = ДатаДокумента; // Например, 31.05.2024

// Правильный подход:
// Устанавливаем дату окончания действия на 1-е число следующего месяца
// или на следующий день, чтобы перекрыть весь текущий день.
НаборЗаписей.ДействуетДо = КонецДня(ДатаДокумента) + 1; 
// Или еще надежнее:
НаборЗаписей.ДействуетДо = НачалоДня(ДобавитьМесяц(ДатаДокумента, 1)); // 01.06.2024

Установив дату «Действует до» равной 01.06.2024, мы гарантируем, что в любой момент времени 31 мая (будь то начало, середина или конец смены) показатель ОплатаВыходногоДня будет равен 1.

Решение 2: Изменение настроек показателя

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

Давайте изменим настройки показателя ОплатаВыходногоДня:

  1. Откроем справочник Показатели расчета зарплаты.
  2. Найдем наш показатель.
  3. Изменим переключатель «Назначение показателя» на «Накапливаемый по отдельным значениям» или «Вводится единовременно» (только в месяце, когда вводится значение).

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

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

Решение 3: Возврат к типовому механизму (Рекомендуемое)

Наиболее надежный и профессиональный путь — отказаться от использования искусственного показателя-флага ОплатаВыходногоДня. Типовая конфигурация ЗУП 3.1 уже содержит мощный механизм учета работы в выходные дни, который не требует доработок кода.

Давайте разберем, как это работает в стандарте:

  1. Документ «Работа в выходные и праздники» при проведении фиксирует не просто «флаг», а специальный Вид времени (обычно это «Праздники и выходные» — код РВ) в регистре накопления и табеле.
  2. Формула начисления оплаты за работу в выходной день в типовой поставке выглядит примерно так:
    ВремяВДняхЧасах * СтоимостьДняЧаса * 2
  3. Показатель ВремяВДняхЧасах является предопределенным. Самое важное: он автоматически возвращает количество часов только за те дни, когда зафиксирован соответствующий вид времени (РВ).

Почему это лучше?

Использование типового механизма избавляет от проблем с «границами дат», «срезами последних» и необходимостью поддерживать сложный кастомный код при обновлениях 1С.

Диагностика проблемы

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

  1. Универсальный отчет. Сформируйте отчет по регистру сведений Значения периодических показателей расчета зарплаты (для сотрудников).

    Отберите записи по проблемному сотруднику и показателю. Внимательно посмотрите на колонки «Период» и «Действует до». Если они совпадают с точностью до секунды или дня (в зависимости от типа поля), это верный признак проблемы.

  2. Пересчет планового ФОТ. Иногда показатели «застревают» в кэше ФОТ. Попробуйте запустить обработку пересчета ФОТ для сотрудника. Если ошибка в периодах, это не поможет, но исключит фактор устаревших данных.
  3. Документ «Начисление зарплаты». Нажмите кнопку «Подробно» (значок калькулятора) в строке начисления. Платформа покажет, какие значения показателей она «видит» в момент расчета. Если там стоит 0 или пустота напротив вашего показателя — проблема точно в выборке данных из регистра.

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

← На главную