Функции бизнес-просесса
Вы можете добавлять пользовательские условия/валидаторы/постфукнции для бизнесс-процессов.
Условие
Позволяют скрыть переход.
Внимание
метод WorkflowCondition.execute будет вызываться очень часто, поэтому если у вас очень сложная логика, лучше используйте WorkflowValidator
Для реализации условий реализуйте интерфейс ru.slie.luna.issue.workflow.condition.WorkflowCondition
package ru.slie.luna.issue.workflow.condition;
import org.springframework.stereotype.Component;
import ru.slie.luna.exception.ValidateException;
import ru.slie.luna.group.Group;
import ru.slie.luna.group.GroupManager;
import ru.slie.luna.issue.workflow.WorkflowTransientVars;
import ru.slie.luna.issue.workflow.annotations.WorkflowFunctionComponent;
import ru.slie.luna.locale.I18nResolver;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Component
public class UserInGroupCondition implements WorkflowCondition {
private final I18nResolver i18n;
private static final String IN_GROUP = "inGroup";
private final GroupManager groupManager;
public UserInGroupCondition(I18nResolver i18n,
GroupManager groupManager) {
this.i18n = i18n;
this.groupManager = groupManager;
}
@Override
public boolean execute(WorkflowTransientVars transientVars, Map<String, String> params) {
if (transientVars.getUser() == null) {
return false;
}
if (params.containsKey(IN_GROUP) && params.get(IN_GROUP) != null) {
return transientVars.getUser().getGroups().contains(params.get(IN_GROUP));
}
return false;
}
@Override
public String getName() {
return i18n.getText("app.workflow.condition.user_in_group.label");
}
@Override
public String getDescription() {
return i18n.getText("app.workflow.condition.user_in_group.description");
}
/**
* Если добавите форму с настройками, этот метод используется для валидации параметров с формы
*/
@Override
public void validateParams(Map<String, String> params) throws ValidateException {
if (params.containsKey(IN_GROUP) && params.get(IN_GROUP) != null) {
Optional<Group> group = groupManager.getByName(params.get(IN_GROUP));
if (group.isEmpty()) {
i18n.getText("app.workflow.condition.user_in_group.group_required");
}
} else {
throw new ValidateException(IN_GROUP, i18n.getText("app.workflow.condition.user_in_group.group_required"));
}
}
/**
* Можете добавить свой компонент, для отображения в списке функций, иначе будет использоваться название постфукнции
* Данные с этого метода попадут в ваш кастомный компонент
*/
@Override
public Map<String, Object> getParamsForView(Map<String, String> params) {
Map<String, Object> out = new HashMap<>();
out.put(IN_GROUP, params.get(IN_GROUP));
return out;
}
/**
* Можно ли повторно использовать на одном переходе
*/
@Override
public boolean isAllowMultiple() {
return true;
}
}Валидатор
Реализация похожа на WorkflowCondition. Разница в том что метод execute должен вызвать ошибку ValidateException. В качестве ключа используйте id поля
public class CommentRequiredValidator implements WorkflowValidator {
...
// Для примера можем проверить наличие комментария
@Override
public void execute(WorkflowTransientVars transientVars, Map<String, String> funcParams) throws ValidateException {
if (transientVars.getRequestParams() == null || !transientVars.getRequestParams().containsKey(IssueFieldConstants.COMMENT)) {
throw new ValidateException(IssueFieldConstants.COMMENT, "Комментарий обязателен");
}
}
// Если заранее знаем какие поля обязательны, можем передать это на форму
@Override
public List<String> getRequiredFields(WorkflowTransientVars transientVars, Map<String, String> funcParams) {
return List.of(IssueFieldConstants.COMMENT);
}
...
}Постфункция
Если надо что-то выполнить после изменения задачи, используем постфукнции. Все постфункции выполняются в том порядке, в котором они расположены на переходе. Вы можете менять порядок в редакторе бизнес-процесса.
Для создания постфункций, реализуйте интерфейс: WorkflowFunction
Фронтенд
Если вашей функции нудны настройки, создайте vue-компонент:
<script setup lang="ts">
import { PropType } from 'vue'
import { Errors, Option, groupService, SingleSelect } from "luna";
defineProps({
errors: Object as PropType<Errors>,
})
type Params = {[key: string]: string}
const value = defineModel<Params>();
const groupOptions = async (term: string, excludes: Array<string>) => {
const {data} = await groupService.findGroups({term}, excludes);
return data.results.map(g => ({id: g.name, name: g.name} as Option<string>));
}
</script>
<template>
<div class="form compact user-in-group-condition-component pad">
<div class="field-group">
<label for="user-in-group-condition-role">{{ $i18n.t("The current user must be a member of the group") }}</label>
<SingleSelect :options="groupOptions" v-model="value.inGroup"></SingleSelect>
<div class="error" v-if="errors['inGroup']">{{ errors['inGroup'] }}</div>
</div>
</div>
</template>
<style lang="scss">
</style><script setup lang="ts">
import { PropType } from 'vue'
import { WorkflowActionFunction } from "luna";
defineProps({
func: {
required: true,
type: Object as PropType<WorkflowActionFunction>,
},
viewParams: {
required: true,
type: Object as PropType<{inGroup: string}>,
}
})
</script>
<template>
<div class="user-in-group-condition">
<div>{{ $i18n.t("User in group") }}: {{ viewParams.inGroup }}</div>
</div>
</template>Информация
Если вам надо доп информация в компоненте редактирования:
import { inject } from 'vue';
import { Injections } from 'luna';
const action = inject(Injections.workflowAction); // Информация о переходе
const funcType = inject(Injections.workflowFuncType); // Тип функции(условие/валидатор/постфункция)
const actionFunc = inject(Injections.workflowActionFunc); // Информация о текущей функцииДескриптор
workflowConditions:
- key: UserInGroupCondition
name: User in group condition
className: ru.slie.luna.issue.workflow.condition.UserInGroupCondition
viewComponent:
path: frontend/UserInGroupEditComponent.js
editComponent:
path: frontend/UserInGroupViewComponent.js
workflowValidators:
- key: CommentRequiredValidator
name: Comment required validator
className: ru.slie.luna.issue.workflow.validator.CommentRequiredValidator
workflowPostfunctions:
- key: MyCustomPostfunction
name: My custom postfunction
className: ru.slie.luna.issue.workflow.postfunction.MyCustomPostfunction