Как в 1С ограничить просмотр документов предыдущих дат

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

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

Почему возникает ошибка при попытке задать текущую дату в RLS

При попытке написать условие RLS вида ГДЕ Дата >= ТекущаяДата() платформа 1С выдает ошибку: Не задано значение параметра "текущаяДата". Выясним причину такого поведения платформы.

Условия RLS (Record Level Security) не исполняются встроенным языком 1С «на лету» для каждой строки. Платформа модифицирует исходный запрос и передает его СУБД в виде чистого SQL-запроса. Напрямую вызывать функции встроенного языка 1С (такие как ТекущаяДата() или НачалоДня()) внутри текста ограничений доступа нельзя. Любые динамические значения должны передаваться в RLS исключительно через параметры сеанса.

Способ 1. Реализация ограничения через RLS и параметры сеанса

Если требуется жестко запретить чтение записей на уровне платформы и СУБД, разберем по шагам, как правильно настроить RLS.

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

    В дереве метаданных конфигурации перейдем в ветку Общие — Параметры сеанса и создадим новый параметр НачалоПериодаRLS с типом Дата (состав даты: Дата и время).

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

    В модуле сеанса (в обработчике УстановкаПараметровСеанса) или в общем модуле при старте системы заполним значение параметра началом текущего дня. Посмотрим на пример кода:

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

    Обратите внимание: использование метода ТекущаяДатаСеанса() вместо ТекущаяДата() гарантирует учет часового пояса клиента, если сервер и клиентские рабочие места находятся в разных регионах.

  3. Настройка ограничения в роли

    Откроем нужную роль, перейдем к целевому документу (например, Документ.РеализацияТоваровУслуг) и на вкладке Права для права Чтение укажем условие ограничения доступа к данным:

    ТекущаяТаблица ГДЕ (ТекущаяТаблица.Дата >= &НачалоПериодаRLS)

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

  1. Переход через полночь: Если сеанс пользователя открыт круглосуточно, параметр сеанса, заполненный при входе, на следующий день устареет. Пользователю потребуется перезапустить программу либо потребуется регламентный сброс параметров сеанса.
  2. Нарушение ссылочной целостности: Запрет на чтение документов приведет к тому, что в движениях регистров, отчетах и документах-основаниях вместо ссылок на прошлые документы пользователь будет видеть надпись <Объект не найден>.
  3. Ошибки проведения: Если при проведении нового документа код конфигурации обращается к движениям или остаткам прошлых документов (партионный учет, ФИФО, взаиморасчеты) не в привилегированном режиме, проведение завершится критической ошибкой прав доступа.

Способ 2. Ограничение на уровне формы списка и формы документа (рекомендуемый)

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

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

  1. Установка фиксированного отбора в форме списка

    В модуле формы списка документов в обработчике ПриСозданииНаСервере добавим отбор в ФиксированныеНастройки динамического списка. Посмотрим на реализацию:

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

    Установка свойства РежимОтображения = Недоступный гарантирует, что поле не появится в окне «Настроить список», и пользователь не сможет снять фильтрацию.

  2. Запрет открытия ранее созданных документов

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

    
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
        Если Не РольДоступна("ПолныеПрава") Тогда
            // Проверяем, что документ уже существует в базе и его дата меньше текущего дня
            Если Не Объект.Ссылка.Пустая() И Объект.Дата < НачалоДня(ТекущаяДатаСеанса()) Тогда
                ВызватьИсключение "Просмотр и редактирование документов за прошлые даты запрещены.";
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    

Для конфигураций на обычных формах аналогичный отбор устанавливается в процедуре ПередОткрытием формы списка через свойства Отбор.Дата.Использование = Истина, Отбор.Дата.ВидСравнения = ВидСравнения.ИнтервалВключаяГраницы и отключение доступности настройки периода у элемента управления таблицы.

Использование интерфейсного подхода полностью решает задачу сокрытия информации от рядового персонала, не нарушает алгоритмы проведения документов и не создает лишней нагрузки на СУБД.

← На главную