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