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

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

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

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

Причины некорректного подсчета остатков

Выясним причину, почему СКД начинает просто суммировать остатки вместо получения фактического среза на начало и конец периода:

  1. Модификация поля Регистратор в тексте запроса. Использование конструкций вида ВЫБОР КОГДА ... ТОГДА ... ИНАЧЕ Регистратор КОНЕЦ или вызов функций типа ТИПЗНАЧЕНИЯ(Регистратор) подменяет стандартное системное поле виртуальной таблицы. В этом случае СКД теряет связь с внутренним механизмом позиционирования движений и не может автоматически применить правила расчета остатков.
  2. Отсутствие поля НомерСтроки. В рамках одного документа-регистратора может быть несколько строк движений. Без поля НомерСтроки невозможно однозначно определить порядок записей на границе периодов, что приводит к искажению итогов.
  3. Неполная настройка роли полей остатков. Если для полей КолНачОст и КолКонОст не задано общее имя группы остатков, СКД воспринимает их как два независимых числовых ресурса и применяет стандартное суммирование.

Решение 1: Корректная настройка ролей полей в наборе данных (Рекомендуемый способ)

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

Шаг 1. Скорректируем запрос набора данных. Уберем искусственные обертки вокруг регистратора и добавим поля периодов и номера строки:


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

Шаг 2. Перейдем на вкладку Наборы данных и настроим колонку Роль для каждого поля:

  1. Для полей измерений Номенклатура и ХарактеристикаНоменклатуры установим флаг Измерение.
  2. Для поля ПериодСекунда установим флаг Период и укажем порядковый номер 1.
  3. Для поля Регистратор установим флаг Период, порядковый номер 2 и флаг Игнорировать NULL.
  4. Для поля НомерСтроки установим флаг Период и порядковый номер 3.
  5. Для поля КолНачОст укажем тип Начальный остаток и заполним свойство Имя значением Количество.
  6. Для поля КолКонОст укажем тип Конечный остаток и в свойстве Имя укажем то же самое значение Количество.

Шаг 3. На вкладке Ресурсы укажем стандартные формулы расчета:


Сумма(КолПриход)
Сумма(КолРасход)
Сумма(КолНачОст)
Сумма(КолКонОст)

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

Решение 2: Использование функций языка выражений СКД

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

Для агрегации конечного остатка по конкретной группировке можно использовать функцию ВычислитьВыражениеСГруппировкойМассив(). Посмотрим на пример выражения для ресурса КолКонОст:


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

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

Решение 3: Разделение на отдельные таблицы в запросе

Если требуется полностью исключить зависимость от механизма периодов СКД, можно переписать запрос, объединив или соединив отдельные виртуальные таблицы:

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

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

← На главную