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