При разработке внешних печатных форм или кастомных отчетов в конфигурации 1С:Зарплата и Управление Персоналом 3.1 программисты часто сталкиваются с неприятной особенностью: функция программного получения остатка отпуска выдает результат, который отличается от типовой справки об отпусках ровно на 2.33 дня. Как мы знаем, 2.33 — это стандартное количество дней отпуска, полагающееся сотруднику за один полностью отработанный месяц (при норме 28 дней в году).
Разберем подробно, почему возникает эта «потеря» месяца и как правильно вызывать программные функции, чтобы их результат на 100% совпадал с данными кадрового учета.
Проанализируем ситуацию, когда мы передаем дату в функцию ОстаткиОтпусковСотрудниковНаДату. Внутри программного кода типовой конфигурации эта функция часто принудительно приводит переданную дату к началу дня с помощью оператора НачалоДня(ДатаОстатков).
Рассмотрим, как это влияет на логику программы. В 1С:ЗУП 3.1 право на очередной месяц отпуска (те самые 2.33 дня) возникает, когда сотрудник отработал более 15 дней в текущем рабочем месяце. Если дата остатков попадает точно на границу, когда до выполнения условия «отработано полных 15 дней» не хватает буквально одной секунды, программа отбрасывает этот месяц.
Типовые отчеты (например, «Справка об остатках отпусков») при формировании «на дату» фактически рассчитывают данные на 00:00:00 следующего дня. Это позволяет включить весь рабочий день выбранной даты в стаж сотрудника. Если же мы вызываем функцию программно и передаем туда дату без учета времени, она воспринимается как '2023-05-20 00:00:00'. В итоге 20-е число в расчет не попадает, и если именно этого дня не хватало для закрытия очередного месяца стажа, мы получаем заниженный результат.
Для того чтобы программный вызов функции ОстаткиОтпусковСотрудниковНаДату вернул те же данные, что и пользователь видит в интерфейсе, попробуем передавать дату «с запасом» в один день или использовать конец дня.
Посмотрим на пример кода, который часто приводит к ошибке:
// Ошибочный вариант: может не хватать 2.33 дня
МассивСотрудников = Новый Массив;
МассивСотрудников.Добавить(СсылкаНаСотрудника);
Остатки = ОстаткиОтпусков.ОстаткиОтпусковСотрудниковНаДату(МассивСотрудников, ДатаОтчета);
А теперь проанализируем правильный подход. Чтобы синхронизировать расчет с типовыми механизмами, рекомендуется передавать либо начало следующего дня, либо использовать функцию КонецДня, если вызываемая процедура корректно ее обрабатывает:
// Правильный вариант №1: Смещение на начало следующего дня
ДатаРасчета = НачалоДня(ДатаОтчета) + 86400; // Добавляем сутки
Остатки = ОстаткиОтпусков.ОстаткиОтпусковСотрудниковНаДату(МассивСотрудников, ДатаРасчета);
// Правильный вариант №2: Использование КонецМесяца (если расчет идет на конец периода)
Остатки = ОстаткиОтпусков.ОстаткиОтпусковСотрудниковНаДату(МассивСотрудников, КонецМесяца(ДатаОтчета));
Выясним еще один важный технический момент. Функция ОстаткиОтпусковСотрудниковНаДату в общем модуле ОстаткиОтпусков является упрощенной «оберткой». Типовые отчеты в ЗУП 3.1 строятся на системе компоновки данных (СКД), которая обращается к виртуальным таблицам и более сложным внутренним механизмам, учитывающим не только фактические остатки, но и планируемые отпуска, а также корректировки.
Если простая корректировка даты не помогает, стоит обратить внимание на процедуру СформироватьТаблицуОстатковОтпусков. Она позволяет получить более детальную структуру данных. Проанализируем пример ее вызова:
СтруктураПараметров = ОстаткиОтпусков.ОписаниеПараметровДляОстаткиОтпусков();
СтруктураПараметров.Сотрудники = МассивСотрудников;
СтруктураПараметров.ДатаОстатков = КонецДня(ДатаОтчета);
// Установка флага, чтобы расчет соответствовал регламентированному учету
СтруктураПараметров.ВидыОтпусков = ВидыОтпусков;
РезультатТаблица = ОстаткиОтпусков.ОстаткиОтпусков(СтруктураПараметров);
Именно использование расширенной структуры параметров позволяет избежать «потери» данных из-за специфических настроек учета (например, если в программе включено использование общих остатков отпусков или ведутся сложные расчеты по нескольким видам отпусков одновременно).
Разберем ситуацию, связанную с отпусками за свой счет (без сохранения оплаты). Согласно законодательству, если сотрудник берет более 14 дней за свой счет в течение рабочего года, дата окончания его рабочего года смещается.
Типовой отчет при формировании справки анализирует все документы-отклонения. Если ваша программная функция вызывается в контексте, где не обновлены временные таблицы запроса или не учтены последние проведенные документы (в случае внешней обработки), расчет может «промахнуться» мимо даты окончания рабочего года на те же 2.33 дня. Всегда проверяйте, чтобы на момент вызова функции все кадровые приказы были проведены.
Если вы обнаружили расхождение в 2.33 дня при использовании программного кода в ЗУП 3.1, выполните следующие шаги:
НачалоДня(ВашаДата) + 1 (следующий день). В 90% случаев это решает проблему «недосчитанного» месяца.ВидыОтпусков не заполнен.ОстаткиОтпусков.ОстаткиОтпусков(СтруктураПараметров) с предварительным заполнением через ОписаниеПараметровДляОстаткиОтпусков().Помните, что в версии 3.1 разработчики 1С заложили иную логику по сравнению с версией 2.5, и именно дата среза теперь играет ключевую роль в определении права на накопленные дни отдыха.