При разработке бизнес-логики в 1С:Предприятие часто возникает задача ограничить доступ к определенным операциям в зависимости от прав пользователя. Типичный пример: запретить выбор конкретного значения в документе, если у пользователя нет специальной роли. Начинающие разработчики часто сталкиваются с трудностями при написании условий, путая синтаксис сравнения перечислений и логические операторы. Разберем детально, как реализовать такую проверку правильно и красиво.
Представим ситуацию: в документе есть реквизит ВидОперации, который принимает значения из перечисления (например, "А", "Б", "В"). Нам нужно реализовать следующую логику:
Рассмотрим по шагам, как избежать ошибок и построить надежное условие в модуле объекта документа.
Одной из самых частых ошибок является попытка сравнить значение перечисления с логическим значением Истина или Ложь. Проанализируем ошибочный код:
// ОШИБОЧНЫЙ КОД
Если НЕ Перечисления.ВидыОпераций.А = Истина Тогда
// Так делать нельзя!
КонецЕсли;
Выясним причину ошибки: значения перечислений в 1С являются объектами ссылочного типа. Они не могут быть "истинными" или "ложными" сами по себе. Ссылка на значение перечисления может быть либо равна другой ссылке, либо нет. Правильное сравнение всегда выглядит так: РеквизитДокумента = Перечисления.ИмяПеречисления.ИмяЗначения.
Еще одна ловушка — обращение к менеджеру перечисления вместо конкретного реквизита. Код Перечисления.ВидыОпераций <> Перечисления.ВидыОпераций.А также не имеет смысла, так как вы пытаетесь сравнить всю совокупность метаданных с одной конкретной ссылкой.
Теперь перейдем к правильному построению условия. Нам нужно проверить два факта одновременно: отсутствие роли и выбор запрещенного значения. Проанализируем итоговый вариант решения задачи в обработчике ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем наличие роли и выбранное значение
Если НЕ РольДоступна("ПолныеПрава")
И ВидОперации = Перечисления.ВидыОпераций.СписаниеЗадолженности Тогда
Отказ = Истина; // Блокируем запись документа
// Информируем пользователя о причине отказа
ТекстСообщения = "У вас недостаточно прав для оформления операции 'Списание задолженности'!";
Сообщить(ТекстСообщения);
КонецЕсли;
КонецПроцедуры
Посмотрим на это условие внимательнее. Если РольДоступна() возвращает Ложь И при этом в поле ВидОперации выбрано значение СписаниеЗадолженности, система установит флаг Отказ = Истина. Во всех остальных случаях (если роль есть ИЛИ выбрана другая операция) запись будет разрешена.
Использование метода Сообщить() — это базовый вариант, но в современных конфигурациях (особенно на управляемых формах) лучше использовать объект СообщениеПользователю. Это позволит "привязать" ошибку к конкретному полю на форме, что сделает интерфейс более дружелюбным. Разберем, как это сделать:
Если НЕ РольДоступна("СпециальнаяРоль") И ВидОперации = Перечисления.ВидыОпераций.А Тогда
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Операция 'А' доступна только пользователям с расширенными правами.";
Сообщение.Поле = "ВидОперации"; // Привязка к полю формы
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
КонецЕсли;
Рассмотрим несколько продвинутых советов, которые помогут сделать ваш код более профессиональным:
ПередЗаписью в модуле объекта сработает в любом случае.Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; в начало обработчика. Это предотвратит блокировку записи исторических данных, которые могли быть созданы до введения ограничений.РольДоступна() работает быстро, но если вы проверяете множество условий в цикле, рассмотрите возможность получения списка ролей один раз при начале сеанса и сохранения их в параметрах сеанса или функциональных опциях.Таким образом, мы выяснили, что секрет успеха заключается в четком понимании типов данных (ссылка на перечисление — это не число и не булево) и аккуратном использовании логического оператора И для связки проверки прав и значений реквизитов. Следуя этим правилам, вы сможете создавать надежные и понятные системы контроля доступа в ваших решениях на базе 1С.