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