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

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

В работе с 1С часто возникает задача ограничить доступ пользователей к данным в отчетах. Например, менеджер должен видеть информацию только по своему складу, а период формирования отчета не должен выходить за рамки текущего месяца. Рассмотрим, как реализовать такие ограничения программно на примере универсального отчета в конфигурации «Управление торговлей 10.3» на обычных формах.

Исходная задача: для пользователей с определенной ролью в отчете «Ведомость по денежным средствам» необходимо принудительно установить отбор по конкретному складу, запретив его изменение. Также нужно установить дату начала отчета по умолчанию как начало текущего месяца и запретить выбор более ранней даты.

Решение: Программное изменение настроек отчета

Наиболее простой способ решить эту задачу для отчетов, использующих ПостроительОтчета (как большинство отчетов в УТ 10.3), — это добавить код в модуль объекта отчета, который будет выполняться при формировании. Основная логика будет находиться в процедуре СформироватьОтчет.

Разберем по шагам, как это сделать.

Шаг 1. Проверка роли пользователя

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


// Предположим, роль для менеджера по складу называется "МенеджерПоСкладуОсновной"
Если РольДоступна("МенеджерПоСкладуОсновной") Тогда
    // Здесь будет код для установки периода и отбора
КонецЕсли;

Шаг 2. Ограничение начальной даты периода

Чтобы пользователь не мог установить дату начала отчета ранее текущего месяца, мы можем использовать функцию Макс(). Она сравнит дату, установленную пользователем (УниверсальныйОтчет.ДатаНач), с началом текущего месяца (НачалоМесяца(ТекущаяДата())) и выберет наибольшую (то есть самую позднюю) из них. Таким образом, даже если пользователь выберет прошлый год, программа принудительно подставит первое число текущего месяца.


// ... внутри условия проверки роли
УниверсальныйОтчет.ДатаНач = Макс(НачалоМесяца(ТекущаяДата()), УниверсальныйОтчет.ДатаНач);

Шаг 3. Установка принудительного отбора по складу

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

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

Итоговый код для процедуры СформироватьОтчет

Соберем все шаги в единый фрагмент кода, который нужно вставить в процедуру СформироватьОтчет в модуле объекта вашего отчета.


Процедура СформироватьОтчет(ТабличныйДокумент)

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

    // Стандартный вызов формирования универсального отчета
    УниверсальныйОтчет.СформироватьОтчет(ТабличныйДокумент);

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

Этот код решит поставленную задачу: при формировании отчета для пользователя с ролью «МенеджерПоСкладуОсновной» период и отбор будут принудительно скорректированы.

Дополнительные улучшения и альтернативные подходы

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

Как заблокировать поля на форме отчета?

Вышеописанный код изменяет настройки в момент нажатия кнопки «Сформировать». Однако пользователь все еще может изменить значения в полях на форме. Чтобы полностью заблокировать их, можно в процедуре формы отчета (например, ПриОткрытии) установить свойство Доступность для нужных элементов в Ложь.


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

Система компоновки данных (СКД)

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


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

Наиболее надежный метод — ограничение прав на уровне записей (RLS)

Если требуется, чтобы пользователь нигде в системе не видел данные по чужим складам (ни в отчетах, ни в списках документов), то правильнее всего использовать механизм RLS (Row-Level Security).

Этот подход является наиболее безопасным и комплексным, так как он не зависит от кода конкретного отчета и применяется ко всей системе целиком.

← На главную