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

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

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

Почему СКД суммирует остатки в общих итогах

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


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

Выясним причину некорректного поведения при таком подходе:

  1. Разрыв связи с виртуальной таблицей: Конструкции ПОЛНОЕ СОЕДИНЕНИЕ и функции ЕСТЬNULL для полей периода и номенклатуры сбивают встроенные механизмы СКД. Платформа перестает распознавать поле периода как координату на временной шкале регистра остатков.
  2. Отсутствие парного начального остатка: Механизм расчета остатков СКД требует одновременного наличия как начального, так и конечного остатка, объединенных общей группой в ролях полей.
  3. Стандартная агрегация ресурса: Если на вкладке «Ресурсы» поле конечного остатка рассчитывается стандартным выражением Сумма(КонОст), СКД суммирует значения во всех без исключения группировках и общих итогах.

Способ 1. Разделение запроса на два набора данных (Рекомендуемый)

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

Разберем по шагам реализацию этого подхода:

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

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

Если требуется оставить один общий запрос, необходимо явно указать роли полей на вкладке «Наборы данных».

Выполним следующие обязательные настройки:

  1. В запрос обязательно добавляем поле начального остатка: Остатки.ВНаличииНачальныйОстаток КАК НачОст.
  2. Для поля периода (например, ПериодМесяц) в колонке «Роль» устанавливаем флажок Период и задаем порядковый номер 1.
  3. Для поля Номенклатура в роли отмечаем флажок Измерение.
  4. Для полей остатков настраиваем связь:
    • Для НачОст в роли указываем группу (свойство Имя, например, ВНаличии), а в типе выбираем НачальныйОстаток.
    • Для КонОст указываем то же самое имя группы ВНаличии, а тип устанавливаем в КонечныйОстаток.

Важно: Имя группы остатков у начального и конечного остатка должно строго совпадать. Только при выполнении этого условия платформа рассчитывает итоги как срез на временной границе, а не как сумму.

Способ 3. Вычисление итогов через выражения ресурсов

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

Рассмотрим пример настройки ресурса КонОст:

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

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

Нюансы работы с периодами без движений

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

← На главную