Как программно запретить запись элемента справочника в расширении 1С?

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

При разработке расширений для конфигураций 1С часто возникает задача ограничить запись тех или иных данных. Типичный пример: запретить пользователю с определенной ролью изменять элементы справочника. Казалось бы, достаточно добавить процедуру-обработчик в расширение, установить параметр Отказ = Истина, и задача решена. Однако на практике разработчики часто сталкиваются с тем, что код просто не срабатывает. В этой статье мы подробно разберем, почему это происходит и как правильно реализовать запрет записи с учетом особенностей современных платформ и облачных сервисов вроде 1C:Fresh.

Разбор типичной ошибки: Почему &Перед("ПриЗаписи") может не работать?

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


&Перед("ПриЗаписи")
Процедура Расш1_ПередПриЗаписи(Отказ) 
    Если РольДоступна("Расш1_РСД") Тогда
        Сообщить("Недостаточно прав доступа!");
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры;

Проанализируем основные причины неудачи этого подхода:

  1. Выбор неправильного события: Событие ПриЗаписи вызывается уже внутри транзакции записи, когда данные фактически подготовлены к записи в базу. Для жесткого запрета на раннем этапе лучше использовать событие ПередЗаписью.
  2. Особенности работы аннотаций: В расширениях использование &Перед гарантирует выполнение вашего кода перед основной процедурой, но после этого управление передается в основной код конфигурации. Если в основном коде параметр Отказ будет переопределен (что является плохой практикой, но встречается), ваш запрет может быть проигнорирован.
  3. Безопасный режим расширения: Это критический момент для пользователей 1C:Fresh и облачных систем. Если расширение работает в безопасном режиме, платформа ограничивает перехват методов модулей объектов. В этом случае код в модуле объекта расширения просто не будет вызван.

Решение 1: Правильное использование события ПередЗаписью

Выясним, как сделать код более надежным. Вместо ПриЗаписи используем ПередЗаписью и добавим явное прерывание логики. Рассмотрим вариант с использованием аннотации &Вместо, который позволяет полностью контролировать выполнение процесса.


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

Использование метода ПродолжитьВызов(Отказ) — это стандарт современной разработки. Мы передаем управление дальше по цепочке только в том случае, если наша проверка пройдена успешно.

Решение 2: Обход ограничений безопасного режима

Если ваше расширение работает в безопасном режиме (как это часто бывает в 1C:Fresh), попытки расширить модуль объекта могут быть заблокированы. Проанализируем альтернативные пути решения задачи:

  1. Перенос логики в форму: Это самый простой способ. Мы создаем расширение для формы элемента и формы списка, перехватываем событие ПередЗаписьюНаСервере или ПередЗаписью. Однако помните: этот метод защищает только от интерактивных действий пользователя. Если элемент будет записываться программно (например, через обработку), код формы не сработает.
  2. Использование подписок на события: В самом расширении мы можем создать объект ПодпискаНаСобытие. В качестве источника укажем нужный справочник, а в качестве события — ПередЗаписью. Подписки в расширениях работают стабильнее, так как вызываются платформой напрямую, а не через механизм перехвата имен процедур.

Решение 3: Проверка прав доступа

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


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

Важные рекомендации при работе с параметром Отказ

При работе в расширениях мы должны придерживаться правила "накопительного отказа". Посмотрим, как это выглядит в коде:

Никогда не пишите: Отказ = Ложь; — это может сбросить запрет записи, установленный другим расширением или основной конфигурацией.

Правильно писать:


Если МоеУсловиеЗапрета Тогда
    Отказ = Истина;
КонецЕсли;

Таким образом, если хотя бы один из обработчиков (в основном коде или в любом из расширений) установит Отказ = Истина, элемент не будет записан, что гарантирует целостность бизнес-логики.

Итоги: что выбрать?

Проанализировав ситуацию, мы можем сделать следующие выводы:

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

← На главную