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

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

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

Анализ механизма работы виртуальных таблиц и СКД

Для понимания сути проблемы проанализируем, как формируются остатки в виртуальной таблице ОстаткиИОбороты регистра накопления. В этой таблице остатки рассчитываются строго в разрезе измерений регистра. Реквизиты регистратора не являются измерениями регистра — они относятся к конкретным точечным движениям.

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

Однако, как только в отчете появляется отбор по реквизиту регистратора (например, Регистратор.Склад = &Склад), поведение компоновки данных кардинально меняется:

  1. СКД вынуждена опустить расчет выборки до детальных записей — уровня отдельных документов (регистраторов).
  2. Для каждого документа, попавшего в выборку, вычисляется срез остатка непосредственно на момент проведения этого документа.
  3. Условие отбора по реквизиту документа накладывается платформой в секции ГДЕ уже после выборки. В результате непрерывная цепочка движений разрывается.
  4. При сворачивании данных в вышестоящую группировку (по номенклатуре) СКД суммирует полученные срезы начальных остатков по всем отобранным строкам документов, воспринимая их как слагаемые. В итоге получается арифметическая сумма остатков на моменты проведения каждого документа вместо реального остатка на начало выбранного периода.

Рассмотрим проверенные практические способы обхода этой особенности платформы.

Способ 1. Разделение запроса на таблицы остатков и оборотов

Наиболее надежным архитектурным решением является разделение выборки данных в тексте запроса схемы компоновки данных на две независимые части:

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

Посмотрим на пример структуры такого запроса:


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

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

ВЫБРАТЬ
    Обороты.Номенклатура,
    Обороты.Регистратор,
    Обороты.ПериодСекунда,
    0,
    Обороты.КоличествоПриход,
    Обороты.КоличествоРасход,
    0
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК Обороты
{ГДЕ
    Обороты.Регистратор.* КАК Регистратор}

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

Способ 2. Корректная настройка ролей полей и периодов в СКД

Если запрос строится к таблице ОстаткиИОбороты с периодичностью Авто или Регистратор, СКД требует обязательного соблюдения правил связывания временных измерений:

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

Способ 3. Перенос отбора в группировку детальных записей

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

  1. Открываем закладку Настройки в СКД.
  2. Выбираем группировку Регистратор в структуре отчета.
  3. Переходим на вкладку Отбор для этой конкретной группировки и добавляем условие по реквизитам регистратора.

В этом случае базовый расчет на уровне группировки Номенклатура не будет ограничен условиями документов, и начальный остаток по номенклатуре отобразится верно.

Способ 4. Настройка выражений ресурсов по группировкам

Если требуется запретить суммирование начального и конечного остатка на уровнях, где нет прямого соответствия измерениям, настроим закладку Ресурсы:

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

Таким образом, исключается механическое суммирование остатков по строкам документов, а отчет возвращает корректные управленческие и складские показатели.

← На главную