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