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