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

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

При разработке отчетов в системе компоновки данных (СКД) разработчики часто сталкиваются с ситуацией, когда данные из разных источников имеют разную степень детализации (гранулярность). Типичный пример: продажи или кассовые чеки ведутся с детализацией до кассира, а безналичная выручка фиксируется суммарно за день (или привязана к Z-отчету/терминалу без разделения по сотрудникам).

В результате при левом соединении таблиц в запросе суточная сумма безналичных оплат дублируется в строке каждого кассира, работавшего в этот день. Например, если 31 декабря работали два кассира, у каждого в строке отображается по 1000 рублей. При стандартной агрегации Сумма(Безналичные) система сложит эти показатели и выдаст в итоге дня 2000 рублей вместо фактической 1000 рублей, а также исказит общий итог за весь период.

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

Выясним причину дублирования данных

Проанализируем механику работы СКД. При обычном формировании отчета платформа применяет агрегатную функцию к детальным записям результирующей таблицы запроса. Если в выборке за одну дату сформировалось несколько строк из-за группировки по кассирам, то поле с суточной безналичной суммой дублируется физически в каждой строке выборки. Стандартное выражение ресурса суммирует каждую запись, что приводит к завышению показателей.

Простая замена агрегата на Максимум(Безналичные) решает вопрос только на уровне группировки по конкретной дате, но ломает общий итог за период: вместо сложения показателей разных дней СКД выведет максимальное значение за весь период среди всех дат.

Рассмотрим несколько рабочих подходов для решения этой задачи.

Способ 1. Использование функций агрегации по массиву в ресурсах СКД

Наиболее гибкий способ, не требующий кардинального переписывания запросов, заключается в тонкой настройке вкладки Ресурсы схемы компоновки данных. Платформа 1С:Предприятие 8 позволяет указывать различные формулы расчета одного и того же ресурса для разных уровней группировок.

Разберем по шагам, как настроить расчет ресурса:

  1. Перейдем на вкладку Ресурсы в схеме компоновки данных.
  2. Добавим поле Безналичные для расчета по группировке Дата (и по детальным записям/кассирам). В колонке Выражение укажем: Максимум(Безналичные)
  3. Добавим вторую строку для этого же поля Безналичные, но колонку Рассчитывать по... оставим пустой (это определит расчет для общего итога отчета). В колонке Выражение пропишем специальную конструкцию с агрегацией по массиву:

Сумма(ВычислитьВыражениеСГруппировкойМассив("Максимум(Безналичные)", "Дата"))

Посмотрим на логику работы этой формулы: функция ВычислитьВыражениеСГруппировкойМассив сначала вычисляет максимальное значение поля внутри каждой уникальной даты, складывает полученные результаты в промежуточный массив, а внешняя функция Сумма складывает элементы этого массива для формирования общего итога отчета. В итоге за каждую дату берется ровно одно значение, и все даты корректно плюсуются между собой.

Важное ограничение: данный способ жестко завязан на имя группировки. Если пользователь в режиме предприятия изменит структуру отчета (например, удалит группировку по полю Дата), расчет общего итога может выдать ошибку или неверный результат.

Способ 2. Разделение данных на отдельные наборы и настройка связей

Второй надежный подход — разделить получение данных на два отдельных набора данных (набора данных — запрос) внутри СКД, как предлагалось в обсуждении:

  1. НаборДанных1 (Детализация по кассирам): выбирает данные по чекам, наличным и сотрудникам с группировкой по полям Дата и Кассир.
  2. НаборДанных2 (Суточные итоги безналичных оплат): выбирает общую сумму безналичных оплат исключительно в разрезе поля Дата (без поля Кассир).
  3. На вкладке Связи наборов данных настраиваем связь от НабораДанных1 к НаборуДанных2 по полю Дата (при необходимости также связываем организацию, кассу ККМ или подразделение).

В этом случае поле Безналичные присутствует только на уровне группировки по дате и не привязывается к строкам кассиров. В ресурсах можно использовать стандартную функцию Сумма(Безналичные), и дублирования не возникнет, так как СКД сама распределит агрегацию на соответствующий уровень иерархии.

Способ 3. Выравнивание данных на уровне текста запроса

Если требуется оставить один набор данных и использовать стандартные настройки ресурсов, задвоение можно устранить непосредственно в запросе. Для этого сумму безналичных оплат относят только к одной первой строке кассира за день, а для остальных строк кассиров за этот же день выводят 0.

Рассмотрим пример реализации с помощью временных таблиц и нумерации строк:


ВЫБРАТЬ
    Продажи.Дата КАК Дата,
    Продажи.Кассир КАК Кассир,
    Продажи.Наличные КАК Наличные,
    ВЫБОР
        КОГДА Продажи.Кассир = ПервыеКассиры.Кассир
            ТОГДА БезналичныеПоДням.СуммаБезналичные
        ИНАЧЕ 0
    КОНЕЦ КАК Безналичные
ИЗ
    ВТ_ПродажиКассиров КАК Продажи
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_БезналичныеПоДням КАК БезналичныеПоДням
        ПО Продажи.Дата = БезналичныеПоДням.Дата
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            Дата,
            МИНИМУМ(Кассир) КАК Кассир
        ИЗ
            ВТ_ПродажиКассиров
        СГРУППИРОВАТЬ ПО
            Дата
    ) КАК ПервыеКассиры
        ПО Продажи.Дата = ПервыеКассиры.Дата

При таком подходе обычная Сумма(Безналичные) в ресурсах СКД корректно отработает на всех уровнях отчета: в детальных записях безналичная сумма будет показана один раз у первого кассира дня, внутри группировки дня сумма сойдется без дублей, а в общем итоге сложатся все дни.

← На главную