Как заблокировать документ для редактирования в 1С:Предприятие

Программист IT и автоматизация бизнеса
← На главную

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

Проблема: Почему недостаточно просто заблокировать форму?

Многие начинающие разработчики ограничиваются установкой свойства ТолькоПросмотр = Истина в модуле формы документа. Рассмотрим, почему этого мало. Если мы заблокируем только форму, пользователь все равно сможет выполнить действия с документом из формы списка (например, отменить проведение или пометить на удаление через контекстное меню) или изменить данные программно с помощью внешней обработки. Поэтому мы проанализируем ситуацию с разных сторон.

Способ 1. Надежная защита на уровне модуля объекта

Самый правильный и надежный метод — это проверка возможности записи непосредственно в модуле объекта. Это защитит данные независимо от того, откуда пришел запрос на изменение. Разберем реализацию в процедуре ПередЗаписью. Проанализируем пример кода:


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

Используя параметр Отказ = Истина, мы гарантируем, что никакие изменения не попадут в базу данных. Это решение является фундаментальным, так как оно работает и при ручном редактировании, и при программном вызове метода Записать().

Способ 2. Управление кнопками в форме списка

Часто авторы сталкиваются с проблемой: в форме документа все заблокировано, но в списке кнопки "Провести" и "Отмена проведения" остаются активными. Чтобы решить эту задачу, нам нужно использовать событие списка ПриАктивизацииСтроки. Рассмотрим этот процесс по шагам.

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


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

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

Способ 3. Блокировка всей формы через "ТолькоПросмотр"

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


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

Свойство ТолькоПросмотр автоматически отключает возможность редактирования всех реквизитов и делает стандартные кнопки записи недоступными.

Способ 4. Пессимистическая блокировка данных

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

Посмотрим на пример использования попытки блокировки в ПриОткрытии:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Попытка
        ЗаблокироватьДанныеФормыДляРедактирования();
    Исключение
        ЭтаФорма.ТолькоПросмотр = Истина;
        Сообщить("Документ уже редактируется другим пользователем или заблокирован.");
    КонецПопытки;
КонецПроцедуры

Способ 5. Глобальные механизмы (RLS и Даты запрета)

Если задача стоит масштабнее (например, закрыть целый месяц), рассмотрим системные подходы, которые не требуют написания кода в каждом документе:

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

Резюме и рекомендации

Проанализировав все способы, мы рекомендуем совмещать подходы. Обязательно реализуйте проверку в ПередЗаписью модуля объекта для обеспечения целостности данных. Параллельно используйте ТолькоПросмотр в форме документа и управление доступностью команд в ПриАктивизацииСтроки формы списка для качественного интерфейса (UX). Такой комплексный подход гарантирует, что пользователь не сможет обойти ограничения, а система будет вести себя предсказуемо и понятно.

← На главную