При разработке отчетов по себестоимости в конфигурациях на базе 1С:УТ 11, ERP или КА 2 программисты часто сталкиваются с проблемой некорректного вывода начальных и конечных остатков при детализации по периодам (например, по месяцам). Типичная ситуация: если в периоде были движения, остатки «пропадают», а если движений не было — данные отображаются неверно или строка вовсе отсутствует. Разберем подробно, почему так происходит и как построить идеальный отчет в Системе компоновки данных (СКД).
В попытках получить данные, разработчики часто прибегают к объединению нескольких запросов через оператор ОБЪЕДИНИТЬ ВСЕ (UNION ALL), разделяя получение оборотов и получение остатков. Проанализируем, почему этот метод в СКД работает некорректно. Система компоновки данных — это не просто инструмент выполнения SQL-запросов, это мощный движок, который сам управляет расчетом итогов по временным осям. Когда мы принудительно разделяем остатки и обороты в коде запроса, мы лишаем СКД возможности использовать встроенный механизм «сшивания» итогов по периодам.
Если в одном запросе (выборке) для конкретного периода (например, Январь) у вас заполнены только обороты, а остатки стоят как NULL, а в другом запросе — наоборот, СКД при группировке может вывести их разными строками или некорректно агрегировать, если не настроены роли полей. Рассмотрим правильный подход.
Для начала откажемся от избыточных объединений. Нам достаточно одного обращения к виртуальной таблице ОстаткиИОбороты. Важно правильно выбрать периодичность. В нашем случае это Авто или Месяц.
Рассмотрим пример правильного запроса к регистру СебестоимостьТоваров:
ВЫБРАТЬ
СебестоимостьТоваровОстаткиИОбороты.АналитикаУчетаНоменклатуры.Номенклатура КАК Номенклатура,
СебестоимостьТоваровОстаткиИОбороты.ПериодМесяц КАК ПериодМесяц,
СебестоимостьТоваровОстаткиИОбороты.КоличествоНачальныйОстаток КАК КоличествоНачальныйОстаток,
СебестоимостьТоваровОстаткиИОбороты.КоличествоПриход КАК КоличествоПриход,
СебестоимостьТоваровОстаткиИОбороты.КоличествоРасход КАК КоличествоРасход,
СебестоимостьТоваровОстаткиИОбороты.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстаток,
СебестоимостьТоваровОстаткиИОбороты.СтоимостьУпрНачальныйОстаток + СебестоимостьТоваровОстаткиИОбороты.ДопРасходыУпрНачальныйОстаток КАК СтоимостьНачальныйОстаток,
СебестоимостьТоваровОстаткиИОбороты.СтоимостьУпрПриход + СебестоимостьТоваровОстаткиИОбороты.ДопРасходыУпрПриход КАК СтоимостьПриход,
СебестоимостьТоваровОстаткиИОбороты.СтоимостьУпрРасход + СебестоимостьТоваровОстаткиИОбороты.ДопРасходыУпрРасход КАК СтоимостьРасход,
СебестоимостьТоваровОстаткиИОбороты.СтоимостьУпрКонечныйОстаток + СебестоимостьТоваровОстаткиИОбороты.ДопРасходыУпрКонечныйОстаток КАК СтоимостьКонечныйОстаток
ИЗ
РегистрНакопления.СебестоимостьТоваров.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Месяц, , ) КАК СебестоимостьТоваровОстаткиИОбороты
Обратите внимание: мы суммируем составляющие стоимости (основную стоимость и дополнительные расходы) непосредственно в запросе. Это необходимо, так как в УТ 11 себестоимость может складываться из различных компонентов, хранящихся в разных ресурсах регистра.
Это самый важный этап. Без настройки ролей СКД не поймет, что КоличествоНачальныйОстаток — это не просто число, которое нужно складывать, а значение, которое должно браться на начало периода. Перейдем на закладку «Наборы данных» и выполним следующие действия:
ПериодМесяц. В колонке «Роль» нажмем на кнопку выбора. Установим флаг «Период», укажем тип периода «Дополнительный» (так как это месяц) и порядковый номер (например, 1).КоличествоНачальныйОстаток, СтоимостьНачальныйОстаток) в роли укажим тип «Остаток». В поле «Имя» выберем соответствующее имя (например, "Количество"), а в поле «Тип остатка» — «Начальный». Обязательно выберем связь с полем периода — ПериодМесяц.Благодаря этим настройкам, СКД применит специфический алгоритм: начальный остаток для группировки «Февраль» будет взят как конечный остаток «Января», даже если в самом запросе данных за февраль нет.
Выясним причину, по которой периоды без движений могут пропадать из отчета. Виртуальная таблица возвращает только те периоды, в которых была хоть какая-то активность. Чтобы увидеть остатки на конец каждого месяца в интервале (даже если продаж и закупок не было), нужно использовать механизм дополнения периодов.
Проанализируем ситуацию: в настройках СКД на уровне группировки ПериодМесяц нужно зайти в «Параметры редактирования» или «Настройки поля» и установить «Тип дополнения» — «Месяц». Также необходимо указать границы дополнения (начало и конец периода отчета). После этого СКД автоматически добавит строки для недостающих месяцев, а роль «Остаток», настроенная на предыдущем шаге, позволит корректно «протянуть» суммы остатков через эти пустые строки.
При работе с этим регистром важно помнить о нескольких технических нюансах:
РазделУчета. Если в отчете не наложить фильтр по конкретному разделу (например, «Товары на складах»), данные могут задвоиться, так как один и тот же товар может числиться и в разделе «Товары на складах», и в разделе «Товары в пути».КлючиАналитикиУчетаНоменклатуры. Однако СКД через разыменование полей (точка от Аналитики к Номенклатуре) делает это достаточно эффективно.Перейдем на закладку «Ресурсы». Для всех полей остатков и оборотов нужно указать выражение СУММА(ИмяПоля). Не бойтесь использовать сумму для остатков — благодаря настроенным ролям полей на Шаге 2, СКД не будет тупо складывать остаток января с остатком февраля в общих итогах. Вместо этого система возьмет значение на начало самого первого периода и на конец самого последнего.
Рассмотрим пример выражения для ресурсов, чтобы избежать пустых ячеек:
ЕСТЬNULL(СУММА(СтоимостьПриход), 0)
Использование ЕСТЬNULL гарантирует, что в печатной форме отчета вместо пустой ячейки будет стоять аккуратный ноль, что значительно повышает читаемость отчета для конечного пользователя (бухгалтера или финансового директора).
Подведем итог: секрет корректного отчета по остаткам в СКД кроется не в сложности SQL-запроса, а в правильном описании метаданных полей (Ролей) и использовании механизмов дополнения периодов. Проанализированный нами метод является стандартным и наиболее надежным для платформы 1С 8.3.