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

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

При разработке сложных отчетов на базе Системы компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда стандартные агрегатные функции начинают вести себя непредсказуемо. Типичный симптом: начальные и конечные остатки в отчете отображаются верно, но итоги по приходу или расходу либо обнуляются, либо «схлопываются» (например, вместо суммы 100 + 100 отчет выводит 100). Особенно часто это проявляется, когда данные собираются не из одной виртуальной таблицы, а через ОБЪЕДИНИТЬ ВСЕ из нескольких временных таблиц.

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

Причина 1: Неправильная настройка ролей полей

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

Проанализируем шаги по исправлению ролей:

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

Причина 2: Проблема уникальности записей и ключевых полей

Если в отчете мы видим, что сумма двух разных документов реализации по 100 рублей в итоге дает 100 рублей, это явный признак того, что СКД посчитала эти записи дублями. Рассмотрим, почему это происходит. Система компоновки при расчете ресурсов группирует данные по измерениям и периодам. Если в наборе данных не определены ключевые поля, позволяющие однозначно отличить одну запись от другой, СКД может «схлопнуть» их при вычислении итогов.

Для решения этой проблемы выполним следующие действия:

  1. В запросе обязательно выберем поле Регистратор и, что еще важнее, НомерСтроки (или уникальный идентификатор записи).
  2. На закладке Набор данных отметим Регистратор и ПериодСекунда как обязательные поля или укажем их в качестве ключевых.
  3. Если мы используем временные таблицы, убедимся, что при объединении (UNION ALL) в результирующую таблицу попадают все необходимые разрезы данных, включая секунду и регистратор.

Причина 3: Отсутствие периода «Секунда» при детализации до регистратора

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

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


ВЫБРАТЬ
    Остатки.Номенклатура,
    Остатки.Склад,
    Остатки.ПериодСекунда,
    Остатки.Регистратор,
    Остатки.КоличествоНачальныйОстаток,
    Остатки.КоличествоПриход,
    Остатки.КоличествоРасход,
    Остатки.КоличествоКонечныйОстаток
ИЗ
    ВТ_ОбъединенныеДанные КАК Остатки

Причина 4: Обработка значений NULL в левых соединениях

Часто к основной таблице остатков левым соединением подключаются дополнительные данные (цены, упаковки, характеристики). Выясним, как это влияет на итоги. Если для какой-то позиции номенклатуры цена не найдена, в поле цены попадет NULL. В консоли запросов СУММА может работать корректно, но СКД при построении сложного дерева итогов может исключать строки с NULL из расчета определенных ресурсов.

Рекомендация: Всегда оборачивайте числовые поля, получаемые через левое соединение, в функцию ЕСТЬNULL.


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

Причина 5: Специфика виртуальных таблиц и автозаполнения

Проанализируем случай, когда использование временных таблиц блокирует возможность СКД автоматически настраивать параметры. Если мы используем ВременныеТаблицы, СКД не может применить расширение языка запросов для виртуальных таблиц (такое как {ГДЕ ...} или автоматический расчет периодичности).

Если проблему не удается решить настройкой ролей, попробуем изменить архитектуру отчета:

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

Использование статей ИТС для глубокого анализа

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

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

← На главную