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