Как настроить отбор пользователей по группе доступа в 1С 8.3

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

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

Способ 1. Программное заполнение списка выбора (Режим выбора из списка)

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

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

В модуле управляемой формы пропишем следующий код:


&НаКлиенте
Процедура ИмяРеквизитаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    // Отменяем стандартное открытие формы выбора справочника
    СтандартнаяОбработка = Ложь;
    
    // Очищаем старые элементы списка выбора перед заполнением
    Элемент.СписокВыбора.Очистить();
    
    // Получаем массив пользователей определенной группы с сервера
    ЧленыГруппы = ПолучитьСписокГруппыНаСервере("НазваниеВашейГруппы");
    
    Если ЧленыГруппы <> Неопределено И ЧленыГруппы.Количество() > 0 Тогда
        Для Каждого Пользователь Из ЧленыГруппы Цикл
            Элемент.СписокВыбора.Добавить(Пользователь);
        КонецЦикла;
    КонецЕсли;

КонецПроцедуры

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

КонецФункции

Важное предупреждение: При использовании свойства РежимВыбораИзСписка = Истина разработчики часто сталкиваются с неприятным поведением платформы. При повторном открытии формы или после проведения документа выбранное значение визуально исчезает из поля ввода, хотя физически оно записано в базу данных. Выясним причину этого поведения.

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

  1. Инициализировать и заполнять СписокВыбора элементов формы заранее на сервере — например, в обработчике события ПриСозданииНаСервере или ПриЧтенииНаСервере.
  2. Отказаться от жесткой установки свойства РежимВыбораИзСписка. Вместо этого можно вызывать всплывающий список программно с помощью метода ПоказатьВыборИзСписка на клиенте, передавая туда временный объект типа СписокЗначений.

Способ 2. Открытие кастомной формы выбора с передачей параметров

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

Для начала создадим в справочнике Пользователи вспомогательную форму выбора (например, с именем ФормаВыбораПоГруппе) и настроим в ней динамический список с произвольным запросом. В качестве текста запроса динамического списка укажем следующее соединение:


ВЫБРАТЬ
    СправочникПользователи.Ссылка КАК Ссылка,
    СправочникПользователи.ПометкаУдаления КАК ПометкаУдаления,
    СправочникПользователи.Наименование КАК Наименование,
    СправочникПользователи.Недействителен КАК Недействителен
ИЗ
    Справочник.ГруппыДоступа.Пользователи КАК ГруппыДоступаПользователи
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Пользователи КАК СправочникПользователи
        ПО ГруппыДоступаПользователи.Пользователь = СправочникПользователи.Ссылка
ГДЕ
    ГруппыДоступаПользователи.Ссылка = &ГруппаДоступа

Теперь нам нужно передать значение параметра &ГруппаДоступа из нашей основной формы при открытии этой вспомогательной формы выбора. Сделаем это в обработчике начала выбора реквизита на клиенте:


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

КонецПроцедуры

Чтобы динамический список на открываемой форме отреагировал на переданный параметр, в модуле созданной формы выбора в обработчике ПриСозданииНаСервере необходимо связать параметр запроса с переданным параметром формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартныйПакет)
    
    // Проверяем, передан ли параметр из вызывающей формы
    Если Параметры.Свойство("ГруппаДоступа") Тогда
        // Устанавливаем параметр динамического списка "Список"
        Список.Параметры.УстановитьЗначениеПараметра("ГруппаДоступа", Параметры.ГруппаДоступа);
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Использование стандартной формы выбора и Фиксированных настроек (Best Practice)

Предыдущие способы имеют свои недостатки: создание кастомных форм увеличивает нагрузку при поддержке и обновлении конфигурации, а простые запросы к табличной части Справочник.ГруппыДоступа.Пользователи не учитывают иерархическую структуру современных конфигураций 1С на базе БСП (Библиотеки Стандартных Подсистем).

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

Чтобы избежать этой ошибки и не создавать лишние кастомные формы в конфигураторе, задействуем механизм ФиксированныеНастройки компоновки данных динамического списка стандартной формы выбора, а состав пользователей будем получать через регистр сведений СоставыГруппПользователей.

Реализуем этот надежный метод по шагам.

Шаг 1. Напишем на сервере функцию, которая извлечет абсолютно всех актуальных пользователей группы доступа с учетом вложенности групп и отсечет недействительных или помеченных на удаление сотрудников:


&НаСервереБезКонтекста
Функция ПолучитьМассивПользователейГруппыДоступа(ГруппаДоступа)
    
    МассивПользователей = Новый Массив;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗЛИЧНЫЕ
        |	СоставыГруппПользователей.Пользователь КАК Пользователь
        |ИЗ
        |	Справочник.ГруппыДоступа.Пользователи КАК ГруппыДоступаПользователи
        |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.СоставыГруппПользователей КАК СоставыГруппПользователей
        |			ПО (СоставыГруппПользователей.ГруппаПользователей = ГруппыДоступаПользователи.Пользователь
        |				ИЛИ ГруппыДоступаПользователи.Пользователь = СоставыГруппПользователей.Пользователь)
        |ГДЕ
        |	ГруппыДоступаПользователи.Ссылка = &ГруппаДоступа
        |	И НЕ СоставыГруппПользователей.Пользователь.ПометкаУдаления
        |	И НЕ СоставыГруппПользователей.Пользователь.Недействителен";
        
    Запрос.УстановитьПараметр("ГруппаДоступа", ГруппаДоступа);
    РезультатЗапроса = Запрос.Выполнить();
    
    Если Не РезультатЗапроса.Пустой() Тогда
        МассивПользователей = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Пользователь");
    КонецЕсли;
    
    Возврат МассивПользователей;
    
КонецФункции

Шаг 2. В обработчике начала выбора поля ввода на клиенте сформируем настройки компоновки данных для стандартной формы выбора справочника пользователей:


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

Использование этого метода является наиболее гибким и современным стандартом разработки в среде 1С. Мы не создаем новые формы в дереве метаданных конфигурации, не нарушаем поддержку БСП и гарантируем корректное отображение пользователей вне зависимости от того, как именно они добавлены в группу доступа — напрямую или через промежуточные группы пользователей.

← На главную