Как обновлять текущую дату в параметрах сеанса для RLS при переходе на следующие сутки

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

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

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

Почему параметры сеанса не обновляются сами

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

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

Использование функции ТекущаяДатаСеанса вместо ТекущаяДата

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

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

Решение 1: Обновление параметров сеанса через клиентский обработчик ожидания

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

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

  1. В модуле управляемого приложения в процедуре ПриНачалеРаботыСистемы подключаем обработчик ожидания с интервалом, например, раз в 5–10 минут (300–600 секунд).
  2. В клиентской процедуре обработчика проверяем, изменилась ли дата относительно сохраненного значения.
  3. Если дата изменилась, вызываем серверную процедуру для перезаписи параметра сеанса.

Посмотрим на пример реализации в модуле управляемого приложения:


&НаКлиенте
Перем ДатаПоследнейПроверкиСеанса;

&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
    ДатаПоследнейПроверкиСеанса = НачалоДня(ТекущаяДатаСеанса());
    // Проверка раз в 5 минут (300 секунд)
    ПодключитьОбработчикОжидания("ПроверитьСменуСутокСеанса", 300);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСменуСутокСеанса()
    ТекущаяДатаКлиента = НачалоДня(ТекущаяДатаСеанса());
    Если ТекущаяДатаКлиента <> ДатаПоследнейПроверкиСеанса Тогда
        ДатаПоследнейПроверкиСеанса = ТекущаяДатаКлиента;
        ОбновитьПараметрыСеансаНаСервере();
    КонецЕсли;
КонецПроцедуры

В общем серверном модуле (с признаком «Вызов сервера») реализуем процедуру обновления параметра:


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

Поведение динамических списков и интерфейса

Важно учитывать поведение форм: при программном обновлении значения параметра сеанса открытые динамические списки и формы документов автоматически не перечитывают данные с сервера моментально. Для обновления отображаемых строк списка пользователь должен либо нажать кнопку «Обновить», либо в коде необходимо вызвать метод Обновить() у динамического списка формы.

Решение 2: Перенос проверок в объектную модель (подписки на события)

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

В типовых конфигурациях (например, ЗУП 3.1, ERP) проверки дат запрета редактирования часто выносят в объектную модель — подписки на события ПередЗаписью или обработку проверки заполнения. В момент записи объекта на сервере вызывается ТекущаяДатаСеанса(), что полностью исключает рассинхронизацию дат и снимает нагрузку с механизма RLS при чтении объемных таблиц.

← На главную