Как реализовать расчет квартальной премии по сумме отработанных часов и нормы времени в 1С:ЗУП 3.1?

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

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

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

---

1. В чем суть технического ограничения 1С:ЗУП 3.1?

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

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

Мы не можем написать в формуле условное выражение вида Оклад * Процент / 100 * ВремяВЧасах(ПредыдущийКвартал) / НормаЧасов(ПредыдущийКвартал), так как конфигурация попросту не поймет контекста прошлых периодов для этих показателей.

---

2. Математическая ловушка использования «Расчетной базы»

Очень часто в качестве альтернативного (и самого простого) решения предлагают использовать стандартный механизм расчетной базы за предыдущий квартал. Настройка выглядит следующим образом:

  1. Создается начисление с формулой: РасчетнаяБаза * (Процент / 100).
  2. В качестве расчетной базы указывается предопределенное начисление «Оплата по окладу» (или его часовой аналог).
  3. Период расчета базы настраивается как «Предыдущий квартал».

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

Пусть у сотрудника оклад составляет 10 000 рублей. В предыдущем квартале показатели времени распределились следующим образом:

Процент премии составляет 200% (для удобства сопоставления с расчетами автора).

Вариант А. Желаемый расчет (по сумме показателей за квартал):

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

$$\text{Сумма отработанных часов} = 17 + 18 + 19 = 54 \text{ часа}$$

$$\text{Сумма нормы времени} = 22 + 18 + 19 = 59 \text{ часов}$$

$$\text{Доля времени за квартал} = \frac{54}{59} \approx 0.915254$$

$$\text{Результат расчета} = \text{Оклад} \times \frac{\text{Процент}}{100} \times \text{Доля времени} = 10\,000 \times \frac{200}{100} \times \frac{54}{59} = 18\,305{,}08 \text{ руб.}$$

Вариант Б. Расчет через стандартную «Расчетную базу» 1С:

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

$$\text{Оклад за Месяц 1} = 10\,000 \times \frac{17}{22} = 7\,727{,}27 \text{ руб.}$$

$$\text{Оклад за Месяц 2} = 10\,000 \times \frac{18}{18} = 10\,000{,}00 \text{ руб.}$$

$$\text{Оклад за Месяц 3} = 10\,000 \times \frac{19}{19} = 10\,000{,}00 \text{ руб.}$$

$$\text{Итого Расчетная база} = 7\,727{,}27 + 10\,000{,}00 + 10\,000{,}00 = 27\,727{,}27 \text{ руб.}$$

Если мы считаем премию как среднюю долю за квартал (разделив базу на 3 месяца для приведения к месячному окладу) и применив процент:

$$\text{Результат расчета} = \frac{27\,727{,}27}{3} \times \frac{200}{100} = 18\,484{,}84 \text{ руб.}$$

В результате мы получаем расхождение: 18 484,84 руб. против 18 305,08 руб. Разница составляет почти 180 рублей на одном сотруднике. При штате в несколько сотен человек это выливается в огромные суммы переплат или недоплат.

Выясним причину этой погрешности. Математически она объясняется тем, что норма времени в разных месяцах неодинакова (в нашем примере: 22, 18 и 19). Среднее арифметическое от отношений не равно отношению сумм:

$$\frac{\frac{F_1}{N_1} + \frac{F_2}{N_2} + \frac{F_3}{N_3}}{3} \neq \frac{F_1 + F_2 + F_3}{N_1 + N_2 + N_3}$$

Именно из-за этого колебания норм времени стандартная расчетная база искажает итоговый результат, и бухгалтерия абсолютно обоснованно отказывается от этого варианта.

---

3. Решение №1: Настройка схемы со служебным начислением (без программирования)

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

Разберем по шагам схему реализации:

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

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

---

4. Решение №2: Создание внешней обработки заполнения показателей (профессиональный подход)

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

Шаг 1. Создание новых показателей

Для реализации этого метода нам потребуются два новых пользовательских показателя расчета зарплаты. Перейдем в Настройки - Показатели расчета зарплаты и создадим:

  1. ВремяЗаКвартал — числовой, используется «Только в месяце, в котором вводится значение (разовое использование)», вводится непосредственно в документе начисления.
  2. НормаЗаКвартал — аналогичные настройки.

Шаг 2. Настройка формулы начисления

В справочнике «Начисления» создадим новое начисление «Квартальная премия (по часам)». Установим формулу расчета:

Оклад * Процент / 100 * ВремяЗаКвартал / НормаЗаКвартал

Шаг 3. Алгоритм работы внешней обработки

Разработаем внешнюю обработку для заполнения табличной части документа «Премия». При нажатии кнопки заполнения в документе обработка должна выполнять следующие действия:

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

Проанализируем структуру регистров 1С:ЗУП 3.1, откуда следует получать данные. Фактически отработанное время сотрудников хранится в регистре накопления ДанныеОтработанногоВремениРегламентированный. Норма времени по графикам сотрудников содержится в регистре сведений ДанныеГрафикаРаботыАнализ или рассчитывается по производственному календарю и графикам работы.

Рассмотрим пример программного кода запроса для выборки этих показателей:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ДанныеОтработанногоВремени.Сотрудник КАК Сотрудник,
    |	СУММА(ДанныеОтработанногоВремени.ОтработаноЧасов) КАК ВремяЗаКвартал
    |ПОМЕСТИТЬ ВТ_Отработано
    |ИЗ
    |	РегистрНакопления.ДанныеОтработанногоВремениРегламентированный КАК ДанныеОтработанногоВремени
    |ГДЕ
    |	ДанныеОтработанногоВремени.Период МЕЖДУ &НачалоПериода И &КонецПериода
    |	И ДанныеОтработанногоВремени.Сотрудник В (&СписокСотрудников)
    |ГРУППИРОВАТЬ ПО
    |	ДанныеОтработанногоВремени.Сотрудник
    |;
    |
    |ВЫБРАТЬ
    |	ДанныеГрафика.Сотрудник КАК Сотрудник,
    |	СУММА(ДанныеГрафика.Значение) КАК НормаЗаКвартал
    |ПОМЕСТИТЬ ВТ_Норма
    |ИЗ
    |	РегистрСведений.ДанныеГрафикаРаботыАнализ КАК ДанныеГрафика
    |ГДЕ
    |	ДанныеГрафика.Период МЕЖДУ &НачалоПериода И &КонецПериода
    |	И ДанныеГрафика.Сотрудник В (&СписокСотрудников)
    |	И ДанныеГрафика.ВидУчетаВремени = ЗНАЧЕНИЕ(Справочник.ВидыИспользованияВремени.Явка)
    |ГРУППИРОВАТЬ ПО
    |	ДанныеГрафика.Сотрудник
    |;
    |
    |ВЫБРАТЬ
    |	ВТ_Отработано.Сотрудник КАК Сотрудник,
    |	ЕСТЬNULL(ВТ_Отработано.ВремяЗаКвартал, 0) КАК ВремяЗаКвартал,
    |	ЕСТЬNULL(ВТ_Норма.НормаЗаКвартал, 0) КАК НормаЗаКвартал
    |ИЗ
    |	ВТ_Отработано КАК ВТ_Отработано
    |	ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Норма КАК ВТ_Норма
    |	ПО ВТ_Отработано.Сотрудник = ВТ_Норма.Сотрудник";

Запрос.УстановитьПараметр("НачалоПериода", НачалоКвартала);
Запрос.УстановитьПараметр("КонецПериода", КонецКвартала);
Запрос.УстановитьПараметр("СписокСотрудников", МассивСотрудниковДокумента);

После выполнения этого запроса обработка обходит строки табличной части документа «Премия» и автоматически подставляет полученные значения ВремяЗаКвартал и НормаЗаКвартал в соответствующие колонки показателей сотрудников.

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

---

Резюме

Мы выяснили, что для корректного начисления квартальной премии по сумме часов за квартал стандартная «Расчетная база» не подходит из-за математического искажения при сложении долей разных месяцев. Использование служебных начислений решает проблему без программирования, но усложняет учет. Наиболее оптимальным решением является внедрение простой внешней обработки заполнения табличной части, которая берет реальные данные из регистров ДанныеОтработанногоВремениРегламентированный и ДанныеГрафикаРаботыАнализ за нужный период.

← На главную