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