Как ограничить редактирование реквизита «Наименование» для конкретной роли в 1C?

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

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

Метод 1. Программное управление доступностью в управляемой форме

Самый очевидный способ — ограничить возможность изменения поля непосредственно в интерфейсе. Разберем ситуацию: у нас есть роль S_Пользователь, для которой нужно установить режим «Только просмотр» для элемента формы. Проанализируем наиболее эффективный код для процедуры ПриСозданииНаСервере.

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

Рассмотрим пример кода:


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

Использование свойства ТолькоПросмотр предпочтительнее, чем Доступность, так как оно позволяет пользователю выделять и копировать текст из поля, но запрещает его изменение.

Метод 2. Использование механизма «Условного оформления»

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

Разберем, как программно добавить правило оформления при создании формы:

  1. Создаем новый элемент условного оформления.
  2. Устанавливаем оформляемое поле (в нашем случае — Наименование).
  3. Задаем условие (наличие роли).
  4. Устанавливаем свойство «Только просмотр».

Посмотрим на пример реализации:


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

Метод 3. Проверка на уровне модуля объекта (защита данных)

Интерфейсные ограничения легко обойти программно или через консоль запросов. Для обеспечения надежной защиты разберем метод проверки в событии ПередЗаписью модуля справочника. Это гарантирует, что даже если пользователь попытается изменить наименование через внешнюю обработку, система не даст этого сделать.

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


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

Важный момент: использование Ссылка.Наименование инициирует дополнительный запрос к базе данных. В высоконагруженных системах это может быть критично. Если вы используете Библиотеку стандартных подсистем (БСП), лучше использовать кэшированные функции проверки ролей.

Метод 4. Подмена реквизита через форму

Рассмотрим более сложный, но «чистый» с точки зрения обновления типовых конфигураций способ. Вместо того чтобы менять свойства основного реквизита Объект.Наименование, мы можем создать вспомогательный реквизит формы (например, НаименованиеДляРедактирования).

Разберем шаги этого метода:

  1. Добавляем реквизит формы с типом Строка.
  2. На форме скрываем стандартное поле Наименование.
  3. Выводим наше новое поле.
  4. В ПриСозданииНаСервере заполняем его: НаименованиеДляРедактирования = Объект.Наименование;.
  5. В зависимости от роли устанавливаем доступность этого поля.
  6. В событии ПередЗаписьюНаСервере переносим значение обратно: Объект.Наименование = НаименованиеДляРедактирования;.

Этот метод хорош тем, что позволяет полностью контролировать поведение поля, не затрагивая системные механизмы платформы по работе с основным реквизитом Наименование.

Использование расширений для сохранения поддержки

Проанализируем современный подход к реализации данной задачи в типовых конфигурациях (УТ 11, ERP, БП 3.0). Чтобы не снимать справочник с поддержки, крайне рекомендуется использовать Расширения конфигурации.

Мы можем создать расширение и добавить в него процедуру-перехватчик &После для метода ПриСозданииНаСервере формы справочника. Это позволит внедрить наш код, не меняя основную конфигурацию. Посмотрим на пример в расширении:


&ИзменениеИКонтроль("ПриСозданииНаСервере")
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Используем функции БСП для проверки ролей
    Если Пользователи.РолиДоступны("S_Пользователь") Тогда
        Элементы.Наименование.ТолькоПросмотр = Истина;
    КонецЕсли;
    
КонецПроцедуры

Рекомендации по оптимизации

В завершение разберем несколько советов, которые помогут сделать решение более профессиональным:

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

← На главную