При разработке произвольных отчетов на системе компоновки данных (СКД) в конфигурации Зарплата и управление персоналом 3.0 (ЗУП) программисты часто сталкиваются с тем, что отчет игнорирует конкретные даты начала и конца периода. Например, если указать период с 1 по 2 июля, отчет выведет все начисления за июль. Если же указать со 2 по 3 июля — отчет окажется пустым. Давайте проанализируем эту ситуацию, разберем причины такого поведения платформы и найдем способы решения задачи.
Рассмотрим фрагмент кода, который чаще всего становится источником проблемы. Проблема кроется в обращении к виртуальной таблице оборотов регистра накопления РегистрНакопления.НачисленияУдержанияПоСотрудникам.Обороты. Проанализируем типичный запрос:
ВЫБРАТЬ
НачисленияУдержанияПоСотрудникамОбороты.Организация,
НачисленияУдержанияПоСотрудникамОбороты.ФизическоеЛицо,
НачисленияУдержанияПоСотрудникамОбороты.СуммаОборот
ИЗ
РегистрНакопления.НачисленияУдержанияПоСотрудникам.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК НачисленияУдержанияПоСотрудникамОбороты
В этом запросе используются стандартные параметры &НачалоПериода и &КонецПериода. На первый взгляд, запрос составлен верно, но результат не соответствует ожиданиям пользователя. Выясним причину.
Разберем, как устроены регистры накопления в ЗУП 3.0, такие как НачисленияУдержанияПоСотрудникам или ВзаиморасчетыССотрудниками. В отличие от бухгалтерских регистров или регистров в торговых конфигурациях, записи по начислениям зарплаты в ЗУП всегда «привязываются» к началу месяца. Это называется периодом регистрации.
Если сотруднику начислили оклад за июль 2018 года, то в регистре появится запись, где в поле Период будет стоять дата 01.07.2018 00:00:00. Других записей (например, за 15-е или 20-е число) для этого начисления просто не существует.
Проанализируем поведение системы при разных фильтрах:
Важно различать Период регистрации (когда начислили) и Период действия (за какое время начислили). Данные о периоде действия (например, с какого по какое число сотрудник болел или был в отпуске) хранятся в Регистрах расчета, а не в регистрах накопления.
В представленном запросе данные по командировкам объединяются с данными из регистра расчета РегистрРасчета.Начисления. Однако основная масса данных идет из регистров накопления, которые «не знают» о распределении суммы по дням внутри месяца. Посмотрим на этот участок кода:
ГДЕ Начисления.ПериодРегистрации МЕЖДУ &НачалоПериода И &КонецПериода
И Начисления.Регистратор ССЫЛКА Документ.Командировка
Здесь также используется ПериодРегистрации, что возвращает нас к проблеме первого числа месяца.
Если специфика учета в ЗУП не предполагает детализации начислений по дням в регистрах накопления, самым правильным решением будет ограничить пользователя в выборе дат. Мы можем сделать так, чтобы при выборе любого дня внутри месяца отчет всегда считал данные за полный месяц.
Для этого в СКД на закладке «Параметры» для параметров НачалоПериода и КонецПериода в колонке «Выражение» пропишем следующее:
НАЧАЛОПЕРИОДА(&Период.ДатаНачала, "МЕСЯЦ")КОНЕЦПЕРИОДА(&Период.ДатаКонца, "МЕСЯЦ")Таким образом, даже если пользователь выберет 15-е число, система автоматически подставит 1-е число месяца, и данные будут корректными в контексте методологии ЗУП.
Рассмотрим ситуацию, когда нам действительно нужно увидеть суммы, относящиеся только к выбранным дням (например, расчет за первую неделю месяца). В этом случае использование виртуальных таблиц оборотов регистров накопления нам не поможет.
Нам необходимо переписать запрос, обращаясь к РегиструРасчета.Начисления. Рассмотрим алгоритм:
ФактическийПериодДействия регистра расчета.Пример логики расчета в запросе:
ВЫБОР
КОГДА Начисления.ПериодДействияНачало < &НачалоПериода ТОГДА &НачалоПериода
ИНАЧЕ Начисления.ПериодДействияНачало
КОНЕЦ ... // И далее расчет пропорции суммы
Это значительно усложняет запрос и может привести к погрешностям округления, поэтому такой метод используется редко и только в специфических управленческих отчетах.
В ЗУП 3.0 многие стандартные отборы реализованы через расширения языка запросов СКД. Проанализируем использование фигурных скобок {} в коде автора:
ИЗ РегистрНакопления.ИсчисленныеСтраховыеВзносы.Обороты(&НачалоПериода {(&НачалоПериода)}, &КонецПериода {(&КонецПериода)}, Регистратор, Договорник)
Использование конструкции {(&НачалоПериода)} позволяет СКД заменять параметры на лету. Если вы хотите, чтобы отчет учитывал именно движения (регистраторы) внутри периода, попробуйте изменить периодичность виртуальной таблицы с Авто на Запись или День. Но помните: в регистрах накопления ЗУП это все равно приведет к тому, что записи будут найдены только на 1-е число месяца.
Подведем итоги нашего исследования:
Проанализируйте, какая именно точность нужна вашим пользователям. В 99% случаев для «Расчетной ведомости» достаточно месячной детализации, так как налоги, взносы и большинство начислений в системе рассчитываются и закрываются строго помесячно.