При разработке отчетов на системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда необходимо вывести одновременно и конечные остатки товаров, и детальные данные по конкретным документам (например, только продажи по документам «Реализация товаров и услуг»). Если просто выбрать периодичность «Регистратор» в виртуальной таблице, отчет начинает «дублировать» строки, а итоговые остатки рассчитываются неверно. Разберем подробно, почему это происходит и как правильно настроить такой отчет.
Рассмотрим ситуацию: когда мы указываем в параметрах виртуальной таблицы ХозрасчетныйОстаткиИОбороты периодичность «Регистратор», система извлекает записи о движениях, привязанные к каждому конкретному документу. Если в запросе мы используем поле Регистратор, СКД выводит каждую операцию отдельной строкой. Если при этом попытаться просто просуммировать поле «Конечный остаток» в группировке по номенклатуре, мы получим сумму остатков после каждой операции, что фактически является бессмысленным числом, а не реальным остатком на складе.
Вторая критическая ошибка — использование условия ГДЕ для фильтрации типов документов. Проанализируем пример кода с типичной ошибкой:
ГДЕ
ХозрасчетныйОстаткиИОбороты.Счет.Код = "41.01"
И ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг)
Когда вы накладываете жесткий фильтр через ГДЕ на регистратор, виртуальная таблица отсекает все прочие движения (поступления, перемещения, корректировки). Поскольку остатки в виртуальных таблицах рассчитываются на основании оборотов, исключение «лишних» документов приводит к тому, что поле КоличествоКонечныйОстаток начинает показывать остаток, сформированный только выбранными документами, что в корне неверно для бухгалтерского учета.
Для того чтобы СКД понимала, как правильно вычислять итоги по остаткам в присутствии детальных записей (регистраторов), необходимо правильно настроить Роли на закладке «Наборы данных». Это «родной» механизм системы компоновки данных для решения подобных задач.
КоличествоКонечныйОстаток).Количество). Это имя должно быть одинаковым для начального и конечного остатка одного и того же ресурса.Счет), а в поле Поле периода укажем ПериодСекунда или Регистратор.При такой настройке СКД не будет суммировать остатки строк. Вместо этого для итогов по группировке она возьмет значение остатка из самой «поздней» записи в периоде, что и даст нам верный конечный остаток.
Если нам нужны реальные общие остатки, но обороты мы хотим видеть только по конкретному документу, лучше отказаться от фильтра ГДЕ в тексте запроса. Вместо этого мы выберем все данные, а фильтрацию сделаем на уровне ресурсов или вычисляемых полей.
Проанализируем пример запроса, который позволит избежать искажения данных:
ВЫБРАТЬ
ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Номенклатура,
ХозрасчетныйОстаткиИОбороты.КоличествоКонечныйОстаток КАК Остаток,
ВЫБОР
КОГДА ХозрасчетныйОстаткиИОбороты.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
ТОГДА ХозрасчетныйОстаткиИОбороты.КоличествоОборотКт
ИНАЧЕ 0
КОНЕЦ КАК Продано
ИЗ
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, , Счет = &Счет41, , ) КАК ХозрасчетныйОстаткиИОбороты
В этом случае в поле Продано попадут только данные из реализаций, но при этом виртуальная таблица корректно посчитает общий остаток по счету, так как в выборку попали все движения (просто для «не-реализаций» в колонке «Продано» будет ноль).
Выясним причину, по которой опытные разработчики критикуют обращение к Счет.Код. Когда мы пишем Счет.Код = "41.01", платформа выполняет дополнительное соединение с таблицей плана счетов, что замедляет запрос. Кроме того, если код счета изменится в конфигураторе, ваш отчет сломается.
Правильный подход: передавать ссылку на счет через параметры. В параметрах виртуальной таблицы это выглядит так:
РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(..., Счет В ИЕРАРХИИ (&СписокСчетов), ...)
Также важно помнить о типизации Субконто. Поскольку Субконто1 имеет составной тип, обращение к его реквизитам (например, Субконто1.Артикул) крайне непроизводительно. Рассмотрим, как ускорить запрос с помощью оператора ВЫРАЗИТЬ:
ВЫБРАТЬ
ВЫРАЗИТЬ(ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Справочник.Номенклатура).Артикул КАК Артикул,
...
Это заставляет SQL-сервер обращаться к конкретной таблице справочника напрямую, минуя проверку всех возможных типов документов и справочников, входящих в состав субконто.
В тексте запроса автора присутствовала формула расчета потребности. Рекомендуется выносить такие расчеты на закладку «Вычисляемые поля» СКД. Проанализируем ситуацию: если мы считаем «Дней запаса» прямо в запросе, мы можем столкнуться с делением на ноль или неверным расчетом в общих итогах (СКД просто сложит результаты строк вместо того, чтобы применить формулу к итоговым суммам).
Создадим вычисляемое поле ТребуетсяЗаказать с выражением:
(Продано / КоличествоДнейПродажи) * 30 - Остаток
А на закладке Ресурсы укажем расчет этого поля как:
СУММА(Продано) / СУММА(КоличествоДнейПродажи) * 30 - СУММА(Остаток)
Такой подход гарантирует, что на уровне итогов по складу или организации вы получите математически верный результат, а не сумму разрозненных значений по регистраторам.