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

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

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

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

Почему прямой запрос к регистрам в ЗУП 3.1 — это плохая идея?

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

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

Для решения этих задач в системе предусмотрены специальные типовые механизмы и общие модули. Рассмотрим их подробнее.

Решение 1. Использование общего модуля УчетРабочегоВремениРасширенный

Это самый надежный и методически верный способ, который используют сами разработчики фирмы «1С». Для получения планового времени (нормы) без учета фактических отклонений (болезней, отпусков и т.д.) мы будем использовать процедуру УчетРабочегоВремениРасширенный.СоздатьВТДанныеУчетаРабочегоВремениСотрудников.

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

Шаг 1. Подготовка временной таблицы сотрудников

Для работы процедуры нам необходимо передать менеджер временных таблиц, в котором уже присутствует таблица с исходными данными сотрудников. Она должна содержать как минимум три колонки: Сотрудник, ДатаНачала и ДатаОкончания.

Шаг 2. Инициализация параметров и вызов процедуры

Мы инициализируем структуру параметров с помощью типового метода и передаем ее в процедуру формирования временной таблицы.

Рассмотрим пример готового кода на языке 1С:


// Создаем менеджер временных таблиц и запрос
МВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МВТ;

// Шаг 1. Формируем исходную таблицу сотрудников
Запрос.Текст = 
"ВЫБРАТЬ
|	&Сотрудник КАК Сотрудник,
|	&ДатаНачала КАК ДатаНачала,
|	&ДатаОкончания КАК ДатаОкончания
|ПОМЕСТИТЬ ВТСотрудники";

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

// Шаг 2. Заполняем параметры получения времени
ПараметрыПолученияВремени = УчетРабочегоВремениРасширенный.ПараметрыДляЗапросВТДанныеУчетаРабочегоВремениСотрудников();
ПараметрыПолученияВремени.ИмяВТСотрудники = "ВТСотрудники";
ПараметрыПолученияВремени.МенеджерВременныхТаблиц = МВТ;

// Вызываем процедуру формирования ВТ
УчетРабочегоВремениРасширенный.СоздатьВТДанныеУчетаРабочегоВремениСотрудников(ПараметрыПолученияВремени);

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

РезультатЗапроса = Запрос.Выполнить();
ТаблицаНормыВремени = РезультатЗапроса.Выгрузить();

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

Решение 2. Корректировка нормы для уволенных и вновь принятых сотрудников

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

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


// Добавляем получение кадровых данных сотрудников для определения периодов работы
КадровыеДанныеПараметры = КадровыйУчет.ПараметрыДляЗапросаВТКадровыеДанныеСотрудников();
КадровыеДанныеПараметры.ИмяВТСотрудники = "ВТСотрудники";
КадровыеДанныеПараметры.МенеджерВременныхТаблиц = МВТ;
КадровыеДанныеПараметры.КадровыеДанные = "ДатаПриема, ДатаУвольнения";

КадровыйУчет.СоздатьВТКадровыеДанныеСотрудников(КадровыеДанныеПараметры);

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

РезультатСУчетомКадров = Запрос.Выполнить().Выгрузить();

Благодаря этому соединению норма дней будет рассчитана исключительно за те дни месяца, в которые сотрудник имел действующий трудовой договор.

Решение 3. Использование прямого облегченного запроса к регистру ГрафикиРаботыПоВидамВремени

Если вам необходимо обработать колоссальный объем данных (например, за несколько лет по тысячам сотрудников) и использование «тяжелых» процедур общего модуля УчетРабочегоВремениРасширенный вызывает переполнение оперативной памяти или зависание сервера, можно прибегнуть к прямому запросу.

Для корректного отражения нормы нам потребуется связать сотрудника с его актуальным графиком работы и получить плановые показатели из регистра сведений ГрафикиРаботыПоВидамВремени. Важно установить отбор по ресурсу ВремяВЧасах = ЛОЖЬ, чтобы работать именно с днями, а не часами.

Проанализируем структуру такого запроса:


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

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

РезультатПрямогоЗапроса = Запрос.Выполнить().Выгрузить();

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

Подведем итоги

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

← На главную