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

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

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

Почему возникают дубли и неверные остатки

Рассмотрим ситуацию: когда мы указываем в параметрах виртуальной таблицы ХозрасчетныйОстаткиИОбороты периодичность «Регистратор», система извлекает записи о движениях, привязанные к каждому конкретному документу. Если в запросе мы используем поле Регистратор, СКД выводит каждую операцию отдельной строкой. Если при этом попытаться просто просуммировать поле «Конечный остаток» в группировке по номенклатуре, мы получим сумму остатков после каждой операции, что фактически является бессмысленным числом, а не реальным остатком на складе.

Вторая критическая ошибка — использование условия ГДЕ для фильтрации типов документов. Проанализируем пример кода с типичной ошибкой:


ГДЕ
    ХозрасчетныйОстаткиИОбороты.Счет.Код = "41.01"
    И ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг)

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

Способ 1. Использование ролей полей в СКД

Для того чтобы СКД понимала, как правильно вычислять итоги по остаткам в присутствии детальных записей (регистраторов), необходимо правильно настроить Роли на закладке «Наборы данных». Это «родной» механизм системы компоновки данных для решения подобных задач.

  1. Перейдем на закладку Наборы данных в схеме компоновки.
  2. Найдем поля остатков (например, КоличествоКонечныйОстаток).
  3. В колонке Роль нажмем на кнопку редактирования.
  4. Укажем тип поля — Остаток.
  5. Укажем Имя (например, Количество). Это имя должно быть одинаковым для начального и конечного остатка одного и того же ресурса.
  6. В поле Бухгалтерское поле выберем соответствующее поле счета (например, Счет), а в поле Поле периода укажем ПериодСекунда или Регистратор.

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

Способ 2. Вычисляемые поля и обороты через ВЫБОР

Если нам нужны реальные общие остатки, но обороты мы хотим видеть только по конкретному документу, лучше отказаться от фильтра ГДЕ в тексте запроса. Вместо этого мы выберем все данные, а фильтрацию сделаем на уровне ресурсов или вычисляемых полей.

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


ВЫБРАТЬ
    ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Номенклатура,
    ХозрасчетныйОстаткиИОбороты.КоличествоКонечныйОстаток КАК Остаток,
    ВЫБОР 
        КОГДА ХозрасчетныйОстаткиИОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг 
        ТОГДА ХозрасчетныйОстаткиИОбороты.КоличествоОборотКт 
        ИНАЧЕ 0 
    КОНЕЦ КАК Продано
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , Счет = &Счет41, , ) КАК ХозрасчетныйОстаткиИОбороты

В этом случае в поле Продано попадут только данные из реализаций, но при этом виртуальная таблица корректно посчитает общий остаток по счету, так как в выборку попали все движения (просто для «не-реализаций» в колонке «Продано» будет ноль).

Оптимизация: работа со счетами и субконто

Выясним причину, по которой опытные разработчики критикуют обращение к Счет.Код. Когда мы пишем Счет.Код = "41.01", платформа выполняет дополнительное соединение с таблицей плана счетов, что замедляет запрос. Кроме того, если код счета изменится в конфигураторе, ваш отчет сломается.

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

РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(..., Счет В ИЕРАРХИИ (&СписокСчетов), ...)

Также важно помнить о типизации Субконто. Поскольку Субконто1 имеет составной тип, обращение к его реквизитам (например, Субконто1.Артикул) крайне непроизводительно. Рассмотрим, как ускорить запрос с помощью оператора ВЫРАЗИТЬ:


ВЫБРАТЬ
    ВЫРАЗИТЬ(ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Справочник.Номенклатура).Артикул КАК Артикул,
    ...

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

Расчет «Требуется заказать» через вычисляемые поля

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

Создадим вычисляемое поле ТребуетсяЗаказать с выражением:

(Продано / КоличествоДнейПродажи) * 30 - Остаток

А на закладке Ресурсы укажем расчет этого поля как:

СУММА(Продано) / СУММА(КоличествоДнейПродажи) * 30 - СУММА(Остаток)

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

← На главную