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