В процессе разработки часто возникает задача ограничить создание новых документов по определенным бизнес-правилам, которые не связаны напрямую с системой прав доступа. Например, можно запретить создание заказов после 18:00 или разрешить ввод только одного документа определенного вида на основании другого. При этом важно не просто запретить действие, но и понятно объяснить пользователю причину отказа, так как это напрямую влияет на пользовательский опыт при работе с программными ограничениями.
Разберем несколько способов реализации такого запрета, их преимущества, недостатки и особенности применения, в том числе используя расширения для блокировки записи объекта по условию.
Это наиболее подходящий и логичный метод для блокировки интерактивного создания документа. Этот обработчик события формы срабатывает в самый первый момент ее серверной инициализации, еще до того, как форма будет передана на клиент. Для реализации сложной логики изменения интерфейса "на лету" также может быть полезен специальный модификатор управляемых форм.
Ключевые моменты:
Параметры.Ключ.Пустая().ВызватьИсключение(), который прервет выполнение кода и покажет пользователю модальное окно с текстом ошибки.Особенность при работе с расширениями:
При добавлении логики через расширение конфигурации важно использовать обработчик с суффиксом `Перед` (например, `МоеРасширение_ПриСозданииНаСервереПеред`). В обработчиках с суффиксом `После` платформа может запретить изменение стандартных параметров, таких как `Отказ`, и вы получите ошибку "Запрещено изменение параметра, отменяющего действие".
Посмотрим на итоговый пример кода, который решает задачу автора темы:
&НаСервере
// Используем обработчик "Перед", чтобы иметь возможность изменить параметр "Отказ" в расширении
Процедура МоеРасширение_ПриСозданииНаСервереПеред(Отказ, СтандартнаяОбработка)
// Условие 1: Это новый документ?
// Проверяем, что в параметрах формы не передан ключ существующего объекта
Если Параметры.Ключ.Пустая()
// Условие 2: Выполняется ли наше бизнес-правило?
// Например, проверяем роль пользователя и текущее время
И РольДоступна("KMS_Склад")
И Час(ТекущаяДата()) >= 18 Тогда
// Устанавливаем флаг отказа, чтобы форма не открылась
Отказ = Истина;
// Формируем понятный текст для пользователя
ТекстСообщения = "Создание заказов работникам склада после 18:00 запрещено.";
// Вызываем исключение, чтобы показать модальное окно с сообщением
ВызватьИсключение(ТекстСообщения);
КонецЕсли;
КонецПроцедуры
Этот обработчик события объекта, а не формы. Он срабатывает еще раньше, чем `ПриСозданииНаСервере`, в момент, когда платформа создает новый объект документа в памяти. Он тоже подходит для нашей задачи, но имеет свои нюансы и относится к альтернативным способам запрета создания объектов.
Ключевые моменты:
ВызватьИсключение().В некоторых типовых конфигурациях существуют специализированные решения, позволяющие реализовать блокировку и отслеживание изменений объектов 1С непосредственно с формы. Также могут существовать процедуры вида `УправлениеДиалогомСервер.ЗапретитьОткрытиеФормыОбъекта`, которые "под капотом" реализуют сложную логику с передачей параметров и вызовом исключений.
Пример кода:
// В модуле объекта документа
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
// Проверяем наше условие
Если ВыполняетсяУсловиеЗапрета() Тогда
ТекстСообщения = "Создание документа запрещено по таким-то причинам.";
// Прерываем выполнение и показываем ошибку
ВызватьИсключение(ТекстСообщения);
КонецЕсли;
КонецПроцедуры
Этот метод так же эффективен, как и первый, но размещение логики в обработчике формы (`ПриСозданииНаСервере`) часто считается более правильным с точки зрения архитектуры, так как мы управляем именно поведением интерфейса.
Рассмотрим еще несколько методов, которые могут быть полезны в других ситуациях.
`ПередЗаписью`
Этот обработчик позволяет отменить запись документа (`Отказ = Истина`). Однако для задачи запрета создания он не подходит, так как сработает только тогда, когда пользователь уже заполнил весь документ и нажал кнопку "Записать". Это приведет к потере времени и негативному пользовательскому опыту.
Подписка на событие `ОбработкаПолученияФормы`
Это более продвинутый и гибкий механизм. Он позволяет создать централизованную проверку для разных видов документов, не внося изменения в каждый из них. В обработчике подписки можно проанализировать тип создаваемого объекта и условия, а затем либо отменить открытие формы, либо подменить ее на свою "форму-заглушку" с сообщением.
В обсуждении был поднят важный архитектурный вопрос: использование функции РольДоступна("ИмяРоли") для управления бизнес-логикой является антипаттерном. Давайте разберемся, почему.
Какие есть альтернативы?
Если ПараметрыСеанса.ТекущийПользователь.Подразделение = &Склад Тогда.... Это гораздо гибче и проще в администрировании.