Как реализовать собственное ограничение RLS для номенклатуры на базе БСП 2.4?

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

Реализация ограничений на уровне записей (RLS) в современных конфигурациях, использующих Библиотеку стандартных подсистем (БСП) версии 2.4 и выше, существенно отличается от классического подхода «чистой» платформы. Основная сложность заключается в использовании механизма «Производительного RLS», который опирается на предварительно рассчитанные ключи доступа. Рассмотрим, как интегрировать собственную логику скрытия номенклатуры (например, по флагу «Не действует» из регистра сведений) в экосистему БСП, сохранив при этом быстродействие системы.

Анализ архитектуры ограничения доступа в БСП 2.4

Прежде чем приступать к кодингу, разберем, как БСП обрабатывает права. В версии 2.4 (используемой в УТ 11.4) система не просто выполняет запрос, прописанный в роли. Она обращается к служебным таблицам РегистрСведений.КлючиДоступаКОбъектам. Когда мы открываем список номенклатуры, платформа проверяет соответствие ключа доступа объекта и разрешенных ключей текущего пользователя.

Если мы попытаемся вставить в шаблон RLS прямой запрос к периодическому регистру сведений (используя СрезПоследних), это приведет к катастрофическому падению производительности при формировании динамических списков и проведении документов. Поэтому наша задача — сделать так, чтобы БСП сама управляла доступом, основываясь на наших данных.

Способ 1: Использование стандартного реквизита ГруппаДоступа

Это самый «чистый» способ с точки зрения поддержки типовой конфигурации. В справочнике Номенклатура уже есть реквизит ГруппаДоступа. Мы можем использовать его для разделения товаров на «Разрешенные» и «Скрытые».

Алгоритм действий:

  1. Создадим в справочнике ГруппыДоступаНоменклатуры элемент, например, «Скрытая номенклатура».
  2. В профилях групп доступа для менеджеров укажем этот вид доступа и добавим созданную группу в исключения (запретим её).
  3. Внедрим механизм автоматической актуализации реквизита ГруппаДоступа в справочнике Номенклатура при изменении нашего регистра сведений.

Для реализации автоматизации в расширении создадим подписку на событие ПриЗаписи для нашего регистра сведений. Рассмотрим пример кода:


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

    // Предположим, в регистре есть измерение Номенклатура и ресурс Действует (Булево)
    Для Каждого Запись Из Источник Цикл
        ОбъектНом = Запись.Номенклатура.ПолучитьОбъект();
        Если ОбъектНом = Неопределено Тогда
            Продолжить;
        КонецЕсли;
        
        НужнаяГруппа = ?(Запись.Действует, Справочники.ГруппыДоступаНоменклатуры.ПустаяСсылка(), 
                                            Справочники.ГруппыДоступаНоменклатуры.НайтиПоНаименованию("Скрытая"));
        
        Если ОбъектНом.ГруппаДоступа <> НужнаяГруппа Тогда
            ОбъектНом.ГруппаДоступа = НужнаяГруппа;
            // Важно: отключаем проверки, чтобы ускорить запись
            ОбъектНом.ОбменДанными.Загрузка = Истина; 
            ОбъектНом.Записать();
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Важный момент: Если у вас планируется массовая загрузка цен или прайсов (100 000+ позиций), запись в справочник может затянуться. В этом случае обновление реквизита лучше вынести в фоновое задание или использовать метод УстановитьСсылкуНового() при первичной загрузке, чтобы минимизировать количество транзакций.

Способ 2: Реализация собственного Вида доступа (Программный метод)

Если использование стандартной группы доступа невозможно (например, она уже занята под другие цели), мы можем расширить состав видов доступа БСП. Это более трудоемкий, но правильный путь для сложных внедрений.

Рассмотрим шаги по добавлению вида доступа через УправлениеДоступомПереопределяемый:

  1. В расширении переопределим процедуру ПриЗаполненииВидовДоступа в модуле УправлениеДоступомПереопределяемый.
  2. Добавим описание нашего нового ограничения.

Пример регистрации нового вида доступа:


Процедура ПриЗаполненииВидовДоступа(ВидыДоступа) Экспорт
    
    Вид = ВидыДоступа.Добавить();
    Вид.Имя          = "СтатусНоменклатуры";
    Вид.Заголовок    = НСтр("ru = 'Статус номенклатуры'");
    Вид.ТипЗначений  = Тип("СправочникСсылка.Номенклатура"); // Или ссылка на ваш регистр/перечисление
    Вид.ГруппыЗначений = Тип("СправочникСсылка.ГруппыДоступаНоменклатуры");
    
КонецПроцедуры

После добавления вида доступа необходимо будет обновить шаблоны RLS в ролях. В БСП для этого используется стандартный шаблон #ПоЗначениям. Разберем его структуру для нашей задачи:

#ПоЗначениям("Справочник.Номенклатура", "", "", "СтатусНоменклатуры", "Ссылка", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "")

Такой подход заставит систему учитывать настройки, сделанные в профилях групп доступа, для вашего нового вида доступа.

Оптимизация массового обновления прав

Проанализируем ситуацию, когда необходимо «скрыть» сразу весь прайс-лист. Прямая перезапись 100 000 элементов справочника заблокирует работу пользователей. Для обхода этой проблемы в БСП предусмотрен механизм обновления ключей доступа.

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

Почему нельзя использовать СрезПоследних в тексте RLS?

Рассмотрим техническую причину. Когда вы пишете в роли условие типа:
ГДЕ Ссылка В (ВЫБРАТЬ Номенклатура ИЗ РегистрСведений.Статусы.СрезПоследних(&Период, Флаг = ИСТИНА)),
платформа при каждом обращении к номенклатуре генерирует вложенный запрос с использованием конструкции MAX(Период) и GROUP BY. Если в базе 100 пользователей одновременно подбирают товар, нагрузка на SQL-сервер возрастает экспоненциально.

Рекомендация: Всегда стремитесь к тому, чтобы RLS работал по индексированному полю (обычно это Ссылка или ГруппаДоступа). Все сложные условия должны быть вычислены ДО того, как пользователь открыл форму списка, и сохранены в простом реквизите или ключе доступа.

Настройка профиля и исключений

Разберем, как настроить права в интерфейсе после внесения изменений в код:

  1. Откройте «Группы настроек пользователей» или «Профили групп доступа».
  2. Выберите профиль «Менеджер по продажам».
  3. На вкладке «Ограничения доступа» добавьте ваш вид доступа (или стандартный «Номенклатура»).
  4. Установите значение «Все разрешены, исключения назначаются в группах доступа».
  5. Создайте группу доступа «Недействующие товары» и добавьте туда запрещенные элементы.

Таким образом, для большинства пользователей система будет возвращать пустое значение или <Объект не найден>, а администраторы и руководители, у которых это ограничение не задано в профиле, будут видеть полную картину данных.

Резюме

Для реализации задачи в БСП 2.4 наиболее эффективным является путь синхронизации состояния регистра с реквизитом справочника через подписки на события. Это позволяет использовать оптимизированные алгоритмы БСП, не создавая «велосипедов» в тексте запросов RLS, и гарантирует стабильную работу системы даже при больших объемах данных.

← На главную