При разработке отчетов на базе регистров накопления программисты часто сталкиваются с неприятной ситуацией: если по конкретному объекту (контрагенту, номенклатуре, складу) в выбранном периоде отсутствуют движения (приходы или расходы), то отчет выводит пустой результат, даже если на начало периода есть ненулевое сальдо. Рассмотрим подробнее, почему так происходит и как заставить систему показывать данные правильно.
Разберем ситуацию на примере виртуальной таблицы ОстаткиИОбороты. По умолчанию эта таблица оптимизирована для производительности. Если в параметрах таблицы не указан специальный метод дополнения периодов, система анализирует только те моменты времени, в которых зафиксированы реальные записи в регистре (физические движения документов). Если между датой начала и датой конца отчета документов не было, запрос просто не находит строк для формирования выборки, и начальный остаток «теряется» для системы компоновки данных.
Первое, что необходимо сделать — это изменить четвертый параметр виртуальной таблицы ОстаткиИОбороты. Проанализируем стандартный запрос, который часто генерирует конструктор:
ВЫБРАТЬ
РасчетыСПоставщикамиОстаткиИОбороты.Поставщик КАК Поставщик,
РасчетыСПоставщикамиОстаткиИОбороты.СуммаНачальныйОстаток КАК СуммаНачальныйОстаток,
РасчетыСПоставщикамиОстаткиИОбороты.СуммаКонечныйОстаток КАК СуммаКонечныйОстаток
ИЗ
РегистрНакопления.РасчетыСПоставщиками.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, Движения, ) КАК РасчетыСПоставщикамиОстаткиИОбороты
В данном примере используется метод дополнения Движения. Это означает, что записи будут выбраны только за те секунды/дни, когда были движения. Чтобы исправить это, заменим параметр на ДвиженияИГраницыПериода. Посмотрим на обновленный код:
ВЫБРАТЬ
РасчетыСПоставщикамиОстаткиИОбороты.Поставщик КАК Поставщик,
РасчетыСПоставщикамиОстаткиИОбороты.СуммаНачальныйОстаток КАК СуммаНачальныйОстаток,
РасчетыСПоставщикамиОстаткиИОбороты.СуммаПриход КАК СуммаПриход,
РасчетыСПоставщикамиОстаткиИОбороты.СуммаРасход КАК СуммаРасход,
РасчетыСПоставщикамиОстаткиИОбороты.СуммаКонечныйОстаток КАК СуммаКонечныйОстаток
ИЗ
РегистрНакопления.РасчетыСПоставщиками.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, ДвиженияИГраницыПериода, ) КАК РасчетыСПоставщикамиОстаткиИОбороты
Теперь система принудительно добавит в результат запроса две виртуальные записи: на начало периода и на конец периода. Даже если оборотов не было, начальная граница периода «подтянет» актуальный остаток, и он отобразится в отчете.
После включения метода ДвиженияИГраницыПериода вы можете заметить, что в отчете появились странные пустые строки, в которых выводится только сальдо, а поля Регистратор или ПериодДень не заполнены. Выясним причину этого поведения.
Так как записи границ периода являются виртуальными, у них нет физического регистратора (документа). Если в вашем отчете настроена детальная группировка по регистратору, СКД честно выводит эти технические строки. Чтобы избавиться от визуального мусора, выполним следующие действия:
Регистратор Заполнено. Это скроет пустые строки границ, при этом итоги по остаткам на уровне вышестоящих группировок сохранятся.ЕСТЬNULL(СуммаНачальныйОстаток, 0).Если вы используете Систему компоновки данных, мало просто изменить запрос. Выясним, как правильно настроить вкладку «Наборы данных». Для корректной работы остатков СКД должна понимать, какое поле является начальным остатком, а какое — конечным. Проверьте следующие настройки в колонке «Роль»:
СуммаНачальныйОстаток: установите тип Остаток, вид Начальный. Укажите «Имя группы» (например, «Сумма») и обязательно выберите соответствующее поле конечного остатка.СуммаКонечныйОстаток: установите тип Остаток, вид Конечный, имя группы то же самое («Сумма»).ПериодСекунда) должны иметь роль Период с соответствующим порядковым номером.Важный нюанс: Если роли не настроены, СКД может начать суммировать остатки по иерархии группировок как обычные числа, что приведет к неверным итоговым суммам (остатки будут удваиваться или утраиваться при наличии нескольких движений внутри периода).
В сложных случаях, когда виртуальная таблица ОстаткиИОбороты ведет себя непредсказуемо из-за специфических фильтров, рассмотрим вариант разделения запроса на два набора данных или две временные таблицы:
Остатки на начало периода (виртуальная таблица Остатки).Обороты за период (виртуальная таблица Обороты).Этот способ гарантирует наличие строки с контрагентом, если у него был остаток, даже если во второй таблице (оборотах) данных нет. Конечный остаток в этом случае рассчитывается формулой: НачальныйОстаток + Приход - Расход. Для построения выборок срезов остатков на диапазоне дат в запросах можно использовать методику формирования срезов остатков и диапазонов дат через запросы.
Проанализируем еще одну частую ошибку. Иногда программисты накладывают условия на данные в секции ГДЕ основного запроса, а не в параметрах виртуальной таблицы. Рассмотрим пример неправильного кода:
ВЫБРАТЬ ...
ИЗ РегистрНакопления.РасчетыСПоставщиками.ОстаткиИОбороты(,, Авто, ДвиженияИГраницыПериода, ) КАК Таблица
ГДЕ Таблица.Организация = &Организация
В этом случае записи дополнения (границы), созданные системой, могут быть отсечены условием ГДЕ, если поле организации в них окажется пустым или не будет соответствовать логике компоновки. Правильный подход — передавать все фильтры по измерениям непосредственно в параметры виртуальной таблицы (последний параметр «Условие»).
Подведем итог: для исправления «пропадающего» сальдо используйте метод ДвиженияИГраницыПериода, правильно настраивайте роли полей в конструкторе СКД и следите за тем, чтобы фильтры не отсекали технические записи границ периода.