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