Как использовать текущую дату в ограничениях доступа на уровне записей (RLS) в 1С

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

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

В этой статье мы подробно разберем, почему в шаблонах RLS нельзя использовать привычные функции языка запросов напрямую, и проанализируем проверенные способы реализации таких ограничений на примере конфигурации «Управление торговлей 10.3».

Почему функция ТекущаяДата() не работает в шаблонах RLS

Давайте разберем причину этого ограничения. Механизм RLS работает на уровне СУБД (SQL Server, PostgreSQL и др.). Когда платформа выполняет запрос к базе данных от имени пользователя, у которого настроены ограничения, она динамически модифицирует этот запрос, добавляя в секцию ГДЕ условия из шаблона RLS.

Платформа 1С:Предприятие не выполняет трансляцию функций типа ТекущаяДата() или НачалоПериода() в соответствующие функции конкретной СУБД при формировании RLS-запроса. В тексте ограничений разрешено использовать только:

  1. Поля текущей таблицы и вложенных таблиц.
  2. Параметры сеанса.
  3. Функциональные опции (начиная с версии 8.3).

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

Способ 1. Использование параметров сеанса

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

Шаг 1. Создание параметра сеанса

В конфигураторе перейдем в ветку Общие -> Параметры сеанса. Создадим новый параметр, например, с именем ТекущаяДатаДоступа. Укажем для него тип Дата (состав даты: Дата и время или только Дата, в зависимости от ваших задач).

Шаг 2. Инициализация параметра

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

Разберем пример кода для модуля сеанса:


Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    Если ТребуемыеПараметры = Неопределено Тогда
        // Инициализация при начале работы
        ПараметрыСеанса.ТекущаяДатаДоступа = НачалоДня(ТекущаяДата());
    Иначе
        // Инициализация по требованию системы
        Для Каждого ИмяПараметра Из ТребуемыеПараметры Цикл
            Если ИмяПараметра = "ТекущаяДатаДоступа" Тогда
                ПараметрыСеанса.ТекущаяДатаДоступа = НачалоДня(ТекущаяДата());
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Шаг 3. Настройка RLS

Теперь в роли, где настраивается ограничение прав, мы можем обратиться к этому параметру. Текст ограничения в шаблоне будет выглядеть следующим образом:

ГДЕ Дата >= &ТекущаяДатаДоступа

Здесь префикс & указывает платформе, что значение нужно взять из одноименного параметра сеанса.

Способ 2. Решение проблемы «полуночи»

Проанализируем важный нюанс: если пользователь вошел в систему в 23:00 и работает до 02:00 ночи, значение параметра сеанса &ТекущаяДатаДоступа останется вчерашним (так как оно установилось при входе). Это может привести к тому, что пользователь будет видеть лишние данные или, наоборот, не сможет работать с новыми документами.

Чтобы избежать этой проблемы, мы можем использовать один из следующих подходов:

  1. Обработчик ожидания: На стороне клиента можно запустить процедуру, которая каждые 30-60 минут будет вызывать серверный метод для обновления значения параметра сеанса.
  2. Обновление перед критическими действиями: В конфигурации УТ 10.3 можно добавить обновление параметра в обработчик открытия основных журналов документов.

Пример обновления параметра сеанса из кода:


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

Проблемы производительности и индексация

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

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

Альтернатива: Программные отборы в формах

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

В конфигурации «Управление торговлей 10.3» это реализуется в процедуре ПриОткрытии или ПередОткрытием формы списка:


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

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

Подведем итоги

Для реализации ограничения по дате в RLS мы выяснили следующее:

← На главную