Часто возникает задача — сделать так, чтобы отчет, например, по продажам, при открытии менеджером сразу показывал данные только по нему — для этого есть разграничение видимости документов для менеджера. Основная сложность в том, что в отчете данные привязаны к элементу справочника «Сотрудники», а в систему пользователь заходит под учетной записью «Пользователь ИБ». Необходимо установить между ними связь и применить фильтр автоматически.
В этой статье мы разберем два основных подхода к решению этой задачи: декларативный (через настройки самой схемы компоновки данных) и программный (с помощью кода в модуле отчета), а также коснемся вопроса создания разных вариантов отчета для разных ролей пользователей.
Этот метод является наиболее правильным и предпочтительным, так как он использует штатные механизмы СКД, не требует написания кода и делает отчет более гибким.
Для начала нужно убедиться, что в вашей конфигурации есть механизм, связывающий пользователя информационной базы (ИБ) с соответствующим ему сотрудником. Обычно это реализуется через специальный регистр сведений, например, СоответствиеПользователейИСотрудников, где хранятся пары «Пользователь» — «Сотрудник». В типовых конфигурациях на базе Библиотеки стандартных подсистем (БСП) такая связь, как правило, уже есть.
Откроем схему компоновки данных и в тексте основного запроса добавим левое соединение с этим регистром сведений — для этого подойдёт консоль разработчика для СКД и запросов. Предположим, в нашем отчете есть поле Контрагент.ОтветственныйМенеджер (тип «Справочник.Сотрудники»), по которому нужно фильтровать. Тогда соединение будет выглядеть так:
...
ИЗ
РегистрНакопления.Продажи.Обороты(...) КАК ПродажиОбороты
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СоответствиеПользователейИСотрудников КАК СоответствиеПользователей
ПО ПродажиОбороты.Контрагент.ОтветственныйМенеджер = СоответствиеПользователей.Сотрудник
...
Теперь добавим условие в секцию ГДЕ нашего запроса, которое будет использовать нового участника. Создадим для этого параметр, например, &ТекущийПользователь.
...
ГДЕ
СоответствиеПользователей.Пользователь = &ТекущийПользователь
...
Это условие отберет только те записи о продажах, где ответственный менеджер связан с текущим пользователем ИБ — поможет фильтрация данных по ответственному менеджеру.
Перейдем на вкладку «Параметры» в конструкторе схемы. Для нашего нового параметра ТекущийПользователь нужно указать, откуда брать значение. В колонке «Выражение» можно прописать функцию для получения текущего пользователя. Если ваша конфигурация использует БСП, это может быть выражение &Пользователи.ТекущийПользователь. В более простых случаях можно использовать параметр сеанса &ПараметрыСеанса.ТекущийПользователь.
Также важно убедиться, что у этого параметра снят флажок «Включать в пользовательские настройки», чтобы пользователь не мог его изменить вручную.
Этот способ позволяет решить задачу без единой строчки кода в модуле отчета, что упрощает дальнейшую поддержку и развитие.
Этот метод применяется, когда логика отбора сложная, или если нужно динамически менять настройки перед формированием отчета — для этого подойдёт автоматическая установка отборов в отчетах. Именно к этому решению пришел автор в теме на форуме.
Вся работа будет происходить в обработчике события ПриКомпоновкеРезультата в модуле объекта отчета.
Посмотрим на пошаговый алгоритм:
Сначала нам нужно выполнить небольшой запрос, чтобы по текущему пользователю ИБ найти связанный с ним элемент справочника «Сотрудники». Для этого, как и в первом способе, нам понадобится регистр сведений, хранящий эту связь.
Это критически важный шаг. Частая ошибка — пытаться изменить настройки по умолчанию (СхемаКомпоновкиДанных.НастройкиПоУмолчанию). Это не сработает, так как пользователь уже мог изменить их в форме отчета. Правильно — получить актуальные настройки из объекта КомпоновщикНастроек.
В полученном объекте настроек находим нужный нам элемент отбора (например, по полю «Ответственный менеджер») и устанавливаем его правое значение равным сотруднику, которого мы нашли на первом шаге — поможет инструмент для программной настройки отборов.
После всех манипуляций необходимо загрузить измененный объект настроек обратно в компоновщик, чтобы отчет сформировался уже с ними.
Проанализируем итоговый рабочий код:
В модуле объекта отчета создаем процедуру:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Шаг 1: Определяем сотрудника для текущего пользователя
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| СотрудникиПользователя.Сотрудник КАК Сотрудник
|ИЗ
| РегистрСведений.СотрудникиПользователя КАК СотрудникиПользователя
|ГДЕ
| СотрудникиПользователя.Пользователь = &Пользователь";
// Используем стандартную функцию БСП для получения текущего пользователя
Запрос.УстановитьПараметр("Пользователь", Пользователи.ТекущийПользователь());
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Сотрудник = Неопределено;
Если Выборка.Следующий() Тогда
Сотрудник = Выборка.Сотрудник;
КонецЕсли;
// Если сотрудник не найден, выходим, чтобы не сломать отчет
Если Сотрудник = Неопределено Тогда
Возврат;
КонецЕсли;
// Шаг 2: Получаем ТЕКУЩИЕ настройки отчета
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// Шаг 3: Находим нужный элемент отбора и устанавливаем значение
// ВАЖНО: Поиск по индексу (Элементы[2]), как в примере с форума, ненадежен,
// так как порядок элементов может измениться.
// Лучше найти элемент по имени поля (идентификатору).
// Предположим, наш отбор добавлен в СКД по полю "Контрагент.ОтветственныйМенеджер"
// Найдем нужный элемент отбора. Создадим, если его нет.
ЭлементОтбора = Настройки.Отбор.Элементы.Найти(Новый ПолеКомпоновкиДанных("Контрагент.ОтветственныйМенеджер"));
Если ЭлементОтбора = Неопределено Тогда
ЭлементОтбора = Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Контрагент.ОтветственныйМенеджер");
КонецЕсли;
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Сотрудник;
// Шаг 4: Загружаем измененные настройки обратно в компоновщик
КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
КонецПроцедуры
Этот код надежно установит отбор по текущему пользователю непосредственно перед формированием отчета.
Автор вопроса также хотел, чтобы у «главных менеджеров» отчет был немного другим (например, с дополнительным полем). Это классическая задача для механизма вариантов отчета в СКД.
ПриСозданииНаСервере, можно проверить роль текущего пользователя и установить нужный вариант по умолчанию через свойство Отчет.КомпоновщикНастроек.ТекущийВариант.Использование вариантов — это штатный и самый удобный способ предоставления разного вида одного и того же отчета для разных ролей без необходимости создавать несколько отдельных отчетов.