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

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

В процессе разработки конфигураций на платформе 1С часто возникает задача жесткого ограничения прав пользователя на изменение данных в зависимости от бизнес-процесса. Типичный пример: когда документ переходит в статус "В работе" или "Выполнен", его табличная часть должна стать недоступной для редактирования. При этом заказчик может потребовать, чтобы даже возврат в предыдущие статусы не "размораживал" строки. Рассмотрим подробно, как реализовать такую логику, используя различные механизмы платформы.

Метод 1. Использование технического реквизита (Флаг блокировки)

Простое условие "если статус равен Х, то блокировать" не всегда работает корректно, если мы хотим сохранить блокировку при любых последующих изменениях. Проанализируем ситуацию: пользователь установил статус "В работе", ТЧ заблокировалась. Если он решит обхитрить систему и вернет статус "Принят", обычное условие в коде формы может снова разрешить редактирование. Чтобы этого избежать, нам понадобится "память" документа о том, что он уже когда-то был заблокирован.

Разберем по шагам создание такой системы:

  1. Добавим в документ новый реквизит ЗапретРедактированияПринудительно с типом Булево. Не будем выносить его на форму, чтобы пользователь не мог изменить его вручную.
  2. В модуле формы документа создадим обработчик события ПриИзменении для реквизита Статус.
  3. Пропишем логику установки флага и блокировки интерфейса.

Посмотрим на пример кода в модуле формы:


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

Функция управления интерфейсом может выглядеть так:


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

Метод 2. Условное оформление (для Управляемых форм)

Использование свойства Доступность часто делает таблицу "серой" и трудночитаемой. Выясним причину, почему Условное оформление считается более профессиональным подходом. Оно позволяет гибко управлять визуальным состоянием элементов на уровне платформы, сохраняя при этом удобство для пользователя (например, возможность копировать текст из ячеек).

Рассмотрим, как настроить условное оформление программно в процедуре ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Создаем элемент условного оформления
    ЭлементОформления = УсловноеОформление.Элементы.Добавить();
    
    // Указываем, какое поле будем оформлять (наша табличная часть)
    ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
    ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("Товары");
    
    // Устанавливаем условие: ЗапретРедактированияПринудительно = Истина
    ЭлементУсловия = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементУсловия.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.ЗапретРедактированияПринудительно");
    ЭлементУсловия.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементУсловия.ПравоеЗначение = Истина;
    
    // Задаем само оформление
    ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);
    
КонецПроцедуры

Этот метод гарантирует, что как только значение реквизита ЗапретРедактированияПринудительно станет равным Истина, табличная часть Товары мгновенно перейдет в режим "Только чтение" без дополнительного обновления формы.

Метод 3. Защита на уровне модуля объекта

Важно помнить, что любые ограничения на форме можно обойти программно (например, через внешнюю обработку). Если нам нужно "жестко" ограничить изменения, проанализируем ситуацию на уровне сервера в модуле объекта. Это предотвратит запись документа, если правила бизнес-логики были нарушены.

Разберем пример кода в процедуре ПередЗаписью модуля объекта:


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

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

Важный нюанс: метод Модифицированность() для табличных частей работает эффективно, позволяя быстро определить, менялись ли строки. Однако в некоторых случаях надежнее сравнивать состав таблиц через Выгрузить() и сравнение коллекций, если требуется исключить ложные срабатывания при простом перестроении строк.

Метод 4. Разграничение прав доступа для исправления ошибок

В обсуждении на форуме справедливо заметили: "А как исправлять ошибки через полгода?". Жесткая блокировка может парализовать работу, если вкралась опечатка. Проанализируем решение через Роли.

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


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

Подведение итогов

Мы рассмотрели комплексный подход к блокировке данных. Для полноценной реализации рекомендуется совмещать визуальные и серверные методы:

  1. Используйте скрытый булевый реквизит для фиксации состояния "заморозки".
  2. Настраивайте Условное оформление для комфортной визуализации запрета на форме.
  3. Дублируйте проверку в Модуле объекта для защиты от программных правок.
  4. Оставляйте "лазейку" через проверку РольДоступна() для ответственных сотрудников.

Такой подход делает систему надежной и гибкой, защищая данные от случайных или намеренных изменений рядовыми пользователями после выполнения ключевых этапов бизнес-процесса.

← На главную