При разработке отчетов на базе системы компоновки данных (СКД) разработчики часто сталкиваются с ситуацией: при формировании отчета по номенклатуре остатки рассчитываются идеально, но стоит пользователю добавить отбор по любому реквизиту документа-регистратора (например, по складу документа, подразделению или номеру), как в строках группировок и общих итогах появляются искаженные начальные остатки. Разберем подробно, почему платформа 1С ведет себя подобным образом и какими способами можно получить корректные данные.
Для понимания сути проблемы проанализируем, как формируются остатки в виртуальной таблице ОстаткиИОбороты регистра накопления. В этой таблице остатки рассчитываются строго в разрезе измерений регистра. Реквизиты регистратора не являются измерениями регистра — они относятся к конкретным точечным движениям.
Когда мы не накладываем отбор по регистраторам, СКД строит выборку на уровне измерений (например, Номенклатура). Начальный остаток на начало периода отчета для номенклатуры рассчитывается один раз.
Однако, как только в отчете появляется отбор по реквизиту регистратора (например, Регистратор.Склад = &Склад), поведение компоновки данных кардинально меняется:
ГДЕ уже после выборки. В результате непрерывная цепочка движений разрывается.Рассмотрим проверенные практические способы обхода этой особенности платформы.
Наиболее надежным архитектурным решением является разделение выборки данных в тексте запроса схемы компоновки данных на две независимые части:
Остатки (на начало и на конец периода) исключительно в разрезе измерений регистра (без участия регистратора). На эту часть не накладываются фильтры по документам.Обороты или реальной таблицы движений регистра. Здесь присутствуют поле Регистратор и все необходимые реквизиты документов, по которым пользователь сможет устанавливать любые отборы.Посмотрим на пример структуры такого запроса:
ВЫБРАТЬ
Остатки.Номенклатура КАК Номенклатура,
НЕОПРЕДЕЛЕНО КАК Регистратор,
НЕОПРЕДЕЛЕНО КАК ПериодСекунда,
Остатки.КоличествоОстаток КАК КоличествоНачальныйОстаток,
0 КАК КоличествоПриход,
0 КАК КоличествоРасход,
0 КАК КоличествоКонечныйОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&НачалоПериода, ) КАК Остатки
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Обороты.Номенклатура,
Обороты.Регистратор,
Обороты.ПериодСекунда,
0,
Обороты.КоличествоПриход,
Обороты.КоличествоРасход,
0
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(&НачалоПериода, &КонецПериода, Авто, ) КАК Обороты
{ГДЕ
Обороты.Регистратор.* КАК Регистратор}
При таком подходе фильтрация по реквизитам документов затронет только оборотные строки, а начальные остатки останутся целостными и рассчитаются строго по измерениям регистра.
Если запрос строится к таблице ОстаткиИОбороты с периодичностью Авто или Регистратор, СКД требует обязательного соблюдения правил связывания временных измерений:
ПериодСекунда или ПериодДень.ПериодСекунда: флаг Период, тип периода — 2.Регистратор: флаг Период, тип периода — 1 (дочерний), флаг Обязательное, а в поле Выражение упорядочивания указан родительский период ПериодСекунда.НачальныйОстаток и КонечныйОстаток соответственно.Если пользователю необходимо видеть общие начальные остатки по номенклатуре без искажений, а фильтровать только состав отображаемых документов в расшифровке, отбор следует перенести из общего корня отчета в настройки конкретной группировки:
Регистратор в структуре отчета.В этом случае базовый расчет на уровне группировки Номенклатура не будет ограничен условиями документов, и начальный остаток по номенклатуре отобразится верно.
Если требуется запретить суммирование начального и конечного остатка на уровнях, где нет прямого соответствия измерениям, настроим закладку Ресурсы:
КоличествоНачальныйОстаток в колонке Рассчитывать по... укажем только измерение Номенклатура и Общий итог, исключив группировку Регистратор.Сумма(КоличествоНачальныйОстаток), либо специализированные формулы вычисления остатков в контексте группировок.Таким образом, исключается механическое суммирование остатков по строкам документов, а отчет возвращает корректные управленческие и складские показатели.