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