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