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