Как в обычном приложении 1С открывать управляемую форму только для определенных пользователей?

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

В процессе постепенного перевода конфигураций 1С с обычных форм на управляемые (УФ) часто возникает задача «мягкого» внедрения. Нам необходимо, чтобы рядовые пользователи продолжали работать в привычном интерфейсе, в то время как администраторы или разработчики могли уже сейчас тестировать и использовать новые управляемые формы. Разберем, как реализовать этот механизм, какие подводные камни нас ждут и как правильно передать данные между формами разных типов.

Анализ ситуации: почему стандартные механизмы могут не сработать

В платформе 1С существует стандартное событие менеджера объекта — ОбработкаПолученияФормы. На первый взгляд, это идеальное место для подмены формы. Мы могли бы прописать логику выбора там, и платформа сама бы подставляла нужную форму. Однако здесь есть важное ограничение: это событие не работает в толстом клиенте в режиме обычного приложения при стандартном открытии (например, из формы списка через двойной клик). Платформа в этом режиме ориентируется на формы, указанные как «основные» в метаданных, и игнорирует перехват в менеджере для обычных форм.

Проанализируем ситуацию: если наше основное приложение — обычное, то единственным надежным местом для перехвата остается событие ПередОткрытием самой обычной формы, которая назначена формой объекта по умолчанию.

Реализация перехвата в событии ПередОткрытием

Рассмотрим основной алгоритм действий. Когда пользователь пытается открыть документ, сначала инициализируется обычная форма. В её модуле мы проверяем, кто именно открывает объект. Если это администратор, мы программно вызываем управляемую форму, а открытие текущей обычной формы отменяем с помощью параметра Отказ.

Посмотрим на пример базового кода в модуле обычной формы документа:


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

Обработка новых объектов и копирования данных

Ситуация усложняется, когда мы создаем новый документ или копируем существующий. В обычном приложении объект создается в памяти, и нам нужно передать накопленные в нем данные (например, после обработки Заполнение или ПриКопировании) в новую управляемую форму. Если просто вызвать ПолучитьФорму, мы можем получить пустую форму, не связанную с текущим контекстом ЭтотОбъект.

Разберем по шагам, как корректно передать данные реквизитов и табличных частей. Для этого нам придется вручную перенести значения из ЭтотОбъект (Обычная форма) в данные управляемой формы.

Пример расширенного кода для нового объекта в событии ПередОткрытием:


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

Важный нюанс: при переносе данных через ЗаполнитьЗначенияСвойств важно помнить, что в управляемой форме основным реквизитом является Объект. Поэтому мы обращаемся именно к ФормаУФ.Объект.

Оптимизация: использование ролей вместо имен пользователей

Проанализируем практику проверки Наименование = "Администратор". Это крайне ненадежный метод (так называемый "хардкод"). Если в базе появится второй администратор или первый сменит имя, код перестанет работать.

Выясним, как сделать это профессионально. Рекомендуется создать в конфигурации специальную роль, например, ИспользоватьУправляемыеФормы. Тогда проверка в коде станет универсальной и гибкой:


Если РольДоступна("ПолныеПрава") Или РольДоступна("ИспользоватьУправляемыеФормы") Тогда
    // Логика подмены формы
КонецЕсли;

Почему не стоит забывать про ввод на основании?

При вводе на основании данные в ЭтотОбъект попадают еще до открытия формы. Если вы используете вышеописанный метод с ручным копированием реквизитов, убедитесь, что вы обрабатываете все табличные части. Однако есть более изящный способ: использование параметров формы.

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

Критически важные настройки

Чтобы управляемые формы вообще могли открываться внутри обычного интерфейса, необходимо убедиться, что в свойствах конфигурации включен флаг «Использовать управляемые формы в обычном приложении».

Также стоит помнить о следующих моментах:

  1. Модальность: Управляемые формы в обычном приложении могут вести себя иначе в плане блокировки окон. Проверяйте, как закрывается форма и возвращаются ли данные, если она открыта для выбора.
  2. Контекст: При программном открытии УФ из обычной формы, владельцем формы (параметр Владелец) по умолчанию будет являться та обычная форма, которую мы закрываем через Отказ = Истина. Это может привести к потере связи, если вызывающая форма (например, форма списка) ждет оповещения. В таких случаях передавайте владельца явно в метод ПолучитьФорму.
  3. Производительность: Ручной перебор метаданных для копирования реквизитов (как предлагалось в некоторых сообщениях форума) работает медленнее, чем прямое обращение или использование ЗаполнитьЗначенияСвойств. Постарайтесь избегать вложенных циклов по метаданным в процедурах открытия форм.

Таким образом, мы выяснили, что наиболее эффективный путь реализации данной задачи в гибридном режиме — это точечный перехват в событии ПередОткрытием обычной формы с последующим программным заполнением данных управляемой формы для новых объектов.

← На главную