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