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

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

При разработке отчетов в типовых конфигурациях (например, 1С:Управление торговлей 11, ERP или КА) часто возникает задача разграничения видимости данных: для обычного менеджера необходимо жестко зафиксировать отбор по его подразделению и заказам без возможности редактирования, а руководителю — предоставить доступ к выбору любого сотрудника своего отдела.

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

Анализ типовых ошибок при добавлении отбора

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

  1. Обращение к коллекции элементов формы вместо компоновщика настроек: Попытка вызова метода вроде Элементы.Отборы.Добавить() или Элементы.Отбор.Элементы.Добавить() вызывает исключение времени выполнения, так как Элементы — это коллекция элементов графического интерфейса формы, а не структура данных СКД. Отбор хранится в объекте КомпоновщикНастроек.
  2. Игнорирование пользовательских настроек: Если отбор добавляется только в коллекцию Отчет.КомпоновщикНастроек.Настройки.Отбор, но в схеме компоновки этот отбор вынесен в состав пользовательских настроек, сохраненные настройки пользователя (или типовые механизмы БСП при открытии формы) перезапишут программно установленные значения. В результате на форме поля отбора останутся пустыми или примут сохраненное ранее значение.
  3. Установка режима отображения в значение «Недоступный»: Присвоение свойству РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный полностью скрывает элемент отбора из пользовательского интерфейса. Если разработчик ожидает увидеть заполненное поле на форме, данный режим применять нельзя — поле будет скрыто.

Способ 1. Использование фиксированных настроек компоновщика

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

Посмотрим на пример установки фиксированного отбора при открытии формы отчета на сервере:


&НаСервере
Процедура ПриОткрытииНаСервере()
    
    ТекущийПользователь = ПараметрыСеанса.ТекущийПользователь;
    
    // Проверяем роль пользователя
    Если Не РольДоступна("РуководительПодразделения") Тогда
        
        // Очищаем существующие фиксированные отборы по нужному полю, если они были
        ПолеОтбора = Новый ПолеКомпоновкиДанных("Заказ.Менеджер");
        Индекс = Отчет.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Количество() - 1;
        Пока Индекс >= 0 Цикл
            Элемент = Отчет.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы[Индекс];
            Если Элемент.ЛевоеЗначение = ПолеОтбора Тогда
                Отчет.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Удалить(Элемент);
            КонецЕсли;
            Индекс = Индекс - 1;
        КонецЦикла;
        
        // Добавляем жесткий отбор для обычного менеджера
        ЭлементОтбора = Отчет.КомпоновщикНастроек.ФиксированныеНастройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
        ЭлементОтбора.ЛевоеЗначение  = ПолеОтбора;
        ЭлементОтбора.ВидСравнения   = ВидСравненияКомпоновкиДанных.Равно;
        ЭлементОтбора.ПравоеЗначение = ТекущийПользователь;
        ЭлементОтбора.Использование  = Истина;
        
    КонецЕсли;

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

Способ 2. Работа с пользовательскими настройками компоновщика

Разберем ситуацию, когда отбор должен оставаться видимым на форме отчета, но для менеджера возможность его изменения блокируется, а для руководителя — остается активной.

Для этого необходимо находить и модифицировать элемент непосредственно в коллекции ПользовательскиеНастройки:


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

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

Способ 3. Переопределение отбора в модуле объекта при компоновке результата

Выясним, как гарантировать наложение условий в момент самого формирования отчета, независимо от действий пользователя в диалоговых формах. Для этого используется обработчик ПриКомпоновкеРезультата в модуле объекта отчета.

Посмотрим, как выглядит программная инициализация компоновки с корректировкой настроек:


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

Важное замечание по безопасности: Программное ограничение отборов на уровне конкретного отчета СКД решает только задачу удобства интерфейса. Если требуется гарантированная защита от просмотра чужих данных на уровне базы данных (включая универсальные отчеты, консоли запросов и выгрузки), разграничение доступа в 1С:Управление торговлей необходимо настраивать через типовой механизм RLS (Ограничение прав на уровне записей) и группы доступа.

← На главную