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