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