Как в 1С:УНФ временно заблокировать документы от изменений выборочно?

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

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

Разбираемся в терминологии: блокировка СУБД против бизнес-логики

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

1. Пессимистическая (транзакционная) блокировка

Когда вы открываете форму документа в 1С и начинаете что-то менять, платформа пытается выполнить метод ЗаблокироватьДанныеДляРедактирования(). Если другой пользователь уже редактирует этот объект, вы получите сообщение об ошибке.

Этот механизм предназначен для обеспечения целостности данных в момент записи или активного редактирования. Он не подходит для задачи "заблокировать на день-два", потому что:

  1. Блокировка снимается при закрытии окна или завершении сеанса.
  2. Длительные транзакции "вешают" сервер и мешают регламентным заданиям (например, бэкапам).
  3. Это техническое ограничение, а не административное.

2. Логическая (бизнес) блокировка

Это именно то, что требовалось автору вопроса: установка признака, запрещающего изменение документа по воле пользователя на длительный срок. Здесь нет открытых транзакций базы данных. Система просто "знает", что этот документ трогать нельзя. В типовом функционале УНФ такого механизма для произвольного выбора документов "из коробки" в явном виде нет, но мы рассмотрим, как управлять статусами и бизнес-логикой для решения этой задачи.

Способ 1. Использование штатных механизмов (Состояния и Права)

Если мы не хотим или не можем программировать, давайте посмотрим, что предлагает УНФ. Логика работы этой конфигурации тесно связана с понятием Состояния (статуса) документа. Это особенно актуально для "Заказов покупателей", "Заказ-нарядов" и т.д.

Мы можем настроить систему так, чтобы при переходе документа в определенный статус его редактирование запрещалось.

  1. Зайдем в настройки параметров учета или настройки конкретного вида документов.
  2. Найдем настройку "Запрет редактирования реквизитов" или настройку прав доступа по статусам.
  3. Установим правило: если статус "На согласовании" или "Заблокирован", редактировать документ может только определенная роль (или никто).

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

Способ 2. Программная реализация (через Расширение)

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

Давайте спроектируем это решение по шагам.

Шаг 1. Хранение информации о блокировках

Нам нужно где-то хранить информацию о том, какой документ заблокирован, кем и когда. Для этого идеально подойдет Регистр сведений. Создадим его в расширении.

Назовем его, например, РГ_ЗаблокированныеОбъекты.

Измерения:

Ресурсы:

Шаг 2. Интерфейс блокировки

Пользователю нужна кнопка. Мы добавим общую команду или кнопку на форму документа через расширение формы.

Логика команды проста: она должна создавать или удалять запись в нашем регистре сведений РГ_ЗаблокированныеОбъекты. Примерный код процедуры на сервере при нажатии кнопки "Заблокировать":


МенеджерЗаписи = РегистрыСведений.РГ_ЗаблокированныеОбъекты.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ОбъектБлокировки = Объект.Ссылка;
МенеджерЗаписи.Пользователь = Пользователи.ТекущийПользователь();
МенеджерЗаписи.ДатаБлокировки = ТекущаяДата();
МенеджерЗаписи.Записать();

Шаг 3. Запрет открытия формы (Визуальная блокировка)

В обсуждении предлагали использовать событие ПриСозданииНаСервере. Это верно для улучшения пользовательского опыта (UX). Если документ заблокирован, мы должны сразу открыть его только на просмотр и предупредить пользователя.

В модуле расширения формы документа пишем:


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

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

Важно: Этого недостаточно! Проверка на форме защищает только от интерактивного изменения через эту конкретную форму. Если кто-то попытается изменить документ через групповую обработку, обмен данными или программно, этот код не сработает.

Шаг 4. Гарантированный запрет записи (Подписка на событие)

Чтобы защита была надежной ("железобетонной"), нам нужно перехватить сам момент записи объекта в базу данных. Для этого в расширении создадим Подписку на событие ПередЗаписью для нужных документов.

В обработчике подписки мы проверим наличие блокировки. Если она есть, и текущий пользователь — не тот, кто её поставил (или не администратор), мы откажем в записи.


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

    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   РГ.Пользователь КАК Пользователь
        |ИЗ
        |   РегистрСведений.РГ_ЗаблокированныеОбъекты КАК РГ
        |ГДЕ
        |   РГ.ОбъектБлокировки = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        ТекущийЮзер = Пользователи.ТекущийПользователь();
        // Разрешаем менять автору блокировки, остальным - отказ
        Если Выборка.Пользователь <> ТекущийЮзер Тогда
            Отказ = Истина;
            ВызватьИсключение "Документ заблокирован пользователем: " + Выборка.Пользователь;
        КонецЕсли;
    КонецЕсли;

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

Как работает блокировка файлов?

Автор вопроса также интересовался блокировкой файлов. В 1С, в том числе в УНФ, механизм работы с файлами похож на системы контроля версий.

Когда вы открываете прикрепленный файл на редактирование, система помечает его "Занятым" (обычно иконка становится зеленой). Технически, в регистре сведений ФайлыВРабочемКаталоге или аналогичном (зависит от версии БСП) появляется запись.

Пока пользователь не нажмет кнопку "Закончить редактирование" (сохранить новую версию в 1С) или "Освободить", другие пользователи смогут открыть этот файл только в режиме чтения. Это штатный функционал подсистемы «Работа с файлами», и программировать здесь обычно ничего не нужно — достаточно правильно настроить права и тома хранения файлов.

Резюме

Давайте подведем итог. Чтобы запретить изменение конкретных документов в УНФ на несколько дней:

  1. Стандартные механизмы (дата запрета, статусы) решают задачу частично и работают по группам документов, а не точечно.
  2. Техническая блокировка (объектная) работает только в момент транзакции и не подходит для удержания "на дни".
  3. Лучшее решение — создание расширения с регистром сведений для хранения списка заблокированных объектов и подпиской на событие, которая будет проверять этот регистр и запрещать сохранение изменений.
← На главную