Пользовательская задача

Назначение одного пользователя

Чтобы указать исполнителя задачи, используйте один из следующих вариантов в раскрывающемся списке Assignee source на панели свойств:

single assignee

Выражение

Вам будет нужно написать выражение для анализа имени пользователя-исполнителя. Например, если сущность User хранится в переменной процесса с именем manager, выражение будет иметь вид ${manager.username}. Если вы хотите назначить задачу конкретному пользователю, можно сразу написать его имя.

Кроме того, можно вызвать метод бина Spring, который возвращает имя пользователя: ${smpl_MyBean.evaluateManager(methodParam1, 'methodParam2')}.

Переменная процесса

Если выбрать источник исполнителей Process variable, на панели свойств появится компонент ComboBox. В этом поле отображаются поля и переменные процесса, которые относятся к типу Entity, а их класс сущности реализует интерфейс UserDetails.

Для назначения задач при моделировании процесса доступна встроенная переменная процесса initiator. Она содержит сущность пользователя, запустившего процесс.

Вы можете отключить переменную процесса initiator, используя следующее свойство:

jmix.bpm.process-initiator-variable-enabled=false

Также вы можете изменить имя свойства initiator:

jmix.bpm.process-initiator-variable-name=manager

Когда процесс запускается без использования процессной формы запуска, значения переменных процесса могут быть переданы с помощью API. В этом случае, если вам нужно назначить пользователю задачу из одной из переменных процесса, вы можете либо написать явное выражение для исполнителя, либо добавить информацию о переменной процесса в раздел Process variables.

Провайдер пользователей

Если исполнитель определяется во время выполнения, вы можете использовать провайдера пользователей – бины Spring с аннотацией @UserProvider. Эта аннотация имеет два атрибута:

  • value - имя, которое будет отображаться в моделере.

  • description - пояснение назначения метода, опционально.

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

@UserProvider(value = "smpl_MyUserProvider", description = "Returns a user with the specified email")
public class MyUserProvider {

    @Autowired
    private DataManager dataManager;

    public String getUserByEmail(String parameter) {
        return dataManager.load(User.class)
                .query("select u from smpl_User u where u.email = :email")
                .parameter("email", parameter)
                .one()
                .getUsername();
    }
}

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

provider

Обратите внимание на флажок is var. В основном он применяется для строковых параметров. Если флажок не установлен, то значение аргумента будет записано в результирующее выражение в апострофах. Если флажок установлен, апострофы добавляться не будут, и в метод будет передана переменная с заданным именем.

Многоэкземплярные задачи

Пользовательская задача может быть назначена нескольким пользователям. Например, вам нужно несколько человек для утверждения задачи. Они могут работать параллельно или друг за другом. Обратитесь к документацию Flowable за основными сведениями.

Давайте рассмотрим элемент userTask в XML модели процесса:

<userTask id="myTask" name="My Task" flowable:assignee="${assignee}">
  <multiInstanceLoopCharacteristics isSequential="true"
     flowable:collection="${collectionVariable}" flowable:elementVariable="assignee" >
  </multiInstanceLoopCharacteristics>
</userTask>

При моделировании процесса потребуется заполнить выражение для поля collection элемента multiInstanceLoopCharacteristics и поля elementVariable. После этого значение elementVariable будет использоваться в качестве назначенного исполнителя для элемента userTask.

BPM моделер поможет вам заполнить все эти атрибуты при наличии у вас списка пользователей в переменной процесса. На панели свойств у элемента модели User Task есть раздел Multi instance. При изменении типа многоэкземплярности с None на Parallel или Sequential на панели появляются новые поля.

Предположим, что в процессной форме запуска вы определили поле approvers с типом Entity list, а класс сущности реализует интерфейс UserDetails, например User. Это значение поля содержит коллекцию пользователей. Для текущей пользовательской задачи вы можете выбрать источник коллекции Process variable, а затем выбрать поле approvers в Process variable.

multi instance

В этом случае система предложит автоматически заполнить поля collection, elementVariable и assignee.

collection

Пользователи и группы-кандидаты на задачи

Вы можете указать список потенциальных исполнителей для пользовательской задачи (см. документацию Flowable). Задача с кандидатами отображается на экране My tasks в списке Group tasks для каждого кандидата. После того как любой из кандидатов берет задачу себе, она перемещается в список Assigned tasks этого пользователя, и исчезает из списка Group tasks других кандидатов.

Кандидаты определяются с помощью полей Candidate groups или Candidate users на панели свойств пользовательской задачи.

В диалоге Candidate groups edit можно определить одно из следующих значений Group source:

  • User groups. Вы можете выбрать одну или несколько групп пользователей из списка. Дополнительную информацию см. в разделе Группы пользователей.

  • User groups provider. Используйте этот тип, если группы должны быть анализированы программно. Тогда следует выбрать бин Spring с аннотацией @UserGroupListProvider. Эта аннотация имеет два атрибута:

    • value - имя, которое будет отображаться в моделере.

    • description - пояснение назначения метода, опционально.

    Бин должен реализовать один или несколько методов с возвращаемым типом List<String>. Метод получает значения параметров, указанные в моделере, и возвращает список кодов групп пользователей.

  • Expression. Вы должны предоставить выражение, используемое механизмом процесса. Выражение должно возвращать список кодов групп пользователей. Он будет записан в flowable:candidateGroups атрибут userTask элемента.

В диалоге Candidate users edit можно определить одно из следующих значений User source:

  • Users. Вы можете выбрать одного или нескольких пользователей из списка.

  • Users provider. Используйте этот тип, если список пользователей должен быть анализирован программно. Тогда следует выбрать бин Spring с аннотацией @UserListProvider. Эта аннотация имеет два атрибута:

    • value - имя, которое будет отображаться в моделере.

    • description - пояснение назначения метода, опционально.

    Бин должен реализовать один или несколько методов с возвращаемым типом List<String>. Метод получает значения параметров, указанные в моделере, и возвращает список имен пользователей.

  • Expression. Вы должны предоставить выражение, используемое механизмом процесса. Выражение должно возвращать список имен пользователей. Он будет записан в flowable:candidateUsers атрибут userTask элемента.

Выходы пользовательской задачи

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

Для процессных форм экрана Jmix выходы определяются в контроллере экрана. Для процессных форм диалогового окна ввода выходы определяются в разделе Outcomes панели свойств.

panel outcomes

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

complete task

Когда пользователь нажимает одну из кнопок выхода, задача завершается, и решение записывается в специальную переменную процесса, имя которой строится по следующему шаблону: <user-task-id>_result. Значение переменной содержит информацию о пользователях, выполнивших задачу, и выбранных ими выходах.

После установки выходов для задачи вам необходимо указать условия для потоков операций после элемента-исключающего шлюза. Вы можете написать выражение условия или выбрать выход из выпадающего списка.

Давайте рассмотрим пример настройки потока операций. Задача Approve – многоэкземплярная.

multi instance task

Чтобы указать условия для потока операций approved, выберите ее на холсте и настройте ее свойства:

flow conditions
  1. Измените Condition source на User task outcome и выберите задачу и ее выход в выпадающих списках. Также можно выбрать Expression как источник условий.

  2. Так как пользовательская задача является многоэкземплярной, необходимо указать дополнительный параметр — Condition type. В нашем случае процесс продолжит выполнение с использованием данного потока операций только в том случае, если все параллельные утверждающие исполнители завершили задачу с выходом approve.

Панель свойств расширения

Моеделер предоставляет для пользовательских задач дополнительную панель Extension properties. Она также доступна для элементов сервисной задачи и задачи-сценария.

priority panel

Вы можете определить свойства с типом значений String, а затем использовать их внутри контроллеров экранов и служб с помощью метода getElementExtensionProperties.

В приведенном ниже примере нами отображено свойство Priority, определенное в панели Extension properties пользовательской задачи внутри процессной формы:

@Autowired
private ProcessFormContext processFormContext;

@Autowired
private BpmModelService bpmModelService;

@Autowired
private TextField<String> priority;

@Subscribe
public void onInit(InitEvent event) {
    String processDefinitionId = processFormContext.getTask().getProcessDefinitionId(); (1)
    String elementId = processFormContext.getTask().getTaskDefinitionKey();

    String priorityValue = bpmModelService.getElementExtensionProperties(processDefinitionId, elementId)
            .get(0)
            .getValue(); (2)

    priority.setValue(priorityValue); (3)
}
1 Получает processDefinitionId и elementId от объекта processFormContext.
2 Получает значение свойства.
3 Заполняется со значением TextField.

Открытая форма может выглядеть следующим образом:

priority form