При разработке отчетов в конфигурациях 1С:Зарплата и управление персоналом 3.1 (ЗУП) или 1С:Зарплата и кадры государственного учреждения (ЗКГУ) часто возникает задача отобрать данные по совмещениям сотрудников. Основная сложность заключается в том, что период документа совмещения может лишь частично пересекаться с периодом, который выбрал пользователь в отчете. Например, совмещение назначено с 15 сентября по 15 октября, а отчет формируется за октябрь. В этом случае документ обязательно должен попасть в выборку.
В этой статье мы разберем, как правильно составить запрос к интервальным регистрам, проанализируем условия пересечения периодов и оптимизируем код для получения корректных кадровых данных.
В ЗУП 3.1 для учета занятости позиций штатного расписания и фактически выполняемых работ используются специальные "интервальные" регистры сведений. В нашем случае наиболее подходящим является РегистрСведений.ЗанятостьПозицийШтатногоРасписанияИнтервальный. Его преимущество в том, что он уже хранит данные в виде готовых периодов (с датой начала и датой окончания), что значительно упрощает написание запросов по сравнению с классическими регистрами сведений.
Рассмотрим структуру этого регистра, которая нам понадобится:
Сотрудник — кто выполняет совмещение.ДатаНачала и ДатаОкончания — границы интервала записи.ВидЗанятостиПозиции — позволяет отфильтровать именно совмещения (значение перечисления Совмещена).ДокументОснование — ссылка на сам документ Совмещение должностей.Для того чтобы выбрать все записи, которые хотя бы одним днем попадают в выбранный пользователем период (&НачалоПериода - &КонецПериода), необходимо реализовать логику пересечения. Существует четыре классических случая:
Многие разработчики пытаются описать все эти условия через громоздкие конструкции ИЛИ и МЕЖДУ. Однако проанализируем ситуацию: все эти четыре условия сводятся к одной простой формуле, которая является стандартом в разработке на 1С:
ДатаНачала <= &КонецПериода И ДатаОкончания >= &НачалоПериода
Давайте разберем, как применить это знание на практике. Вместо использования ОБЪЕДИНИТЬ ВСЕ, как это часто делают новички, мы напишем элегантный и производительный запрос. Проанализируем пример кода:
ВЫБРАТЬ
Занятость.Сотрудник КАК Сотрудник,
Занятость.ДатаНачала КАК ДатаНачала,
Занятость.ДатаОкончания КАК ДатаОкончания,
Занятость.ДокументОснование КАК ДокументОснование,
Занятость.ДокументОснование.ПричинаСовмещения КАК ВидДополнительнойРаботы,
Занятость.ДокументОснование.РазмерДоплаты КАК РазмерДоплаты,
Занятость.ЗамещаемыйСотрудник КАК ЗамещаемыйСотрудник
ПОМЕСТИТЬ ВТ_Совмещения
ИЗ
РегистрСведений.ЗанятостьПозицийШтатногоРасписанияИнтервальный КАК Занятость
ГДЕ
Занятость.ВидЗанятостиПозиции = ЗНАЧЕНИЕ(Перечисление.ВидыЗанятостиПозицийШтатногоРасписания.Совмещена)
И Занятость.ДатаНачала <= &ДатаОкончания
И Занятость.ДатаОкончания >= &ДатаНачала
;
Обратите внимание на работу с пустой датой окончания. В ЗУП бессрочные начисления или совмещения записываются с датой окончания 31.12.3999. Указанное выше условие отлично справляется с такими датами, так как 31.12.3999 всегда будет больше любой разумной &ДатаНачала, выбранной пользователем.
Просто получить список документов часто недостаточно. Обычно требуется вывести должность сотрудника, его подразделение или ФИО замещаемого коллеги. Проанализируем ситуацию с полем ЗамещаемыйСотрудник. Как было отмечено в обсуждении, это поле может быть пустым, если совмещение оформлено на вакантную ставку (позицию штатного расписания).
Для корректного получения данных на дату события в ЗУП 3.1 рекомендуется использовать временные таблицы и механизмы общих модулей, но если мы пишем чистый запрос в СКД, нам нужно соединиться с кадровыми данными. Рассмотрим правильный способ компоновки:
ВЫБРАТЬ
ВТ_Совмещения.Сотрудник КАК Сотрудник,
ВТ_Совмещения.ДокументОснование КАК ДокументОснование,
ВТ_Совмещения.ДатаНачала КАК ДатаНачалаСовмещения,
ВТ_Совмещения.ДатаОкончания КАК ДатаОкончанияСовмещения,
// Выбираем данные через точку от документа, если это допустимо для производительности
ВТ_Совмещения.ДокументОснование.Организация КАК Организация,
ВТ_Совмещения.ЗамещаемыйСотрудник КАК ЗамещаемыйСотрудник,
// Получаем текущие кадровые данные сотрудника
КадровыеДанные.Подразделение КАК Подразделение,
КадровыеДанные.Должность КАК Должность
ИЗ
ВТ_Совмещения КАК ВТ_Совмещения
ЛЕВОЕ СОЕДИНЕНИЕ СрезПоследних.КадроваяИсторияСотрудников КАК КадровыеДанные
ПО ВТ_Совмещения.Сотрудник = КадровыеДанные.Сотрудник
И КадровыеДанные.Период <= ВТ_Совмещения.ДатаНачала
Если вы используете этот запрос в СКД, важно помнить о параметрах. Чтобы условия по датам применялись гибко, можно использовать виртуальные таблицы (если данные берутся из них) или стандартные отборы. Выясним причину, по которой иногда отчет работает медленно: это происходит из-за избыточных группировок (СГРУППИРОВАТЬ ПО), которые часто добавляются автоматически при использовании конструктора. Если записи в интервальном регистре уникальны по документам-основаниям, группировку можно исключить.
Важный нюанс: поле Регистратор в интервальных регистрах не всегда совпадает с полем ДокументОснование. Всегда используйте ДокументОснование для получения данных о параметрах совмещения (причина, сумма доплаты, начисление), так как именно это поле является ключевым для связи с первичным документом.
Разберем по шагам алгоритм создания идеального запроса для совмещений:
ЗанятостьПозицийШтатногоРасписанияИнтервальный.Совмещена.НачалоДокумента <= КонецОтчета И КонецДокумента >= НачалоОтчета.ДокументОснование (тип Документ.СовмещениеДолжностей).ЗамещаемыйСотрудник, помня о вакансиях.Используя этот подход, вы получите точный список всех совмещений, действовавших в любой момент выбранного периода, независимо от того, когда они были открыты или закрыты.