Как правильно рассчитать итоги по ресурсам в СКД и избежать дублирования оплат

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

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

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

Причина возникновения проблемы: эффект «декартова произведения»

Прежде чем переходить к решению, выясним причину ошибки. Когда мы связываем таблицу Продажи.Состав с таблицей Оплаты по полю ДокументОснование, СУБД создает строку для каждой комбинации «Товар — Оплата». Если в реализации 5 товаров и 2 платежных поручения, в выборке получится 10 строк. Сумма каждого платежа повторится 5 раз (по количеству товаров). Стандартный ресурс Сумма(СуммаОплаты) просто сложит всё, что видит в выборке, и выдаст неверный результат.

Решение №1: Использование нескольких наборов данных (Золотой стандарт)

Наиболее правильным и архитектурно верным способом решения задачи в СКД является разделение запроса на два независимых набора данных. Этот метод позволяет системе самостоятельно управлять агрегацией данных на разных уровнях группировки.

Рассмотрим этот метод по шагам:

  1. Создадим НаборДанных1 (Запрос): Здесь мы выбираем данные по реализациям и их табличным частям (номенклатура, количество, сумма продажи).
  2. Создадим НаборДанных2 (Запрос): В этом наборе мы выбираем данные только по оплатам (ПКО, платежные поручения), группируя их по документу-основанию.
  3. Настроим связи: Перейдем на вкладку «Связи наборов данных». Укажем НаборДанных1 как источник связи, а НаборДанных2 как приемник. Условие связи — поле Ссылка (из реализации) и ДокументОснование (из оплат).

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

Решение №2: Использование функции ВычислитьВыражениеСГруппировкойМассив

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

Проанализируем ситуацию: нам нужно просуммировать оплаты, но только один раз для каждого документа оплаты. В поле «Выражение» для ресурса СуммаОплаты следует прописать следующую конструкцию:


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

Разберем, что здесь происходит:

Решение №3: Метод объединения вместо соединения

Еще один профессиональный прием — использование оператора ОБЪЕДИНИТЬ ВСЕ в одном запросе. Вместо того чтобы «растягивать» таблицу оплат вширь (присоединяя её к товарам), мы добавляем её данные вниз.

Рассмотрим структуру такого запроса:


// Часть 1: Данные по товарам
ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    РеализацияТовары.Номенклатура КАК Номенклатура,
    РеализацияТовары.Сумма КАК СуммаПродажи,
    0 КАК СуммаОплаты
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары
ГДЕ ...

ОБЪЕДИНИТЬ ВСЕ

// Часть 2: Данные по оплатам
ВЫБРАТЬ
    Оплата.ДокументОснование КАК Документ,
    ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) КАК Номенклатура,
    0 КАК СуммаПродажи,
    Оплата.Сумма КАК СуммаОплаты
ИЗ
    Документ.ПриходныйКассовыйОрдер КАК Оплата
ГДЕ ...

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

Решение №4: Особенности работы в УТ 11.4 (Использование регистров)

Если вы работаете в конфигурации «Управление торговлей 11.4» (или ERP/КА), получение данных напрямую из табличных частей документов считается признаком неоптимальной разработки. Программа построена на регистрах накопления, в которых данные уже подготовлены для отчетов.

Для получения корректных итогов рекомендуется:

  1. Для данных о продажах использовать виртуальную таблицу Обороты регистра накопления ВыручкаИСебестоимостьПродаж.
  2. Для данных об оплатах использовать регистр РасчетыСКлиентамиПоДокументам.

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

Дополнительно: Исправление ошибки идентификаторов метаданных

В процессе разработки вы можете столкнуться с технической ошибкой: «Для объекта метаданных Отчет.ОтчетОТоварах не найден идентификатор...». Это часто происходит в современных конфигурациях на базе БСП, когда новый отчет еще не зарегистрирован в системе.

Для устранения этой проблемы попробуйте выполнить одно из действий:

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

← На главную