При разработке отчетов или выборок данных в системе 1С:Зарплата и Управление Персоналом 3.1 программисты часто сталкиваются с ситуацией, когда запрос к регистру накопления УдержанияПоИсполнительнымДокументам выдает пустой результат или не группирует записи так, как ожидается. Рассмотрим подробно, почему возникают такие проблемы и как их правильно решить, используя механизмы платформы 1С:Предприятие 8.
В типовом решении автор столкнулся с тем, что запрос к физической таблице регистра не возвращал данные при установке параметров &ДатаНачала и &ДатаКонца. Разберем по шагам основные причины, по которым это может происходить.
Во-первых, критически важно соблюдать последовательность параметров. Если в условии МЕЖДУ дата начала окажется позже даты окончания, результат всегда будет пустым. Проанализируем пример кода автора:
Запрос.Текст = "ВЫБРАТЬ
| УдержанияПоИсполнительнымДокументам.Период КАК Период,
| ...
|ГДЕ
| УдержанияПоИсполнительнымДокументам.Период МЕЖДУ &ДатаНачала И &ДатаКонца";
Запрос.УстановитьПараметр("ДатаНачала", ДатаС);
Запрос.УстановитьПараметр("ДатаКонца", ДатаПо);
Во-вторых, в 1С существует нюанс с «границей даты». Если в качестве &ДатаКонца передается дата без указания времени (например, 31.05.2023 00:00:00), то все записи, сделанные в течение этого дня, не попадут в выборку. Выясним причину: физически документ может иметь время 12:00:00, что строго больше полуночи. Для решения этой проблемы всегда используйте функцию КонецДня() при установке параметров.
Запрос.УстановитьПараметр("ДатаКонца", КонецДня(ДатаПо));
В-третьих, стоит обратить внимание на само поле Период. В регистрах накопления ЗУП 3.1 поле Период часто хранит первое число месяца (период регистрации), а не дату документа. Если вы пытаетесь сделать отбор «внутри» месяца (например, с 10-го по 20-е число), данные за этот месяц не попадут в результат, так как их период — 1-е число.
Для получения итоговых сумм за период (группировка по физлицу и получателю) в 1С правильнее использовать не физическую таблицу, а виртуальную таблицу Обороты. Проанализируем преимущества этого подхода:
ГДЕ.Посмотрим на пример правильного построения запроса через обороты:
ВЫБРАТЬ
УдержанияОбороты.ФизическоеЛицо КАК ФизическоеЛицо,
УдержанияОбороты.Получатель КАК Получатель,
УдержанияОбороты.СуммаУдержанияОборот КАК СуммаУдержания
ИЗ
РегистрНакопления.УдержанияПоИсполнительнымДокументам.Обороты(&НачалоПериода, &КонецПериода, , ) КАК УдержанияОбороты
В этом случае параметры устанавливаются стандартным способом:
Запрос.УстановитьПараметр("НачалоПериода", ДатаС);
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ДатаПо));
Если по какой-то причине необходимо использовать именно физическую таблицу (например, нужны дополнительные данные из регистратора), выясним, как «схлопнуть» записи по физическому лицу. Для этого необходимо применить агрегатные функции и оператор группировки.
Разберем пример запроса с группировкой:
ВЫБРАТЬ
Удержания.ФизическоеЛицо КАК ФизическоеЛицо,
Удержания.Получатель КАК Получатель,
СУММА(Удержания.СуммаУдержания) КАК СуммаУдержания
ИЗ
РегистрНакопления.УдержанияПоИсполнительнымДокументам КАК Удержания
ГДЕ
Удержания.Период МЕЖДУ &ДатаНачала И &ДатаКонца
СГРУППИРОВАТЬ ПО
Удержания.ФизическоеЛицо,
Удержания.Получатель
Важный момент: Чтобы группировка сработала, из списка полей ВЫБРАТЬ нужно обязательно исключить поле Период и Регистратор. Если оставить эти поля, система не сможет сложить суммы, так как для каждой строки период или документ будут уникальными.
Проанализируем структуру регистра УдержанияПоИсполнительнымДокументам. В нем присутствуют измерения ФизическоеЛицо, Организация, Получатель и ИсполнительныйДокумент.
Если ваша задача — получить одну общую сумму по сотруднику независимо от того, по скольким документам (больничным, начислениям) она прошла, используйте группировку только по ФизическоеЛицо и Получатель. Если же у одного сотрудника несколько исполнительных листов одному и тому же получателю и их нужно разделять, добавьте в группировку поле ИсполнительныйДокумент.
Рассмотрим полезный совет по именованию параметров. Вместо имен ДатаС и ДатаПо рекомендуется использовать ДатаНачала и ДатаОкончания. Это снижает вероятность ошибки при вводе дат и делает код более читаемым для других разработчиков.
Подведем итог: для корректной работы запроса всегда проверяйте границы периода с помощью КонецДня(), отдавайте предпочтение виртуальным таблицам .Обороты и внимательно следите за списком полей в секции СГРУППИРОВАТЬ ПО. Это позволит вам получать точные данные из системы 1С:Предприятие без лишних затрат ресурсов сервера.