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