При отладке механизмов расчета пособий по временной нетрудоспособности в программе «1С:Зарплата и управление персоналом» (ЗУП) разработчики часто сталкиваются с неочевидным поведением системы. Например, когда выражение в отладчике Окр(СреднийВсего * ПроцентОплаты / 100, 2) возвращает одно значение (например, 410,8), а в итоговую переменную ДневноеПособие записывается совершенно другое число (например, 445,36). На первый взгляд это может показаться ошибкой округления, сбоем платформы или скрытым переопределением в расширениях. Однако за таким поведением скрываются строгие законодательные алгоритмы расчета пособий. Разберем детально, почему так происходит, как устроен этот механизм и где именно в коде искать корни проблемы.
Для того чтобы понять логику программы, обратимся к Федеральному закону № 255-ФЗ «Об обязательном социальном страховании на случай временной нетрудоспособности и в связи с материнством». Согласно закону, расчет пособия по временной нетрудоспособности регулируется двумя параллельными правилами ограничения минимального размера выплаты. Программа обязана рассчитать оба варианта и выбрать наибольший из них.
Рассмотрим эти правила на примере сотрудника, работающего на полставки (коэффициент ставки — 0,5), при условии, что федеральный МРОТ равен 27 093 рублям:
Если фактический средний заработок сотрудника за предыдущие два календарных года ниже рассчитанного по МРОТ, то расчет производится исходя из МРОТ на дату наступления страхового случая. Формула расчета минимального среднего дневного заработка (СДЗ):
СДЗ_мин = (МРОТ * 24 / 730) * ДоляСтавки
Подставим наши значения:
(27093 * 24 / 730) * 0.5 = 890.72877 * 0.5 = 445.36438
После округления до двух знаков после запятой мы получаем фиксированную величину минимального дневного заработка — 445,36 руб.
Этот минимум («путинский минимум», введенный в период пандемии) гарантирует, что за полный календарный месяц болезни сотрудник получит сумму не ниже МРОТ (с учетом его доли ставки). Поскольку количество дней в месяцах различается, дневной лимит по этому правилу плавает и рассчитывается отдельно для каждого месяца болезни по формуле:
Лимит_месяца = (МРОТ / КалендарныеДниМесяца) * ДоляСтавки
Проанализируем, как количество календарных дней в месяце влияет на итоговый выбор программы 1С:ЗУП.
Ситуация А: Расчет в месяце с 31 днем (май, март, август)
Рассчитаем лимит по Правилу 2 для месяца, содержащего 31 календарный день:
27093 / 31 * 0.5 = 436.98 руб.
Программа сопоставляет значения:
Так как 445,36 руб. больше, чем 436,98 руб. и 410,80 руб., программа выбирает его в качестве итогового дневного пособия. Именно поэтому в переменную ДневноеПособие попадает значение 445,36.
Ситуация Б: Расчет в месяце с 30 днями (апрель, июнь, сентябрь)
Рассчитаем лимит по Правилу 2 для месяца, содержащего 30 календарных дней:
27093 / 30 * 0.5 = 451.55 руб.
Снова сопоставим значения:
В этом случае лимит полного месяца (451,55 руб.) оказывается больше, чем СДЗ по стандартному МРОТ (445,36 руб.). Программа обязана начислить пособие исходя из большей величины. За 2 дня апреля сумма составит: 451,55 * 2 = 903,10 руб.
Выясним причину, почему при прохождении отладчиком строчки расчета разработчик видит в вычислении выражения 410,8, а в переменную записывается 445,36. В конфигурации «1С:Зарплата и управление персоналом» расчет пособий выполняется поэтапно в специализированных общих модулях (например, УчетПособийСоциальногоСтрахования или РасчетПособий).
Упрощенно алгоритм сравнения и переопределения переменных выглядит следующим образом:
// Шаг 1: Определение фактического СДЗ сотрудника
ФактическийСДЗ = СреднийВсего * ПроцентОплаты / 100; // Здесь получается 410,80
// Шаг 2: Расчет минимального СДЗ из МРОТ по Правилу 1
МинимальныйСДЗИзМРОТ = Окр((МРОТ * 24 / 730) * ДоляСтавки, 2); // Получается 445,36
// Шаг 3: Сравнение и выбор наибольшего СДЗ для расчета
РасчетныйСДЗ = Макс(ФактическийСДЗ, МинимальныйСДЗИзМРОТ); // 445,36 побеждает 410,80
// Шаг 4: Расчет по дням с учетом ограничений конкретного месяца (Правило 2)
Для Каждого СтрокаПериода Из ТаблицаДнейБЛ Цикл
ДнейВМесяце = ПолучитьКоличествоДнейВМесяце(СтрокаПериода.Дата);
МинимумЗаМесяц = Окр((МРОТ / ДнейВМесяце) * ДоляСтавки, 2);
// Итоговое дневное пособие не может быть ниже минимума за месяц
СтрокаПериода.ДневноеПособие = Макс(РасчетныйСДЗ, МинимумЗаМесяц);
КонецЦикла;
При отладке разработчик часто анализирует только базовую строчку расчета исходной переменной и вычисляет её значение «в лоб» через табло или выражение быстрого просмотра. Однако далее по коду алгоритм выполняет проверки ограничений (Шаг 3 и Шаг 4), переопределяя значение переменной ДневноеПособие. Именно поэтому итоговый результат в переменной отличается от ручного вычисления формулы.
Для того чтобы эффективно анализировать подобные ситуации в будущем и не тратить время на поиски несуществующих ошибок округления, рекомендуем придерживаться следующих правил: