Как в запросе 1С и RLS получить всех вышестоящих руководителей по иерархии подразделений?

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

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

Почему нельзя получить всех родителей прямым обращением через точку

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


#Если &ДокументооборотИспользоватьОграниченияПравДоступа #Тогда
ТаблицаДокумента ИЗ Документ.Отсутствие КАК ТаблицаДокумента
    ГДЕ 
        ТаблицаДокумента.Сотрудник = &ТекущийПользователь ИЛИ 
        ТаблицаДокумента.Сотрудник.Подразделение.Руководитель = &ТекущийПользователь ИЛИ
        ТаблицаДокумента.Сотрудник.Подразделение.Родитель.Руководитель = &ТекущийПользователь ИЛИ
        ТаблицаДокумента.Сотрудник.Подразделение.Родитель.Руководитель.Подразделение.Родитель.Руководитель = &ТекущийПользователь
#КонецЕсли

Такой подход имеет принципиальные недостатки:

  1. Отсутствие рекурсии в языке запросов 1С: Платформа 1С:Предприятие не поддерживает рекурсивные конструкции SQL (такие как WITH RECURSIVE). Выбрать произвольное, заранее неизвестное количество уровней иерархии вверх одним выражением в запросе невозможно.
  2. Критическая деградация производительности RLS: Конструкции с разыменованием ссылочных полей через точку (например, Сотрудник.Подразделение.Родитель.Руководитель) транслируются СУБД в каскады неявных левых соединений (LEFT JOIN). Поскольку условие RLS накладывается на каждую считываемую строку, такой запрос быстро приводит к блокировкам таблиц и зависанию динамических списков.
  3. Ограниченность структуры: Если иерархия подразделений компании превысит число жестко прописанных уровней (например, появится 5-й или 6-й уровень вложенности), доступ вышестоящему руководству перестанет предоставляться.

Способ 1. Инверсия логики с проверкой иерархии «сверху вниз»

Оператор платформы В ИЕРАРХИИ отлично оптимизирован для проверки вхождения элементов сверху вниз, но не работает в обратную сторону. Поэтому вместо того, чтобы от документа подниматься вверх к руководителю, логику разворачивают в противоположном направлении.

Разберем по шагам, как это реализовать:

  1. При старте сеанса или в момент вычисления параметров сеанса определяем список подразделений, которыми руководит текущий пользователь, и записываем их в параметр &ПодразделенияТекущегоРуководителя.
  2. В условии RLS используем оператор В ИЕРАРХИИ:

#Если &ДокументооборотИспользоватьОграниченияПравДоступа #Тогда
ТаблицаДокумента ИЗ Документ.Отсутствие КАК ТаблицаДокумента
    ГДЕ 
        ТаблицаДокумента.Сотрудник = &ТекущийПользователь
        ИЛИ ТаблицаДокумента.Сотрудник.Подразделение В ИЕРАРХИИ (&ПодразделенияТекущегоРуководителя)
#КонецЕсли

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

Способ 2. Подготовка списка доступных сотрудников в параметрах сеанса

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

Посмотрим на алгоритм реализации:

  1. Создаем параметр сеанса СписокДоступныхСотрудников с типом ФиксированныйМассив.
  2. При инициализации сеанса процедурой на встроенном языке циклически обходим дерево подразделений и заполняем массив ссылками на всех сотрудников, находящихся в прямом и косвенном подчинении пользователя.
  3. Условие RLS в шаблоне прав сводится к предельно простой и быстрой проверке:

ТаблицаДокумента ИЗ Документ.Отсутствие КАК ТаблицаДокумента
    ГДЕ 
        ТаблицаДокумента.Сотрудник В (&СписокДоступныхСотрудников)

Способ 3. Денормализация структуры (Таблица связей иерархии)

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

Разберем архитектуру такого решения:

  1. Создаем регистр сведений ИерархияПодразделенийИРуководителей с измерениями Подразделение, ВышестоящееПодразделение и Руководитель.
  2. В подписке на событие ПриЗаписи справочника СтруктураПредприятия или Подразделения запускаем процедуру, которая программно раскручивает всех родителей каждого подразделения и записывает полные плоские связки со всеми вышестоящими руководителями.
  3. В RLS соединяем проверяемую таблицу с подготовленным регистром:

ТаблицаДокумента ИЗ Документ.Отсутствие КАК ТаблицаДокумента
    ГДЕ 
        ТаблицаДокумента.Сотрудник = &ТекущийПользователь
        ИЛИ ТаблицаДокумента.Сотрудник.Подразделение В (
            ВЫБРАТЬ 
                РегистрИерархии.Подразделение 
            ИЗ 
                РегистрСведений.ИерархияПодразделенийИРуководителей КАК РегистрИерархии 
            ГДЕ 
                РегистрИерархии.Руководитель = &ТекущийПользователь
        )

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

← На главную