Как в ЗУП 3.1 программно получить остатки отпусков по видам для списка сотрудников

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

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

Причина проблемы: «Эффект наблюдателя» и кеширование данных

Многие разработчики замечают странное поведение системы: если вызвать программную функцию получения остатков, она возвращает 0. Но стоит пользователю открыть типовой отчет «Остатки отпусков» по этому же сотруднику, как программный метод тут же начинает возвращать корректные цифры. Рассмотрим подробнее, почему так происходит.

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

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

Шаг 1: Принудительная актуализация данных

Чтобы данные в регистре соответствовали текущему состоянию кадрового учета, необходимо использовать метод АктуализироватьДанныеОбОстаткахОтпусков. Выясним, как выглядит этот вызов:


// МассивСотрудников - список ссылок на справочник Сотрудники
// НужнаяДата - дата, на которую требуется актуальность данных
ОстаткиОтпусков.АктуализироватьДанныеОбОстаткахОтпусков(МассивСотрудников, НужнаяДата);

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

Шаг 2: Подготовка параметров для детального расчета

Стандартная функция ОстаткиОтпусковСотрудниковНаДату является упрощенной оберткой, которая внутри себя «сворачивает» таблицу, удаляя информацию о видах отпусков (основной, дополнительный, северный и т.д.). Чтобы получить детализацию, нам нужно использовать основной метод ОстаткиОтпусков.ОстаткиОтпусков(), предварительно настроив структуру параметров.

Разберем по шагам создание структуры параметров:

  1. Инициализируем структуру с помощью типовой функции описания, чтобы не пропустить важные поля.
  2. Заполняем обязательные поля: список сотрудников и дату.
  3. Настраиваем флаги детализации.

Посмотрим на пример кода:


// Получаем пустую структуру параметров с правильным составом полей
ПараметрыОстатков = ОстаткиОтпусков.ОписаниеПараметровДляОстаткиОтпусков();

// Заполняем основные данные
ПараметрыОстатков.Сотрудники = СписокСотрудников; // Массив или СписокЗначений
ПараметрыОстатков.ДатаОстатков = КонецДня(ДатаРасчета);

// Ключевой момент: отключаем удаление детализации
ПараметрыОстатков.УдалятьДетализациюПоВидамОтпусков = Ложь;

// Если нужны остатки за конкретные рабочие года, можно также указать:
// ПараметрыОстатков.УдалятьДетализациюПоПериодам = Ложь;

Шаг 3: Получение и обработка результата

Теперь вызовем основную функцию. В отличие от упрощенных методов, ОстаткиОтпусков.ОстаткиОтпусков(ПараметрыОстатков) возвращает не просто таблицу, а структуру таблиц. Нас интересует таблица ОстаткиПоВидамОтпусков.

Проанализируем пример полной реализации задачи:


// 1. Актуализируем данные в регистре
ОстаткиОтпусков.АктуализироватьДанныеОбОстаткахОтпусков(МассивСотрудников, ДатаРасчета);

// 2. Настраиваем параметры
ПараметрыОстатков = ОстаткиОтпусков.ОписаниеПараметровДляОстаткиОтпусков();
ПараметрыОстатков.Сотрудники = МассивСотрудников;
ПараметрыОстатков.ДатаОстатков = НачалоДня(ДатаРасчета + 86400); // Получаем остаток на "конец дня"
ПараметрыОстатков.УдалятьДетализациюПоВидамОтпусков = Ложь;

// 3. Вызываем расчет
РезультатРасчета = ОстаткиОтпусков.ОстаткиОтпусков(ПараметрыОстатков);

// 4. Извлекаем таблицу с видами отпусков
// В этой таблице будут колонки: Сотрудник, ВидОтпуска, Остаток, КоличествоДней
ТаблицаОстатков = РезультатРасчета.ОстаткиПоВидамОтпусков;

Для Каждого СтрокаОстатка Из ТаблицаОстатков Цикл
    Сообщить("Сотрудник: " + СтрокаОстатка.Сотрудник 
        + ", Вид отпуска: " + СтрокаОстатка.ВидОтпуска 
        + ", Остаток дней: " + СтрокаОстатка.Остаток);
КонецЦикла;

Важные нюансы при работе с датами и видами отпусков

При получении остатков следует учитывать специфику 1С в плане временных границ. Функция ОстаткиОтпусков обычно рассчитывает данные на начало дня. Если вам нужно узнать, сколько дней отпуска накоплено у сотрудника по состоянию на вечер конкретного числа (включая этот рабочий день), в параметр ДатаОстатков рекомендуется передавать следующий день. Либо использовать КонецДня(НужнаяДата), но будьте внимательны, так как алгоритмы расчета иногда могут вести себя по-разному в зависимости от версии конфигурации.

Виды отпусков: если в параметрах поле ВидыОтпусков оставить пустым (Неопределено), система вернет данные по всем правам, которые закреплены за сотрудником в его кадровой истории. Если же вам нужен только основной отпуск, передайте в этот массив конкретную ссылку из справочника ВидыОтпусков.

Отрицательные остатки: Если сотрудник отгулял больше дней, чем заработал, поле Остаток будет содержать отрицательное число. В структуре параметров за это отвечает флаг РассчитыватьДолгиПоОтпускам, который по умолчанию обычно установлен в Истина.

Заключение

Для надежного получения остатков отпусков в ЗУП 3.1 в разрезе их видов необходимо отказаться от простых функций-оберток в пользу метода ОстаткиОтпусков.ОстаткиОтпусков() с детальной настройкой параметров. Помните, что без предварительного вызова процедуры АктуализироватьДанныеОбОстаткахОтпусков вы рискуете получить устаревшие данные из кеша регистра сведений, что и порождает пресловутый «эффект наблюдателя».

← На главную