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