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

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

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

Рассмотрим, с какой проблемой столкнулся разработчик и какими способами можно построить логику отбора в СКД.

Суть проблемы и разбор исходного запроса

Изначально в коде отчета пытались установить параметр запроса ОтветственныйМенеджер только для обычных сотрудников, а в случае проверки роли Администратор просто отключать или переопределять его:


Если НЕ РольДоступна("Администратор") Тогда
    ОтветственныйМенеджер = ПараметрыСеанса.ТекущийПользователь.Ссылка;
    Запрос.УстановитьПараметр("ОтветственныйМенеджер", ОтветственныйМенеджер);
Иначе
    // Как быть здесь, если условие в секции ГДЕ жестко прописано?
КонецЕсли;

Сам запрос выборки данных выглядел следующим образом:


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

Если условие ПродажиОбороты.Ответственный = &ОтветственныйМенеджер прописано в запросе жестко, то для администратора параметр все равно придется передавать, и выборка будет пустой или ограниченной только одним пользователем.

Решение 1. Использование дополнительного булева флага

Наиболее простой вариант обхода жесткого условия — добавить в запрос параметр-флаг (например, &ПоВсем или &НеОтбиратьПоМенеджеру), который управляет вычислением логического выражения.

Разберем по шагам, как изменить секцию ГДЕ в тексте запроса:


ГДЕ
    ПродажиОбороты.Документ.Организация <> &Брак
    И (&ПоВсем ИЛИ ПродажиОбороты.Ответственный = &ОтветственныйМенеджер)

Далее в программном коде перед компоновкой отчета мы передаем значения параметров в зависимости от роли пользователя:


Если РольДоступна("Администратор") Тогда
    Запрос.УстановитьПараметр("ПоВсем", Истина);
    Запрос.УстановитьПараметр("ОтветственныйМенеджер", Справочники.Пользователи.ПустаяСсылка());
Иначе
    Запрос.УстановитьПараметр("ПоВсем", Ложь);
    Запрос.УстановитьПараметр("ОтветственныйМенеджер", ПараметрыСеанса.ТекущийПользователь);
КонецЕсли;

Важное примечание по производительности: Использование конструкции (&ПоВсем ИЛИ Поле = &Значение) удобно в реализации, но для очень больших объемов данных на стороне СУБД такое условие может снизить эффективность использования индексов. Если база данных содержит миллионы записей, рекомендуется использовать механизмы СКД.

Решение 2. Использование необязательных условий языка СКД (фигурные скобки)

Система компоновки данных 1С поддерживает специальный синтаксис для необязательных условий. Если обернуть условие в фигурные скобки {}, СКД сама удалит конструкцию из итогового SQL-запроса, если параметр не задействован.

Пример синтаксиса в тексте запроса СКД:


ВЫБРАТЬ
    ПродажиОбороты.Организация КАК Организация,
    ПродажиОбороты.Ответственный КАК Ответственный,
    ПродажиОбороты.СуммаОборот КАК Сумма
ИЗ
    РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
{ГДЕ
    ПродажиОбороты.Ответственный = &ОтветственныйМенеджер}

В этом случае управление доступностью параметра происходит на программном уровне через выключение свойства Использование у параметра компоновщика настроек:


ПараметрОтветственный = КомпоновщикНастроек.Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("ОтветственныйМенеджер"));

Если НЕ РольДоступна("Администратор") Тогда
    ПараметрОтветственный.Значение = ПараметрыСеанса.ТекущийПользователь;
    ПараметрОтветственный.Использование = Истина;
Иначе
    ПараметрОтветственный.Использование = Ложь;
КонецЕсли;

Решение 3. Стандартные отборы компоновщика настроек (Рекомендуемое)

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

  1. В запросе СКД выбираются все поля без жестких условий по Ответственный.
  2. В настройках СКД на вкладке Отбор добавляется поле Ответственный.
  3. В обработчике модуля объекта отчета ПриКомпоновкеРезультата анализируются права текущего пользователя и программно настраивается доступность элемента отбора:

Процедура ПриКомпоновкеРезультата(ТабличныйДокумент, СтандартнаяОбработка)
    
    Если НЕ РольДоступна("Администратор") Тогда
        // Находим или добавляем элемент отбора по ответственному
        ЭлементОтбора = КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ответственный");
        ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
        ЭлементОтбора.ПравоеЗначение = ПараметрыСеанса.ТекущийПользователь;
        ЭлементОтбора.Использование = Истина;
        ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновки.Недоступный;
    КонецЕсли;

КонецПроцедуры

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

← На главную