При разработке в среде 1С:Предприятие 8.3 (особенно для конфигураций на обычных формах, таких как Бухгалтерия предприятия 2.0) часто возникает задача ограничить видимость определенных типов объектов в составном реквизите. Стандартные механизмы платформы не всегда позволяют сделать это гибко «из коробки», особенно если нужно скрыть типы документов только в конкретном месте, сохранив к ним доступ в остальной системе. В этой статье мы подробно разберем, как реализовать подобную фильтрацию программно.
Представим ситуацию: в табличной части документа есть реквизит с составным типом данных (например, ссылки на различные виды первичных документов). Нам необходимо сделать так, чтобы рядовой бухгалтер видел для выбора только три типа документов, а главный бухгалтер — все доступные типы. При этом важно понимать, что использование RLS (ограничение доступа на уровне записей) здесь не совсем подходит, так как оно полностью скроет объекты из системы, а нам нужно лишь отфильтровать список выбора в конкретной форме.
Рассмотрим несколько эффективных способов решения этой задачи, начиная от самого популярного и заканчивая наиболее архитектурно правильным.
Это классический и самый гибкий метод для обычных форм. Мы полностью берем управление процессом выбора на себя, отключая стандартное поведение системы. Проанализируем, как это работает по шагам.
НачалоВыбора.Разберем пример кода, который позволит нам отфильтровать список типов:
Процедура ТабличнаяЧастьРеквизитНачалоВыбора(Элемент, СтандартнаяОбработка)
// Отключаем стандартное окно выбора типа и поиска
СтандартнаяОбработка = Ложь;
// Создаем список, в котором будут только разрешенные типы
СписокРазрешенныхТипов = Новый СписокЗначений;
// Добавляем базовый набор типов, доступный всем
СписокРазрешенныхТипов.Добавить(Документы.РеализацияТоваровУслуг.ПустаяСсылка(), "Реализация товаров и услуг");
СписокРазрешенныхТипов.Добавить(Документы.ПоступлениеТоваровУслуг.ПустаяСсылка(), "Поступление товаров и услуг");
// Проверяем наличие определенной роли для расширенного списка
Если РольДоступна("ПолныеПрава") Или РольДоступна("ГлавныйБухгалтер") Тогда
СписокРазрешенныхТипов.Добавить(Документы.ОперацияБух.ПустаяСсылка(), "Ручная операция");
СписокРазрешенныхТипов.Добавить(Документы.КорректировкаДолга.ПустаяСсылка(), "Корректировка долга");
КонецЕсли;
// Вызываем диалог выбора из нашего сформированного списка
ВыбранныйЭлемент = ВыбратьИзСписка(СписокРазрешенныхТипов, Элемент);
// Если пользователь выбрал тип, присваиваем пустую ссылку этого типа в реквизит
Если ВыбранныйЭлемент <> Неопределено Тогда
Элемент.Значение = ВыбранныйЭлемент.Значение;
// Если это табличная часть, не забываем обновить текущую строку
ТекущаяСтрока = ЭлементыФормы.ТабличнаяЧасть.ТекущиеДанные;
Если ТекущаяСтрока <> Неопределено Тогда
ТекущаяСтрока.Реквизит = ВыбранныйЭлемент.Значение;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс: при таком подходе мы сразу предлагаем пользователю список типов. Если типов очень много, это может быть неудобно, но для 5–10 вариантов это идеальное решение.
Если мы хотим сохранить стандартный механизм выбора (сначала выбор типа, потом выбор конкретного документа), но ограничить сам перечень доступных типов, мы можем воспользоваться свойством ОграничениеТипа. Рассмотрим подробнее, как программно изменить состав типов при открытии формы.
Выясним причину, по которой этот метод считается более «чистым»: он не подменяет логику платформы, а лишь конфигурирует метаданные поля ввода под конкретного пользователя.
Процедура ПриОткрытии()
// Формируем массив типов, которые хотим оставить
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
МассивТипов.Добавить(Тип("ДокументСсылка.ПоступлениеТоваровУслуг"));
Если РольДоступна("СпециальныеПрава") Тогда
МассивТипов.Добавить(Тип("ДокументСсылка.АвансовыйОтчет"));
КонецЕсли;
// Создаем новое ОписаниеТипов на основании массива
НовоеОписание = Новый ОписаниеТипов(МассивТипов);
// Устанавливаем ограничение на колонку табличной части
// Обратите внимание: для обычных форм это делается через ЭлементыФормы
ЭлементыФормы.ТабличнаяЧасть.Колонки.РеквизитСоставнойТип.ЭлементУправления.ОграничениеТипа = НовоеОписание;
КонецПроцедуры
В этом случае 1С сама отфильтрует стандартное окно выбора типов, и пользователь просто не увидит «лишние» документы в списке.
На форумах часто советуют использовать РольДоступна, однако проанализируем ситуацию глубже. В крупных системах количество ролей может исчисляться сотнями. Более универсальным подходом будет проверка конкретного права. Вместо того чтобы привязываться к именам ролей, проверим, имеет ли пользователь вообще право на чтение объекта.
Рассмотрим пример использования функции ПравоДоступа:
Если ПравоДоступа("Чтение", Метаданные.Документы.КорректировкаДолга) Тогда
СписокРазрешенныхТипов.Добавить(Документы.КорректировкаДолга.ПустаяСсылка());
КонецЕсли;
Этот код более устойчив к изменениям конфигурации: если вы добавите новую роль и дадите ей права на документ, вам не придется переписывать код в форме — проверка прав сработает автоматически.
Проанализируем важный аспект: ограничение выбора не скрывает данные, которые уже были введены ранее (например, администратором). Если пользователь с ограниченными правами откроет документ, где выбран «запрещенный» тип, он его увидит. Чтобы полностью изолировать данные, используем событие ПриВыводеСтроки.
Процедура ТабличнаяЧастьПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
ТипЗначения = ТипЗнч(ДанныеСтроки.Реквизит);
// Проверяем, входит ли тип значения в список разрешенных
Если Не РазрешенныйТипДляПользователя(ТипЗначения) Тогда
ОформлениеСтроки.Ячейки.Реквизит.УстановитьТекст("<Объект недоступен>");
КонецЕсли;
КонецПроцедуры
Мы рассмотрели различные подходы к ограничению типов в составном реквизите. Основной вывод: для обычных форм 1С 8.3 наиболее эффективным является сочетание установки ОграничениеТипа при загрузке формы и дополнительной фильтрации в НачалоВыбора, если требуется сложная бизнес-логика.
Помните, что визуальное скрытие типов в интерфейсе — это не замена полноценной системе прав доступа. Если данные критичны, всегда комбинируйте интерфейсные решения с настройкой ролей и механизмов RLS на уровне метаданных.