При настройке прав доступа в конфигурации «Управление производственным предприятием 1.3» разработчики нередко сталкиваются с задачей: необходимо, чтобы при оформлении конкретного документа (например, ЗаказПокупателя) пользователь мог выбирать только определенные организации или склады, но при этом сохранялся общий доступ к остальным документам и справочникам. Попытка настроить ограничение на уровне записей (RLS) непосредственно на реквизит документа или форму выбора приводит к трудностям. Разберем по шагам, почему механизм RLS не подходит для точечной фильтрации выбора в одной форме и как корректно решить эту задачу программными средствами обычных форм.
Проанализируем принцип работы механизма RLS (Record-Level Security) в платформе 1С:
Организации через RLS, пользователь перестанет видеть запрещенные организации во всей системе. В существующих документах, отчетах и регистрах вместо наименования организации платформа будет отображать <Объект не найден>, что нарушит корректное проведение документов и построение аналитики.NULL, что приведет к системным ошибкам при проведении и контроле заполнения.Таким образом, если цель состоит в том, чтобы урезать доступный перечень организаций исключительно в момент интерактивного ввода в документе ЗаказПокупателя, механизм RLS использовать нельзя. Эту задачу необходимо решать на уровне интерфейса формы в сочетании с проверкой в модуле объекта.
Рассмотрим основной способ ограничения выбора в обычных формах. Для этого переопределим стандартное поведение поля ввода при нажатии на кнопку выбора.
Откроем форму документа, перейдем в свойства элемента управления (поля ввода) Организация и назначим обработчик для события НачалоВыбора. В процедуре отключим стандартную обработку и откроем форму выбора справочника с наложенным программным отбором:
Процедура ОрганизацияНачалоВыбора(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем массив или список разрешенных организаций
СписокРазрешенныхОрганизаций = Новый СписокЗначений;
СписокРазрешенныхОрганизаций.Добавить(Константы.ОсновнаяОрганизация.Получить());
// Получаем форму выбора, указывая текущий элемент в качестве владельца
ФормаВыбора = Справочники.Организации.ПолучитьФормуВыбора(, Элемент);
// Настраиваем отбор по полю Ссылка
ФормаВыбора.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВСписке;
ФормаВыбора.Отбор.Ссылка.Значение = СписокРазрешенныхОрганизаций;
ФормаВыбора.Отбор.Ссылка.Использование = Истина;
ФормаВыбора.Открыть();
КонецПроцедуры
Обратите внимание: передача параметра Элемент в метод ПолучитьФормуВыбора назначает поле ввода владельцем формы. Благодаря этому при двойном клике по строке в открывшемся списке выбранное значение автоматически подставится в реквизит документа.
Если список доступных организаций или складов состоит из небольшого числа позиций, удобнее перевести поле ввода в режим выпадающего списка. Посмотрим, как это реализовать:
КнопкаСписка и РежимВыбораИзСписка.ПриОткрытии формы документа программно заполним свойство СписокВыбора элемента управления.
Процедура ПриОткрытии()
// Заполняем выпадающий список только разрешенными организациями
ЭлементыФормы.Организация.СписокВыбора.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Организации.Ссылка КАК Организация
|ИЗ
| Справочник.Организации КАК Организации
|ГДЕ
| НЕ Организации.ПометкаУдаления";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Здесь можно применить собственную логику проверки прав пользователя
ЭлементыФормы.Организация.СписокВыбора.Добавить(Выборка.Организация);
КонецЦикла;
КонецПроцедуры
Выясним частые ошибки, которые возникают при реализации подобной логики:
Справочники.Организации.НайтиПоНаименованию("...") крайне нежелательно. При малейшем изменении наименования (лишний пробел, смена названия юрлица) код перестанет находить элемент. Для хранения предопределенных настроек следует использовать константы, параметры сеанса или специализированные регистры сведений.НачалоВыбора отбор. Чтобы это предотвратить, отключите возможность редактирования текста в поле ввода либо обрабатывайте событие ОкончаниеВводаТекста.Любые интерфейсные ограничения в форме действуют только при ручном выборе пользователем. Они не защищают от ввода документов на основании, программной загрузки данных или групповых обработок. Поэтому проверку допустимости выбранных значений необходимо дублировать в модуле объекта документа ЗаказПокупателя в процедуре ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем заполнение организации в соответствии с правами пользователя
Если Не ЭтоНовый() И Не РольДоступна("ПолныеПрава") Тогда
// Проверяем, входит ли Организация в список разрешенных для ТекущегоПользователя
Если Не ОрганизацияРазрешенаДляПользователя(Организация, ПараметрыСеанса.ТекущийПользователь) Тогда
Сообщить("У вас нет прав для оформления заказа от организации: " + Организация, СтатусСообщения.Важное);
Отказ = Истина;
Возврат;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Такой комплексный подход обеспечивает корректное отображение списка выбора в интерфейсе и гарантирует целостность бизнес-логики без необходимости переписывать глобальные шаблоны RLS конфигурации.