Как запретить редактирование документа в 1С при достижении определенного статуса

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки бизнес-логики в 1С часто возникает задача ограничить возможность изменения данных документа, если он прошел определенный этап жизненного цикла. Например, если реквизит Статус принимает значение Утвержден, обычным пользователям (или определенной их группе) должно быть запрещено вносить любые правки. Рассмотрим подробно, как реализовать этот механизм правильно, соблюдая баланс между безопасностью данных и удобством пользователя (юзабилити).

Комплексный подход к запрету редактирования

Проанализируем ситуацию: если мы ограничим редактирование только на уровне формы, программный код (обработки, обмены данными) всё равно сможет изменить документ. Если мы ограничим редактирование только в модуле объекта при записи, пользователь может потратить время на заполнение полей, нажать «Записать» и лишь тогда получить отказ, что вызовет негативную реакцию. Поэтому разберем правильную стратегию, состоящую из двух уровней защиты.

Уровень 1: Визуальная блокировка (Юзабилити)

Для того чтобы пользователь сразу видел, что документ нельзя редактировать, необходимо управлять свойством формы ТолькоПросмотр. Это лучше всего делать в обработчике события ПриЧтенииНаСервере или ПриСозданииНаСервере.

Рассмотрим пример кода, который проверяет статус и роль пользователя:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    Если Объект.Статус = Перечисления.СтатусыДокументов.Утвержден Тогда
        // Проверяем, есть ли у пользователя права на редактирование утвержденных документов
        Если НЕ РольДоступна("ПолныеПрава") И НЕ РольДоступна("АдминистрированиеДанных") Тогда
            ЭтаФорма.ТолькоПросмотр = Истина;
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Установка свойства ТолькоПросмотр = Истина для всей формы автоматически делает все элементы управления недоступными для изменения. Важно отметить нюанс: если реквизиты или элементы формы создаются программно (динамически), платформа всё равно применит к ним режим «только просмотр», если они входят в состав коллекции элементов формы.

Уровень 2: Контроль на уровне модуля объекта (Безопасность)

Проанализируем ситуацию, когда документ изменяется программно. Чтобы гарантированно запретить запись «утвержденного» документа, необходимо использовать обработчик события ПередЗаписью в модуле самого объекта. В отличие от модуля формы, этот код срабатывает всегда, независимо от того, как записывается документ: интерактивно пользователем или программно через обработку.

Разберем пример реализации в модуле объекта:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

    // Обязательно проверяем признак Загрузка, чтобы не блокировать обмен данными
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Ссылка может быть пустой у нового документа, проверяем наличие данных в базе
    Если ЗначениеЗаполнено(Ссылка) Тогда
        
        // Получаем статус из базы данных, а не из текущего объекта (чтобы проверить состояние ДО изменения)
        СтатусВБазе = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "Статус");
        
        Если СтатусВБазе = Перечисления.СтатусыДокументов.Утвержден Тогда
            // Проверяем роли текущего пользователя
            Если НЕ РольДоступна("ПолныеПрава") Тогда
                Сообщение = Новый СообщениеПользователю;
                Сообщение.Текст = "Документ утвержден. Редактирование запрещено!";
                Сообщение.Сообщить();
                Отказ = Истина;
            КонецЕсли;
        КонецЕсли;
        
    КонецЕсли;

КонецПроцедуры

Использование подписок на события для масштабируемости

Если в вашей конфигурации много документов, для которых нужно внедрить подобную логику, выясним причину, почему не стоит писать код в каждом модуле отдельно. Лучше создать одну Подписку на событие ПередЗаписью. Для этого создадим определяемый тип, в который включим все нужные документы, и назначим обработчик в общем модуле.

Посмотрим на пример универсального кода в общем модуле:


Процедура ПроверитьЗапретРедактированияПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт

    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Проверяем наличие реквизита "Статус" у объекта
    МетаданныеОбъекта = Источник.Метаданные();
    Если МетаданныеОбъекта.Реквизиты.Найти("Статус") <> Неопределено Тогда
        
        Если Источник.Статус = Перечисления.СтатусыДокументов.Утвержден Тогда
             // Дополнительная логика проверки ролей или даты запрета
             // Если условие нарушено: Отказ = Истина;
        КонецЕсли;
        
    КонецЕсли;

КонецПроцедуры

Дополнительные профессиональные методы

Помимо программного кода в модулях, существуют и другие способы решения задачи, которые часто используются в типовых решениях (ERP, КА, УТ):

  1. Ограничение на уровне записей (RLS): Это самый надежный метод на уровне платформы. В настройках роли можно прописать условие на право «Изменение». Система на уровне SQL-запроса будет проверять статус документа. Если статус совпадает с запрещенным, запись будет невозможна физически.
  2. Библиотека стандартных подсистем (БСП): Если конфигурация использует БСП, рекомендуется использовать подсистему «Запрет редактирования реквизитов объектов». Она позволяет гибко настраивать блокировку отдельных полей документа в зависимости от условий, не прибегая к сложному программированию.
  3. Условное оформление формы: Вместо полной блокировки через ТолькоПросмотр, можно использовать динамическое оформление. Это позволит, например, оставить доступным поле «Комментарий», даже если весь остальной документ заблокирован.

Важные нюансы и советы

Проанализируем несколько тонких моментов, которые часто упускают начинающие разработчики:

Таким образом, мы рассмотрели многоуровневую систему защиты данных. Комбинируя настройки формы для удобства пользователей и проверки в модулях для обеспечения безопасности, мы создаем надежное и понятное решение в среде 1С.

← На главную