В процессе настройки документооборота часто возникает задача запретить пользователям редактировать документы спустя определенное количество дней после их создания. При решении этой задачи разработчики сталкиваются со спецификой конфигурации «1С:Документооборот», а также с ограничениями механизма RLS (ограничение доступа на уровне записей).
Разберем, почему стандартные подсистемы дат запрета и шаблоны RLS не всегда подходят для этой цели, а также подробно рассмотрим рабочие и надежные варианты реализации контроля.
Прежде чем приступать к разработке, проанализируем важные технические нюансы конфигурации:
Справочник.ВнутренниеДокументы, Справочник.ВходящиеДокументы). Из-за этого стандартная подсистема БСП «Даты запрета изменения» в типовом варианте для них не предназначена.&ТекущаяДата), значение фиксируется один раз при старте сеанса. Если пользователь не перезапускает программу в течение нескольких дней, дата в сеансе устаревает, и проверка прав начинает работать некорректно.Самый простой вариант — ограничить возможность изменения непосредственно в форме документа. Для этого рассчитывается разница между текущим временем и датой создания документа.
Посмотрим на пример кода в обработчике формы. Число 86400 — это количество секунд в одних сутках (24 часа × 60 минут × 60 секунд), так как при вычитании дат в платформе 1С результат получается в секундах:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
КоличествоДнейБлокировки = 5; // Срок в днях
СрокВСекундах = КоличествоДнейБлокировки * 86400;
// Сравниваем разницу дат с допустимым порогом
Если (ТекущаяДата() - Объект.ДатаСоздания) > СрокВСекундах Тогда
ЭтаФорма.ТолькоПросмотр = Истина;
КонецЕсли;
КонецПроцедуры
Ограничения способа: Установка свойства ТолькоПросмотр = Истина защищает документ только от ручного редактирования в открытой форме. Данные по-прежнему можно будет перезаписать через групповое изменение реквизитов, внешние обработки, HTTP/SOAP-сервисы или бизнес-процессы.
Для гарантированной защиты данных от изменения любым способом создадим подписку на событие ПередЗаписью для объектов справочников документов.
Разберем по шагам реализацию этого механизма:
СправочникОбъект.ВнутренниеДокументы, СправочникОбъект.ВходящиеДокументы, СправочникОбъект.ИсходящиеДокументы.ПередЗаписью.ТекущаяДатаСеанса(), чтобы избежать расхождений часовых поясов сервера и клиента.Рассмотрим код обработчика подписки:
Процедура ПроверитьСрокРедактированияДокументаПередЗаписью(Источник, Отказ) Экспорт
// Если объект новый, дата создания только устанавливается, запрет не нужен
Если Источник.ЭтоНовый() Тогда
Возврат;
КонецЕсли;
// Пропускаем проверку для пользователей с полными правами или администраторов
Если РольДоступна("ПолныеПрава") Или РольДоступна("Администратор") Тогда
Возврат;
КонецЕсли;
КоличествоДнейБлокировки = 5;
СрокВСекундах = КоличествоДнейБлокировки * 86400;
// Проверяем срок с момента создания документа
Если (ТекущаяДатаСеанса() - Источник.ДатаСоздания) > СрокВСекундах Тогда
Отказ = Истина;
ВызватьИсключение "Истек допустимый срок редактирования документа ("
+ Строка(КоличествоДнейБлокировки) + " дн.). Изменение запрещено.";
КонецЕсли;
КонецПроцедуры
Если в системе настроена сложная ролевая модель и требуется гибкое управление, наилучшим подходом является разделение онлайн-проверок и фоновой обработки:
ЗакрытОтИзменений с типом Булево.ЗакрытОтИзменений = Истина.Чтобы не снимать типовую конфигурацию с поддержки, все вышеперечисленные проверки рекомендуется выносить в Расширение конфигурации. Для этого обработчик ПередЗаписью в модуле объекта перехватывается с помощью аннотации &Перед:
&Перед("ПередЗаписью")
Процедура Расш_ПередЗаписью(Отказ)
Если ЭтоНовый() Тогда
Возврат;
КонецЕсли;
Если Не РольДоступна("ПолныеПрава") И (ТекущаяДатаСеанса() - ДатаСоздания) > (5 * 86400) Тогда
Отказ = Истина;
Сообщить("Срок редактирования документа истек. Обратитесь к администратору.");
КонецЕсли;
КонецПроцедуры
Такой подход обеспечивает сохранение целостности конфигурации и легкое обновление версии 1С:Документооборот в будущем.