Почему искажаются остатки в СКД при добавлении поля «Регистратор» и как это исправить?

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

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

Выясним причину проблемы

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

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

Способ 1: Использование виртуальной таблицы «ОстаткиИОбороты»

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

Посмотрим по шагам, как это сделать:

  1. Перепишем запрос, обратившись к одной виртуальной таблице регистра ОстаткиИОбороты.
  2. В параметрах виртуальной таблицы установим параметр периодичности в значение Авто или Регистратор.
  3. В этом случае платформа 1С самостоятельно сгенерирует правильное объединение и корректно рассчитает итоги, избавив нас от необходимости вручную настраивать роли и связи.

Способ 2: Жесткая настройка ролей в наборе данных

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

Настройка ролей для полей остатков:

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

Настройка роли для регистратора:

Полю регистратора также необходимо присвоить правильную роль. Укажем тип «Период» и зададим ему порядковый номер. Обычно регистратор идет после поля ПериодСекунда, поэтому номер должен быть соответствующим. Дополнительно в настройках роли регистратора настоятельно рекомендуется установить флаг Игнорировать NULL. Это заставит систему отсекать пустые строки, которые не относятся к документам движения, при расчете итогов.

Чтобы СКД еще корректнее обрабатывала пустые значения непосредственно на уровне SQL-запроса, применим следующую конструкцию при выборке поля:


ВЫБОР 
    КОГДА Регистратор = НЕОПРЕДЕЛЕНО ТОГДА NULL 
    ИНАЧЕ Регистратор 
КОНЕЦ

Способ 3: Разделение на несколько наборов данных

Разберем еще один эффективный архитектурный подход. Если обойтись одним запросом слишком сложно, рекомендуется уйти от использования конструкции ОБЪЕДИНИТЬ ВСЕ внутри самого текста запроса.

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

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

← На главную