В работе с 1С часто возникает задача ограничить доступ пользователей к данным в отчетах. Например, менеджер должен видеть информацию только по своему складу, а период формирования отчета не должен выходить за рамки текущего месяца. Рассмотрим, как реализовать такие ограничения программно на примере универсального отчета в конфигурации «Управление торговлей 10.3» на обычных формах.
Исходная задача: для пользователей с определенной ролью в отчете «Ведомость по денежным средствам» необходимо принудительно установить отбор по конкретному складу, запретив его изменение. Также нужно установить дату начала отчета по умолчанию как начало текущего месяца и запретить выбор более ранней даты.
Наиболее простой способ решить эту задачу для отчетов, использующих ПостроительОтчета (как большинство отчетов в УТ 10.3), — это добавить код в модуль объекта отчета, который будет выполняться при формировании. Основная логика будет находиться в процедуре СформироватьОтчет.
Разберем по шагам, как это сделать.
Шаг 1. Проверка роли пользователя
Чтобы настройки применялись только для определенных пользователей, необходимо добавить проверку на наличие у текущего пользователя нужной роли. Для этого используется функция РольДоступна(). Вся логика ограничений будет выполняться внутри условия.
// Предположим, роль для менеджера по складу называется "МенеджерПоСкладуОсновной"
Если РольДоступна("МенеджерПоСкладуОсновной") Тогда
// Здесь будет код для установки периода и отбора
КонецЕсли;
Шаг 2. Ограничение начальной даты периода
Чтобы пользователь не мог установить дату начала отчета ранее текущего месяца, мы можем использовать функцию Макс(). Она сравнит дату, установленную пользователем (УниверсальныйОтчет.ДатаНач), с началом текущего месяца (НачалоМесяца(ТекущаяДата())) и выберет наибольшую (то есть самую позднюю) из них. Таким образом, даже если пользователь выберет прошлый год, программа принудительно подставит первое число текущего месяца.
// ... внутри условия проверки роли
УниверсальныйОтчет.ДатаНач = Макс(НачалоМесяца(ТекущаяДата()), УниверсальныйОтчет.ДатаНач);
Шаг 3. Установка принудительного отбора по складу
Это ключевая часть задачи. Нам нужно получить доступ к коллекции отборов построителя отчета, найти или добавить нужный нам отбор по складу и установить его значение.
ПостроительОтчета.Отбор.Найти() вернул Неопределено, значит, такого отбора еще нет, и его нужно создать с помощью метода Добавить().ВидСравнения: устанавливаем строгое равенство — ВидСравнения.Равно.Значение: указываем ссылку на нужный элемент справочника «Склады». Важно: для поиска элемента лучше использовать надежный идентификатор, например, код или УИД, а не наименование, которое может измениться.Использование: устанавливаем в Истина, чтобы отбор был активен.Итоговый код для процедуры СформироватьОтчет
Соберем все шаги в единый фрагмент кода, который нужно вставить в процедуру СформироватьОтчет в модуле объекта вашего отчета.
Процедура СформироватьОтчет(ТабличныйДокумент)
// Проверяем, есть ли у пользователя роль, для которой нужны ограничения
Если РольДоступна("МенеджерПоСкладуОсновной") Тогда
// 1. Устанавливаем ограничение на начальную дату периода
УниверсальныйОтчет.ДатаНач = Макс(НачалоМесяца(ТекущаяДата()), УниверсальныйОтчет.ДатаНач);
// 2. Устанавливаем принудительный отбор по складу
Отбор = УниверсальныйОтчет.ПостроительОтчета.Отбор;
// Ищем элемент отбора по имени поля "Склад"
ЭлементОтбора = Отбор.Найти("Склад");
// Если отбор не найден, добавляем его
Если ЭлементОтбора = Неопределено Тогда
ЭлементОтбора = Отбор.Добавить("Склад");
КонецЕсли;
// Настраиваем параметры отбора
ЭлементОтбора.ВидСравнения = ВидСравнения.Равно;
// Ищем нужный склад по коду. Замените "СКЛ001" на код вашего склада
ЭлементОтбора.Значение = Справочники.Склады.НайтиПоКоду("СКЛ001");
ЭлементОтбора.Использование = Истина;
КонецЕсли;
// Стандартный вызов формирования универсального отчета
УниверсальныйОтчет.СформироватьОтчет(ТабличныйДокумент);
КонецПроцедуры
Этот код решит поставленную задачу: при формировании отчета для пользователя с ролью «МенеджерПоСкладуОсновной» период и отбор будут принудительно скорректированы.
Предложенное решение является рабочим, но его можно улучшить. Кроме того, для более современных конфигураций и глобальных задач существуют более правильные подходы.
Как заблокировать поля на форме отчета?
Вышеописанный код изменяет настройки в момент нажатия кнопки «Сформировать». Однако пользователь все еще может изменить значения в полях на форме. Чтобы полностью заблокировать их, можно в процедуре формы отчета (например, ПриОткрытии) установить свойство Доступность для нужных элементов в Ложь.
Процедура ПриОткрытии()
Если РольДоступна("МенеджерПоСкладуОсновной") Тогда
// Блокируем поле для выбора начальной даты
ЭлементыФормы.УниверсальныйОтчетДатаНач.Доступность = Ложь;
// Если отбор по складу выведен на форму, его тоже можно заблокировать
// Имя элемента может отличаться, нужно смотреть в конфигураторе
// ЭлементыФормы.ПолеОтбораСклад.Доступность = Ложь;
КонецЕсли;
КонецПроцедуры
Система компоновки данных (СКД)
Для отчетов, построенных на СКД (стандарт для современных конфигураций), задача решается элегантнее. Можно сделать элемент отбора недоступным для пользователя прямо в настройках компоновщика.
// Пример для отчета на СКД
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
ЭлементОтбора = Настройки.Отбор.Элементы.Найти("Склад");
// ... установка значения ...
// Делаем элемент невидимым и недоступным для пользователя
ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;
Наиболее надежный метод — ограничение прав на уровне записей (RLS)
Если требуется, чтобы пользователь нигде в системе не видел данные по чужим складам (ни в отчетах, ни в списках документов), то правильнее всего использовать механизм RLS (Row-Level Security).
Этот подход является наиболее безопасным и комплексным, так как он не зависит от кода конкретного отчета и применяется ко всей системе целиком.