Как правильно добавить условие по менеджеру партнера в шаблон RLS?

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

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

В типовых ролях обычно используется стандартная конструкция библиотеки стандартных подсистем (БСП):


#Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
#ДляОбъекта("")
#Иначе
#ПоЗначениям( "Документ.ЗаказКлиента","Чтение","",
"Организации","Организация",
"Склады","Склад",
"ГруппыПартнеров","Партнер",
"Подразделения","Подразделение", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","" )
#КонецЕсли

Попытка напрямую вставить выражение ГДЕ Партнер.ОсновнойМенеджер = &ТекущийПользователь в текст роли приводит к синтаксической ошибке, так как вызов шаблона #ПоЗначениям требует строго определенного формата параметров. Разберем по шагам, как устроена эта конструкция, почему прямое редактирование текста роли часто не дает результата и как правильно решить поставленную задачу.

Шаг 1. Анализируем режим работы RLS (универсальный или стандартный)

Первое, на что необходимо обратить внимание — это директива препроцессора #Если &ОграничениеДоступаНаУровнеЗаписейУниверсально. В современных конфигурациях 1С по умолчанию включен производительный (универсальный) режим ограничения прав доступа.

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

Шаг 2. Встраивание условия в шаблон #ПоЗначениям (устаревший режим RLS)

Если в базе используется обычный RLS без механизма ключей доступа, разработчику не обязательно полностью отказываться от шаблона и вручную переписывать условия по всем видам доступа. В шаблоне #ПоЗначениям предусмотрен служебный параметр "Условие".

Посмотрим, как правильно передать произвольное логическое выражение в шаблон. Вместо пустой пары параметров мы подставляем ключевое слово "Условие" и текст проверки:


#ПоЗначениям( "Документ.ЗаказКлиента","Чтение","",
"Организации","Организация",
"Склады","Склад",
"ГруппыПартнеров","Партнер",
"Подразделения","Подразделение",
"Условие", "Партнер.ОсновнойМенеджер = &ТекущийПользователь",
"","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","" )

Важно учитывать особенности работы этого механизма:

  1. Все переданные параметры в шаблоне #ПоЗначениям объединяются по логическому оператору И. Это означает, что заказ будет доступен пользователю только при совпадении организации, склада, подразделения, группы партнеров И одновременном равенстве основного менеджера.
  2. Если требуется логика ИЛИ (например, доступ открыт по подразделению или по факту того, что пользователь назначен менеджером), шаблон #ПоЗначениям не подойдет. В этом случае применяют шаблон #ПоЗначениямРасширенный, поддерживающий логические скобки и операции объединения.
  3. В зависимости от версии БСП, к полям текущей таблицы может потребоваться обращаться через стандартный псевдоним таблицы, например Т.Партнер.ОсновнойМенеджер = &ТекущийПользователь.

Шаг 3. Анализируем риски производительности и платформенные ограничения

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

  1. Неявные соединения (разыменование через точку): Конструкция Партнер.ОсновнойМенеджер на уровне СУБД разворачивается в оператор LEFT OUTER JOIN с таблицей справочника Партнеры. При каждом открытии списка документов, формировании отчетов или проведении документов платформа будет соединять таблицы на уровне ограничений прав. По стандартам разработки фирмы «1С» такие RLS-запросы классифицируются как неоптимальные и приводят к резкому падению скорости работы динамических списков.
  2. Типы данных: Параметр сеанса &ТекущийПользователь хранит ссылку на справочник Пользователи. Если реквизит ОсновнойМенеджер имеет тип ФизическиеЛица или составной тип, простое сравнение на равенство всегда вернет результат Ложь.
  3. Смена ответственного лица: Если у партнера изменится значение реквизита ОсновнойМенеджер, в универсальном режиме RLS потребуется глобальный фоновый пересчет ключей доступа для всей цепочки связанных исторических документов, что создает пиковые нагрузки на сервер.

Шаг 4. Альтернативные и более надежные способы реализации

Рассмотрим два архитектурно правильных подхода, которые рекомендуются вместо ручной правки шаблонов в ролях.

Вариант 1. Использование типового механизма групп доступа партнеров (без доработки кода)

Это наиболее простой и рекомендуемый путь в типовых конфигурациях. Включаем функциональную опцию Группы доступа партнеров в настройках прав пользователей:

  1. Создаем группы доступа партнеров, соответствующие менеджерам (или отделам).
  2. Назначаем партнерам соответствующую группу доступа.
  3. В профилях или группах доступа пользователей выдаем права на соответствующие группы партнеров. Шаблон #ПоЗначениям уже содержит разрез "ГруппыПартнеров","Партнер", поэтому система отработает штатно, быстро и без внесения изменений в конфигурацию.

Вариант 2. Программная настройка в универсальном RLS и денормализация

Если в системе активен универсальный RLS и необходимо контролировать доступ именно по конкретному пользователю:

  1. Денормализация поля: Добавляем реквизит Менеджер непосредственно в документ ЗаказКлиента и заполняем его при выборе партнера. Проверка прямого реквизита документа выполняется СУБД в разы быстрее, чем соединение через точку.
  2. Регистрация вида доступа: В общем модуле УправлениеДоступомПереопределяемый в процедуре ПриЗаполненииВидовДоступа регистрируем новый вид доступа.
  3. Формирование наборов значений: В модуле менеджера документа переопределяем процедуру ПриЗаполненииОграниченияДоступа (или ПриЗаполненииНаборовЗначенийДоступа), где программно передаем значение менеджера в ключи доступа БСП. В таком случае отбор будет производиться по индексированным таблицам ключей доступа, сохраняя максимальную производительность системы.
← На главную