При разработке отчетов на платформе 1С программисты часто сталкиваются с ситуацией, когда простые числовые показатели (сумма, количество) считаются корректно, а вот вычисляемые коэффициенты (цена за единицу, рентабельность, прибыль на квадратный метр) в итогах группировок принимают странные значения. Посмотрим на примере: если мы просто просуммируем результаты деления в каждой строке, то в итоге получим «сумму средних», что не имеет никакого экономического смысла. Проанализируем, почему это происходит и как заставить систему рассчитывать формулу заново для каждого уровня итогов.
Прежде чем переходить к коду, разберем математическую суть проблемы. Предположим, у нас есть две строки в группировке:
Если в запросе мы укажем СУММА(ПрибМ2), система просто сложит 10 и 1, получив 11. Однако правильный расчет для всей группы должен выглядеть иначе: общая прибыль (1100) делится на общую площадь (1010), что дает результат примерно 1.08. Важный вывод: для корректного расчета в итогах нельзя суммировать результат формулы, нужно применять формулу к итоговому результату сумм.
Рассмотрим стандартный запрос 1С. В исходном коде автора была допущена ошибка: в секции ИТОГИ использовалась агрегатная функция СУММА(ПрибМ2). Чтобы исправить расчет в группировках (например, по материалу или городу) и в общих итогах, нам необходимо прописать формулу расчета непосредственно в блоке итогов.
Проанализируем исправленный вариант запроса:
ВЫБРАТЬ
Производство.Заказчик.Город КАК ЗаказчикГород,
Производство.Материал КАК Материал,
СУММА(Производство.ПлощадьИзделия) КАК ПлощадьИзделия,
СУММА(Производство.ЦенаИзделия - Производство.Себестоимость) КАК Прибыль,
// В детальных записях тоже считаем правильно
ВЫБОР
КОГДА Производство.ПлощадьИзделия <> 0
ТОГДА (Производство.ЦенаИзделия - Производство.Себестоимость) / Производство.ПлощадьИзделия
ИНАЧЕ 0
КОНЕЦ КАК ПрибМ2
ИЗ
Документ.Производство.ТабличнаяЧасть1 КАК Производство
ГДЕ
Производство.Ссылка.Проведен = ИСТИНА
СГРУППИРОВАТЬ ПО
Производство.Заказчик.Город,
Производство.Материал
ИТОГИ
СУММА(ПлощадьИзделия),
СУММА(Прибыль),
// КРИТИЧЕСКИ ВАЖНЫЙ МОМЕНТ:
ВЫБОР
КОГДА СУММА(ПлощадьИзделия) <> 0
ТОГДА СУММА(Прибыль) / СУММА(ПлощадьИзделия)
ИНАЧЕ 0
КОНЕЦ КАК ПрибМ2
ПО
ОБЩИЕ,
ЗаказчикГород
В данном примере мы указали системе, что для поля ПрибМ2 на каждом уровне итогов (и для каждого города, и для всего отчета в целом) нужно сначала сложить всю прибыль, затем сложить всю площадь, и только потом выполнить деление. Это гарантирует математическую точность отчета.
Если вы строите отчет не «ручным» запросом, а используете СКД, механизм решения будет несколько иным, но логика останется прежней. В СКД расчет ресурсов настраивается на специальной вкладке.
Разберем по шагам, как настроить расчет коэффициента в СКД:
ПрибМ2 в список ресурсов.Сумма(ПрибМ2) напишем: Сумма(Прибыль) / Сумма(ПлощадьИзделия).ЕстьNull или условие: ВЫБОР КОГДА Сумма(ПлощадьИзделия) = 0 ТОГДА 0 ИНАЧЕ Сумма(Прибыль) / Сумма(ПлощадьИзделия) КОНЕЦ.Важное преимущество СКД: система автоматически применит это выражение ко всем группировкам, которые вы добавите в настройках отчета, будь то иерархия справочников или детальные записи. Нам не нужно прописывать формулу для каждого уровня отдельно.
Проанализируем еще один важный аспект, затронутый в обсуждении. Обращение напрямую к табличным частям документов, таким как Документ.Производство.ТабличнаяЧасть1, является плохой практикой (антипаттерном) в разработке на 1С.
Рассмотрим причины, по которым стоит использовать регистры накопления:
Проведен = ИСТИНА или ПометкаУдаления = ЛОЖЬ.Для корректного отображения вычисляемых полей при группировке данных необходимо соблюдать принцип «Сначала сумма, потом деление». Независимо от того, используете ли вы секцию ИТОГИ в классическом запросе или настраиваете ресурсы в СКД, формула должна оперировать агрегатными значениями СУММА(...), а не пытаться суммировать уже вычисленные в детальных записях коэффициенты.