В процессе разработки на платформе 1С часто возникает задача ограничить права пользователей на определенные действия. Одной из таких задач является запрет создания новых документов на основании уже существующих. Даже если мы установим свойство формы ТолькоПросмотр в значение Истина, стандартные механизмы платформы все равно могут оставлять доступной кнопку Ввести на основании. В этой статье мы подробно разберем, как полностью блокировать эту возможность в обычных формах, используя различные подходы: от визуального скрытия кнопок до жесткого контроля на уровне программного кода модуля объекта.
Давайте проанализируем ситуацию: когда мы открываем форму документа и программно прописываем ЭтаФорма.ТолькоПросмотр = Истина;, платформа блокирует редактирование реквизитов и табличных частей внутри самой формы. Однако командная панель, особенно если она настроена на автозаполнение, продолжает отображать подменю Ввести на основании. Это происходит потому, что ввод на основании — это создание нового объекта, а не изменение текущего. Следовательно, с точки зрения логики прав доступа, просмотр текущего документа не запрещает использовать его данные для заполнения другого. Чтобы решить эту задачу, нам потребуется вмешаться в работу интерфейса или логику заполнения целевых документов.
Рассмотрим метод, основанный на переборе кнопок командной панели формы. Этот способ хорош тем, что он позволяет скрыть кнопку визуально, не давая пользователю даже нажать на нее. Мы можем реализовать это в процедуре ПриОткрытии формы документа-основания.
Для реализации этого метода нам необходимо обратиться к коллекции ЭлементыФормы. Проанализируем пример кода, который выполняет поиск кнопки по её тексту и отключает её доступность:
Процедура ПриОткрытии()
// Проверяем наше условие (например, роль пользователя или статус документа)
Если НужноЗапретитьВводНаОсновании Тогда
Для Каждого Кнопка Из ЭлементыФормы.ДействияФормы.Кнопки Цикл
// Ищем подменю "Ввести на основании"
// В типовых конфигурациях оно часто называется "Подменю1" или имеет заголовок "Ввести на основании"
Если Кнопка.Текст = "Ввести на основании" Или Кнопка.Имя = "ПодменюВвестиНаОсновании" Тогда
Кнопка.Доступность = Ложь;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Однако стоит учитывать, что в обычных формах структура кнопок может быть иерархической. Если кнопка находится внутри подменю, нам потребуется вложенный цикл. Давайте разберем более продвинутый вариант перебора:
// Пример для поиска внутри конкретного подменю
ИмяПодменю = "ДействияФормы"; // Уточните имя вашей командной панели
Попытка
ПодменюОснований = ЭлементыФормы[ИмяПодменю].Кнопки["Подменю1"];
Для Индекс = 0 По ПодменюОснований.Кнопки.Количество() - 1 Цикл
// Можно отключить как всё подменю целиком, так и конкретные пункты
ПодменюОснований.Кнопки[Индекс].Доступность = Ложь;
КонецЦикла;
Исключение
// Обработка случая, если кнопка не найдена
КонецПопытки;
Выясним причину, почему предыдущий способ может быть недостаточен. Пользователь может попытаться ввести документ на основании не из формы, а из списка документов (через контекстное меню). В этом случае визуальное скрытие кнопки в форме не поможет. Нам нужен более глубокий уровень контроля.
В модуле объекта документа, который создается на основании, существует событие ОбработкаЗаполнения. Проблема в том, что у этого события нет стандартного параметра Отказ. Это означает, что мы не можем просто прервать создание документа из этой процедуры. Но мы можем использовать хитрость с объектом ДополнительныеСвойства.
Рассмотрим по шагам реализацию этого механизма:
ОбработкаЗаполнения мы проверяем условия и, если ввод запрещен, записываем флаг в дополнительные свойства создаваемого объекта.ПередОткрытием мы проверяем наличие этого флага и, если он установлен, устанавливаем Отказ = Истина.Посмотрим на пример кода в модуле объекта целевого документа:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ОтчетПроизводстваЗаСмену") Тогда
// Проверяем условие в документе-основании
Если ДанныеЗаполнения.Проведен И НекоторыеУсловияЗапрета Тогда
ЭтотОбъект.ДополнительныеСвойства.Вставить("ЗапретВводаНаОсновании", Истина);
СтандартнаяОбработка = Ложь; // Отключаем стандартное заполнение
Возврат;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Теперь проанализируем код в модуле формы этого же (целевого) документа:
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
Если ЭтотОбъект.ДополнительныеСвойства.Свойство("ЗапретВводаНаОсновании") Тогда
Если ЭтотОбъект.ДополнительныеСвойства.ЗапретВводаНаОсновании = Истина Тогда
Сообщить("Ввод на основании данного документа запрещен по правилам системы!");
Отказ = Истина; // Форма не откроется, объект не будет создан
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим более радикальный интерфейсный метод. В свойствах любой командной панели в обычном приложении есть флажок Автозаполнение. Если мы снимем этот флаг, все стандартные кнопки (Печать, Заполнить, Ввести на основании и т.д.) исчезнут.
После этого мы можем вручную добавить только те кнопки, которые нам действительно нужны. Это избавляет нас от необходимости писать сложные циклы по поиску индексов кнопок. Вы просто создаете кнопку Действия (подменю) и добавляете туда только разрешенные пункты. Этот метод является самым надежным с точки зрения стабильности интерфейса, так как он не зависит от того, как платформа решит назвать кнопку Ввести на основании в следующей версии или при смене локализации.
Проанализируем ситуацию, когда запрет должен быть постоянным для определенных категорий пользователей. Если ввод на основании конкретного типа документа (например, "Перемещение") из "Отчета производства" не предусмотрен бизнес-процессом вообще, лучше всего внести изменения в дерево метаданных.
Для этого выполним следующие действия:
Если же запрет должен зависеть от прав доступа, мы можем создать отдельную роль, в которой у пользователя не будет прав на чтение документа-основания, либо использовать RLS (Record Level Security). Если пользователь не имеет прав на просмотр конкретной записи документа-основания, механизм ввода на основании не сможет получить из него данные, и система выдаст ошибку доступа.
Мы разобрали несколько методов решения задачи. Самым гибким является использование ДополнительныеСвойства в связке с процедурами ОбработкаЗаполнения и ПередОткрытием, так как это позволяет контролировать процесс программно на уровне бизнес-логики. Визуальное скрытие кнопок через ЭлементыФормы отлично подходит для оперативного управления интерфейсом "на лету". Выбор конкретного метода зависит от того, насколько жестким должен быть запрет и требуется ли его изменять динамически в зависимости от данных документа.