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