Как правильно настроить вывод остатков в СКД, чтобы они не суммировались?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Анализируем причину проблемы: механизм агрегации

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

Посмотрим на пример запроса, который часто становится источником ошибок:


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

В данном случае проблема кроется в использовании псевдонимов. Как только мы переименовываем КоличествоКонечныйОстаток в КоличествоОстаток, система компоновки данных может "потерять" автоматическую связь с ролями метаданных. СКД перестает понимать, что это поле является остатком. Если вы создаете отчет не в конструкторе, а программно, то СКДБилдер поможет упростить программное создание СКД и избежать подобных ошибок ручного описания полей.

Шаг 1: Настройка ролей полей в наборе данных

Для того чтобы СКД понимала, как обрабатывать данные, нам необходимо вручную настроить вкладку Роли в конструкторе схемы компоновки данных. Проанализируем ключевые параметры этой настройки:

  1. Тип остатка: Для поля начального остатка (например, КоличествоНачальныйОстаток) необходимо установить значение "Начальный". Для конечного остатка — "Конечный".
  2. Имя: Это критически важный параметр. У пары полей (начальный и конечный остаток по одному ресурсу) должно быть указано одинаковое имя в колонке "Имя" роли. Например, назовем их просто "Количество". Это связывает их в единую сущность для алгоритмов расчета остатков.
  3. Игнорировать значения NULL: Рекомендуется устанавливать этот флаг, чтобы при отсутствии движений в определенном периоде остатки корректно "протягивались" из предыдущих записей.
  4. Связь по измерениям: В настройках роли необходимо указать измерения, в разрезе которых считается остаток (Номенклатура, Склад, Характеристика). Это позволит системе правильно схлопывать итоги, если вы убираете одно из измерений из группировки отчета.

Шаг 2: Правильная работа с псевдонимами (синонимами)

Как мы выяснили, несимметричные синонимы могут сбивать автоматику СКД. Выясним причину: если вы назвали начальный остаток стандартно, а конечный — по-своему, СКД не сможет автоматически сопоставить их. Рассмотрим пример правильного именования в запросе:


ВЫБРАТЬ
    ТоварыНаСкладах.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
    ТоварыНаСкладах.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток

Или, если вы используете свои имена, обязательно пропишите их в ролях так, как указано в Шаге 1. Помните: имена полей в запросе могут быть любыми, но в "Ролях" они должны быть связаны общим идентификатором группы остатков.

Шаг 3: Соединение с ценами и срезами последних

Часто в отчетах по остаткам требуется вывести стоимость. Посмотрим на типичную ошибку соединения с ценами в запросе:


ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&КонецПериода, ТипЦен = &ТипЦен) КАК Цены
ПО ТоварыНаСкладах.Номенклатура = Цены.Номенклатура

Проанализируем ситуацию: если ваш отчет строится по дням за целый месяц, такое соединение подтянет одну и ту же цену (на конец месяца) ко всем строкам отчета. В некоторых случаях, когда требуется оптимизация отчетов с набором данных - объект, разработчики применяют более сложные подходы, иногда используя даже две разных схемы в одном отчете для разделения логики получения данных и их представления.

Рассмотрим правильный подход:

Для получения корректных цен на каждый день лучше использовать Связи наборов данных в СКД. Создадим два набора данных:

В настройках связи укажем: Источник - Набор1, Приемник - Набор2. Свяжем их по полям Номенклатура и Период. В параметрах таблицы цен для СрезПоследних укажем условие использования периода из первого набора. Таким образом, СКД сама выполнит запрос к ценам для каждой даты остатка.

Шаг 4: Настройка ресурсов

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

Если же вы создаете вычисляемое поле, например, СуммаОстатка = КоличествоОстаток * Цена, в выражении ресурса стоит быть внимательным. Иногда требуется указать расчет через конкретные функции агрегации остатков, но в 90% случаев корректно настроенных ролей в базовых полях достаточно для правильной работы вычисляемых ресурсов.

Подведем итог

Для получения корректного последнего значения остатка в СКД мы должны:

  1. Использовать виртуальную таблицу ОстаткиИОбороты (или Остатки, если динамика не нужна).
  2. Обязательно выбирать и начальный, и конечный остатки в запросе, даже если планируем выводить только один из них.
  3. Вручную проконтролировать Роли полей, объединив их общим именем в группе остатков.
  4. Избегать прямого соединения со срезом последних в тексте запроса, если важна точность цен в динамике.

Следуя этим правилам, вы получите отчет, который корректно отображает итоговые остатки на любую дату, не суммируя их между собой.

← На главную