Работа с виртуальными таблицами остатков и оборотов в Системе компоновки данных (СКД) часто преподносит сюрпризы, особенно когда разработчику необходимо вывести детальные записи до регистратора. Основная сложность заключается в том, что при выборе периодичности Регистратор платформа 1С выдает состояние остатка после каждого движения. Если мы просто применим агрегатную функцию Сумма к такому полю в ресурсах, то получим бессмысленные цифры — система просто сложит все промежуточные состояния долга, вместо того чтобы показать актуальный остаток.
В этой статье мы подробно разберем, как заставить СКД корректно отображать остаток по каждой накладной и, что более важно, правильно складывать эти остатки в общих итогах по контрагенту или всему отчету. Рассмотрим несколько подходов: от простых манипуляций с выражениями ресурсов до глубокой настройки ролей полей.
Проанализируем ситуацию на примере. Допустим, у нас есть реализация на 10 000 рублей. По ней было две оплаты: 3 000 и 2 000 рублей. В виртуальной таблице ОстаткиИОбороты с периодичностью Регистратор мы увидим три строки:
Если мы установим ресурс ДолгКонечныйОстаток с функцией Сумма, то в итоге по этой реализации мы увидим 22 000 рублей (10 000 + 7 000 + 5 000), хотя фактический долг составляет всего 5 000. Использование функции Минимум спасет ситуацию внутри группировки по накладной, но в общем итоге по контрагенту система выберет минимальный долг среди всех его накладных (например, 0 по одной из закрытых сделок), вместо того чтобы сложить долги по всем незакрытым реализациям.
Для того чтобы получить корректный общий итог, нам нужно сказать системе: «Сначала возьми по каждой накладной последнее (минимальное) значение остатка, а затем сложи эти значения между собой». Рассмотрим, как это реализовать на вкладке Ресурсы в СКД.
Разберем по шагам настройку выражения для поля ДолгКонтрагентаНаКонецПериода:
ВычислитьВыражениеСГруппировкойМассив.Пример правильного выражения ресурса:
Сумма(ВычислитьВыражениеСГруппировкойМассив("Минимум(ДолгКонечныйОстаток)", "ДокументОтгрузки"))
Рассмотрим подробнее, как работает эта формула:
1. "Минимум(ДолгКонечныйОстаток)" — это агрегат, который вычисляется внутри каждой группы по накладной. Так как остаток уменьшается с каждой оплатой, минимальное значение будет соответствовать самому последнему состоянию взаиморасчетов.
2. "ДокументОтгрузки" — это поле группировки, в разрезе которого мы хотим собрать наши «правильные» остатки.
3. ВычислитьВыражениеСГруппировкойМассив — эта функция обходит все документы отгрузки в текущей группировке (например, по контрагенту), вычисляет для каждого минимальный остаток и помещает эти результаты в массив.
4. Сумма(...) — внешняя функция складывает все элементы полученного массива, выдавая математически верный итог долга.
Выясним причину, почему СКД иногда сама не справляется с остатками. Для того чтобы механизмы компоновки работали корректно в автоматическом режиме, необходимо правильно настроить вкладку Наборы данных, а именно колонку Роль для полей остатков.
Выполним следующие настройки для поля ДолгКонечныйОстаток:
Долг). Это свяжет начальный и конечный остатки в одну логическую сущность.Конечный.КредитныйДокумент (или ДокументОтгрузки).Когда роли настроены верно, СКД при суммировании итогов будет опираться на Поле учета. Она поймет, что если в рамках одного «Поля учета» (одной накладной) встречается несколько строк с остатками, то для итогов нужно брать только последнее значение, а не суммировать их все.
Если отчет очень сложный и настройки ресурсов не помогают, рассмотрим вариант с разделением данных. Это наиболее надежный, хоть и чуть более трудоемкий метод.
Проанализируем ситуацию: нам нужны обороты с регистраторами и итоговый остаток по накладной. Мы можем создать два набора данных — типа «Запрос»:
Остатки на дату конца периода.Затем перейдем на вкладку Связи наборов данных и свяжем их по полям Контрагент и Накладная. В этом случае поле ДолгКонечныйОстаток будет приходить из второго набора, где на каждую накладную приходится строго одна строка. Теперь обычная функция Сумма(ДолгКонечныйОстаток) в ресурсах будет работать абсолютно корректно, так как дублирование строк из-за регистраторов больше не влияет на поле остатка.
Иногда задача требует вычислить остаток математически прямо в ресурсах, если данные в регистре по какой-то причине не позволяют взять готовый срез. Как упоминалось в обсуждении, мы можем комбинировать агрегатные функции разных полей.
Например, если нам нужно рассчитать долг как разницу между суммой накладной и всеми оплатами, выражение может выглядеть так:
Максимум(СуммаОтгрузкиПоНакладной) - Сумма(СуммаОплатыЗаПериод)
В данном примере Максимум(СуммаОтгрузкиПоНакладной) позволит избежать дублирования суммы самой накладной в строках с разными платежками (так как сумма накладной везде одинакова, максимум из них будет равен самой сумме), а Сумма(СуммаОплатыЗаПериод) честно сложит все платежи. Однако помните, что этот метод работает только если отчет строится строго по документам отгрузки и не учитывает начальные остатки за прошлые периоды.
Резюме: Для получения корректных итогов в сложных отчетах с регистраторами наиболее гибким и современным инструментом является функция ВычислитьВыражениеСГруппировкойМассив. Она позволяет обойти ограничения стандартного суммирования и получить точные данные в общих итогах отчета.