При разработке складских отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда в детальных записях (например, по регистратору) остатки отображаются верно, но в итоговых строках по номенклатуре или складу цифры становятся «астрономическими». Система вместо того, чтобы показать реальный остаток на конец периода, просто суммирует все значения из строк ниже. Разберем детально, почему это происходит и как настроить отчет правильно.
Основная причина кроется в том, как СКД воспринимает поля ресурсов. По умолчанию, если мы добавляем поле КонечныйОстаток в ресурсы, система применяет к нему функцию Сумма(). Если для поля не настроены специальные роли, СКД не понимает, что это «остаток», и обрабатывает его как обычное число (как количество прихода или сумму продажи).
Когда мы выводим отчет с детализацией до Регистратора, в каждой строке фиксируется состояние остатка после конкретного документа. Если мы просто сложим эти значения в группировке по Номенклатуре, мы получим бессмысленную сумму промежуточных состояний склада, а не актуальный остаток. Чтобы этого избежать, нам нужно задействовать механизм ролей СКД.
Прежде всего, убедимся, что запрос написан оптимально для работы с периодами. Для получения ведомости остатков и оборотов крайне важно использовать виртуальную таблицу ОстаткиИОбороты. Проанализируем правильное заполнение параметров:
ВЫБРАТЬ
ТоварыНаСкладахОстаткиИОбороты.Номенклатура КАК Номенклатура,
ТоварыНаСкладахОстаткиИОбороты.Склад КАК Склад,
ТоварыНаСкладахОстаткиИОбороты.КоличествоНачальныйОстаток КАК НачальныйОстаток,
ТоварыНаСкладахОстаткиИОбороты.КоличествоПриход КАК Приход,
ТоварыНаСкладахОстаткиИОбороты.КоличествоРасход КАК Расход,
ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток КАК КонечныйОстаток,
ТоварыНаСкладахОстаткиИОбороты.Регистратор КАК Регистратор,
ТоварыНаСкладахОстаткиИОбороты.ПериодСекунда КАК ПериодСекунда
ИЗ
РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , ) КАК ТоварыНаСкладахОстаткиИОбороты
Обратим внимание на параметр Периодичность. Установка значения Авто — обязательное условие. Это позволяет СКД самостоятельно определять нужные периоды в зависимости от настроек группировок пользователя.
Это самый важный этап. Перейдем на закладку «Наборы данных» и найдем колонку «Роль» для наших полей остатка. Нам необходимо вручную указать системе, как работать с этими данными.
Рассмотрим настройку для поля НачальныйОстаток:
Начальный.Количество.Номенклатура, Склад, Серия). Без этого СКД не поймет, в разрезе чего нужно «схлопывать» остатки.Аналогично настроим поле КонечныйОстаток, выбрав вид Конечный и указав то же имя группы — Количество.
Чтобы иерархия периодов работала корректно, СКД должна знать, какое поле является временным измерением. Если мы используем Регистратор, ему нужно назначить роль Период.
Если в отчете используется несколько временных полей (например, ПериодДень и Регистратор), важно правильно расставить их порядковые номера в роли. Для ПериодДень это будет 1, для Регистратор — 2. Это указывает системе на вложенность периодов: регистратор находится «внутри» дня.
Также рекомендуется установить флаг «Обязательное» для поля Регистратор в ролях, если вы планируете видеть движения в разрезе документов, иначе расчет итогов может сбоить при определенных отборах.
После того как мы правильно настроили роли в наборе данных, перейдем на закладку «Ресурсы». Несмотря на то что мы указали роли «Остаток», в выражении ресурса все равно должно стоять Сумма(КонечныйОстаток).
Многих это смущает: «Почему опять сумма?». Дело в том, что благодаря настроенным ролям СКД теперь применяет «умное суммирование». Для детальных записей она покажет значение, а для группировок — значение на начало/конец временного интервала этой группировки по указанным измерениям.
Проанализируем пример: если на начало дня было 10 штук, пришло 5, и в конце дня стало 15, то при наличии двух регистраторов (приходов) СКД не сложит 10+15, а возьмет 10 как начальный остаток группировки «День» и 15 как конечный.
Разберем еще несколько моментов, которые могут влиять на результат:
ГДЕ Период МЕЖДУ..., СКД не сможет рассчитать остаток на начало периода, так как данные до этой даты будут отсечены. Всегда используйте параметры &НачалоПериода и &КонецПериода в самой виртуальной таблице.Автозаполнение в наборе данных мешает ручным настройкам ролей. Если вы настроили роли, но результат не изменился, попробуйте отключить автозаполнение и прописать все поля и их связи вручную.Следуя этим шагам, мы получим корректную ведомость, где остатки по группам (Номенклатура, Склад, Иерархия) будут соответствовать реальному состоянию учета, а не сумме всех строк регистратора.