При разработке управленческих отчетов в системе 1С:Предприятие 8.3 часто возникает задача классификации данных по временным интервалам. Типичный пример — отчет «Aging», в котором количество заказов или объем продаж нужно разбить на колонки: «за последние 30 дней», «от 30 до 60 дней» и так далее. В процессе реализации таких отчетов программисты часто сталкиваются с двумя проблемами: некорректным группировкам в Системе компоновки данных (СКД) и «размножением» (задвоением) остатков при соединении таблиц оборотов и остатков. В этой статье мы подробно разберем, как правильно составить запрос, настроить ресурсы и вытащить даже скрытые дополнительные реквизиты объектов.
Для того чтобы разделить данные (например, количество заказанного товара) по разным колонкам в зависимости от даты, мы используем конструкцию ВЫБОР. Рассмотрим ситуацию, когда нам нужно получить данные за интервалы в 30, 60 и 90 дней относительно текущей даты или даты окончания отчета.
Проанализируем пример кода, который позволяет выделить периоды в запросе:
ВЫБРАТЬ
ЗаказыКлиентов.Номенклатура КАК Номенклатура,
ВЫБОР
КОГДА ЗаказыКлиентов.Период >= ДОБАВИТЬКДАТЕ(&ДатаКон, ДЕНЬ, -30)
ТОГДА ЗаказыКлиентов.Количество
ИНАЧЕ 0
КОНЕЦ КАК КоличествоЗа30Дней,
ВЫБОР
КОГДА ЗаказыКлиентов.Период < ДОБАВИТЬКДАТЕ(&ДатаКон, ДЕНЬ, -30)
И ЗаказыКлиентов.Период >= ДОБАВИТЬКДАТЕ(&ДатаКон, ДЕНЬ, -60)
ТОГДА ЗаказыКлиентов.Количество
ИНАЧЕ 0
КОНЕЦ КАК КоличествоЗа60Дней,
ЗаказыКлиентов.Регистратор КАК Регистратор
ИЗ
РегистрНакопления.ЗаказыКлиентов КАК ЗаказыКлиентов
ГДЕ
ЗаказыКлиентов.Период МЕЖДУ &ДатаНач И &ДатаКон
Важный нюанс: Обратите внимание на функцию ДОБАВИТЬКДАТЕ. Мы используем отрицательное число дней, чтобы «отшагнуть» назад от даты окончания периода. Это позволяет сделать отчет динамическим: данные всегда будут актуальны относительно выбранных параметров.
После того как мы подготовили поля в запросе, нам нужно правильно отобразить их в отчете. Рассмотрим два подхода к проектированию структуры в конструкторе СКД:
КоличествоЗа30Дней, КоличествоЗа60Дней и т.д. в список выбранных полей. В этом случае для каждого интервала будет своя жестко заданная колонка.Интервал, которое принимает строковые значения ("30 дней", "60 дней"). Затем в настройках СКД на вкладке «Настройки» мы создаем таблицу, где в строках будет Номенклатура, а в колонках — поле Интервал. Это сделает отчет более гибким.Пример формирования поля интервала в запросе:
ВЫБОР
КОГДА ДОБАВИТЬКДАТЕ(&ДатаНач, ДЕНЬ, 30) < ЗаказыКлиентов.Период ТОГДА "0-30"
КОГДА ДОБАВИТЬКДАТЕ(&ДатаНач, ДЕНЬ, 60) < ЗаказыКлиентов.Период ТОГДА "31-60"
ИНАЧЕ "Свыше 60"
КОНЕЦ КАК ПериодЗаказа
Выясним причину, по которой при соединении остатков товаров и таблицы заказов цифры в колонке «В наличии» начинают расти в геометрической прогрессии. Это происходит из-за того, что к одной строке таблицы ТоварыНаСкладах.Остатки присоединяется несколько строк из таблицы ЗаказыКлиентов. При суммировании в СКД значение остатка прибавляется столько раз, сколько заказов было у этой номенклатуры.
Рассмотрим два способа исправления ситуации:
Способ 1. Использование функции Максимум в ресурсах.
На вкладке «Ресурсы» для поля ВНаличииОстаток вместо стандартного СУММА(ВНаличииОстаток) пропишите МАКСИМУМ(ВНаличииОстаток). Это простейший «костыль», который заставит систему брать только одно значение остатка для группировки. Однако помните, что это сработает корректно только в том случае, если вы не суммируете остатки по разным складам или характеристикам в одной строке.
Способ 2. Настройка ролей полей (правильный метод).
Разберем по шагам, как это сделать в СКД:
ВНаличииОстаток).После такой настройки СКД поймет, что это поле не является простым числом-оборотом, и применит специфические алгоритмы агрегации, предотвращая суммирование при соединениях.
Часто данные, приходящие с сайта, записываются в так называемые «Дополнительные реквизиты». На форме документа они могут быть не видны, и обращение к ним через точку (ЗаказКлиента.НомерЗаказаНаСайте) выдаст ошибку, так как это не реальный реквизит, а запись в табличной части или регистре.
Проанализируем ситуацию: в конфигурациях на базе БСП (УТ 11, ERP) доп. реквизиты хранятся в табличной части ДополнительныеРеквизиты самого объекта. Чтобы вытащить конкретное значение по имени свойства, используйте следующий запрос:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка,
ДопРеквизиты.Значение КАК НомерЗаказаНаСайте
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказКлиента.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО Реализация.ЗаказКлиента = ДопРеквизиты.Ссылка
И ДопРеквизиты.Свойство.Имя = "НомерЗаказаНаСайте"
Обратите внимание: Мы фильтруем табличную часть прямо в условии соединения ПО. Если использовать ГДЕ, то документы без этого реквизита просто исчезнут из отчета. Также рекомендуется использовать Свойство.Имя (уникальный идентификатор разработчика), а не Свойство.Наименование, так как пользователь может переименовать свойство в интерфейсе, что приведет к поломке отчета.
Создание сложных отчетов в СКД требует понимания механики работы виртуальных таблиц. Мы выяснили, что для классификации по дням лучше всего подходит конструкция ВЫБОР в связке с параметрами. Для корректной работы с остатками необходимо уделять внимание ролям полей или использовать объединение таблиц вместо соединений. А при работе с внешними данными (из интернет-магазинов) всегда проверяйте табличные части дополнительных реквизитов — именно там часто скрыта самая важная информация.