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