Как правильно рассчитать сумму через цену и количество в группировках отчета СКД

Программист 1С v8.3 (Управляемые формы) Управленческий учет Торговля и дистрибуция
← На главную

При разработке отчетов на Системе компоновки данных (СКД) начинающие разработчики часто сталкиваются с ситуацией, когда в детальных записях (строках с регистратором) расчеты верны, но в итогах по группировкам (например, по товару или складу) цифры становятся «космическими» или просто нелогичными. Типичный пример — отчет по движениям товаров, где нужно вывести остаток, цену и сумму (Остаток * Цена). Разберем по шагам, почему это происходит и как настроить отчет правильно.

Анализ причины проблемы: Математика СКД

Выясним причину, по которой обычное перемножение в вычисляемых полях или запросе дает сбой в итогах. Рассмотрим ситуацию: у вас есть товар, который поступал на склад тремя разными документами (регистраторами). При левом соединении таблицы остатков с регистром цен, цена «прилипает» к каждой строке движения.

Когда СКД рассчитывает итог по группировке «Товар», она видит несколько строк. Если в ресурсах просто указано Сумма(Цена * Количество), система может повести себя двояко в зависимости от настроек:

  1. Она может просуммировать все цены во всех строках и умножить на сумму всех количеств.
  2. Она может просуммировать уже перемноженные значения каждой строки, где цена дублируется из-за регистратора.

В обоих случаях результат будет неверным, так как для остатка товара нам нужна одна актуальная цена, умноженная на итоговый остаток, а не сумма цен всех движений.

Шаг 1. Оптимизация запроса и избавление от дублей

Проанализируем исходный запрос. В сообщении форума было предложено заменить конструкцию ВЫРАЗИТЬ на проверку ссылки. Это не только ускоряет запрос, но и делает его более читаемым. Также важно заменить NULL на 0 для корректной арифметики.

Рассмотрим пример правильного написания условий в запросе:


ВЫБОР
    КОГДА ТоварыНаСкладахОстаткиИОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваров
        ТОГДА ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход
    ИНАЧЕ 0
КОНЕЦ КАК КоличествоПродаж

Использование 0 вместо NULL критически важно, так как в 1С любое число, умноженное на NULL, дает NULL, что может полностью обнулить итог по группировке, если хотя бы в одной строке цена не определена.

Шаг 2. Настройка вычисляемых полей и ресурсов

Самая распространенная ошибка — оставлять формулу Цена * Количество только в вычисляемых полях или в самом тексте запроса, не определяя правила агрегации на вкладке «Ресурсы». Для системы компоновки данных поле, полученное перемножением, является обычным числом, и она складывает его простым суммированием.

Чтобы получить верную сумму в группировке по товару, нам нужно указать СКД, как именно рассчитывать итог. Рассмотрим два способа настройки ресурса «СуммаКонечныйОстаток»:

  1. Простой способ: Сумма(КоличествоКонечныйОстаток * Цена). Этот метод сработает корректно только в том случае, если цена в пределах одной группировки (одного товара) гарантированно одинакова.
  2. Профессиональный способ: использование функции ВычислитьВыражениеСГруппировкойТаблица. Это позволяет системе сначала рассчитать итог внутри каждой номенклатуры, а затем сложить эти итоги для вышестоящих уровней (Склад, Организация).

Пример выражения для ресурса «Сумма» на вкладке «Ресурсы»:

Сумма(ВычислитьВыражениеСГруппировкойТаблица("КоличествоКонечныйОстаток * Цена", "Товар"))

Шаг 3. Учет роли полей остатка

В СКД у полей остатков (Начальный и Конечный) есть специальная роль в схеме компоновки. Если мы просто перемножаем КоличествоКонечныйОстаток * Цена, результат перестает восприниматься системой как «остаток». Это значит, что при выводе итогов по времени (например, за период день/месяц) суммы будут складываться, хотя остатки складывать нельзя — нужно брать только последнее значение.

Для корректного решения этой задачи проанализируем настройки полей. Убедимся, что для поля КоличествоКонечныйОстаток на вкладке «Наборы данных» указана роль «Остаток», выбран тип (Конечный) и указано имя соответствующего начального остатка.

В ресурсах для итогов по временным периодам лучше использовать формулу:

Сумма(КоличествоКонечныйОстаток) * Максимум(Цена)

Это гарантирует, что для итоговой суммы будет взято актуальное количество на конец периода и умножено на актуальную цену.

Шаг 4. Соединение наборов данных (Альтернативный подход)

Рассмотрим более продвинутый метод, который часто помогает избежать проблем с «размножением» строк из-за левого соединения. Вместо того чтобы соединять таблицы ОстаткиИОбороты и СрезПоследних прямо в SQL-запросе, мы можем разделить их на два разных набора данных в СКД.

Разберем алгоритм:

  1. Создадим НаборДанных1 (запрос), который получает только остатки и обороты товаров.
  2. Создадим НаборДанных2 (запрос), который получает цены из регистра сведений ЦеныНоменклатуры.СрезПоследних.
  3. Перейдем на вкладку «Связи наборов данных».
  4. Свяжем наборы по полю Товар. В параметре связи для цены (период) укажем дату, на которую нам нужны цены (например, конец периода отчета).

Такой подход позволяет 1С сначала рассчитать все итоги по количеству, а затем «подтянуть» цену к уже сгруппированным строкам. Это исключает дублирование записей регистратора и делает расчет суммы максимально прозрачным.

Резюме

Для того чтобы отчет выводил корректные суммы, придерживаемся следующих правил:

Применяя эти методы, мы добьемся того, что и в детальных записях, и в группировках по товарам, складам или иерархическим группам номенклатуры сумма всегда будет соответствовать ожидаемому значению Количество * Цена.

← На главную