REQ-2596,自动过审支持不同流程数据版本执行不同业务代码
This commit is contained in:
parent
21c4541a70
commit
872b84f1ae
@ -0,0 +1,28 @@
|
|||||||
|
package cn.axzo.workflow.core.common.utils;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SpringContentUtils {
|
||||||
|
|
||||||
|
private static SpringContentUtils.SpringContext springContext;
|
||||||
|
|
||||||
|
public SpringContentUtils(SpringContentUtils.SpringContext springContext) {
|
||||||
|
SpringContentUtils.springContext = springContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T getBean(Class<T> clazz) {
|
||||||
|
return springContext.getBean(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) {
|
||||||
|
return springContext.getBeansOfType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface SpringContext {
|
||||||
|
<T> T getBean(Class<T> var1);
|
||||||
|
|
||||||
|
<T> Map<String, T> getBeansOfType(@Nullable Class<T> type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package cn.axzo.workflow.core.conf;
|
package cn.axzo.workflow.core.conf;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.core.common.utils.SpringContentUtils;
|
||||||
import cn.axzo.workflow.core.engine.behavior.CustomActivityBehaviorFactory;
|
import cn.axzo.workflow.core.engine.behavior.CustomActivityBehaviorFactory;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomCommandContextFactory;
|
import cn.axzo.workflow.core.engine.cmd.CustomCommandContextFactory;
|
||||||
import cn.axzo.workflow.core.engine.id.BasedNacosSnowflakeIdGenerator;
|
import cn.axzo.workflow.core.engine.id.BasedNacosSnowflakeIdGenerator;
|
||||||
@ -20,19 +21,26 @@ import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
|||||||
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
||||||
import com.alibaba.cloud.nacos.NacosServiceManager;
|
import com.alibaba.cloud.nacos.NacosServiceManager;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import org.apache.ibatis.session.SqlSessionFactory;
|
||||||
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
|
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
|
||||||
import org.flowable.common.engine.impl.history.HistoryLevel;
|
import org.flowable.common.engine.impl.history.HistoryLevel;
|
||||||
import org.flowable.form.spring.SpringFormEngineConfiguration;
|
import org.flowable.form.spring.SpringFormEngineConfiguration;
|
||||||
import org.flowable.job.service.JobProcessor;
|
import org.flowable.job.service.JobProcessor;
|
||||||
import org.flowable.spring.SpringProcessEngineConfiguration;
|
import org.flowable.spring.SpringProcessEngineConfiguration;
|
||||||
import org.flowable.spring.boot.EngineConfigurationConfigurer;
|
import org.flowable.spring.boot.EngineConfigurationConfigurer;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.flowable.common.engine.impl.AbstractEngineConfiguration.DB_SCHEMA_UPDATE_TRUE;
|
import static org.flowable.common.engine.impl.AbstractEngineConfiguration.DB_SCHEMA_UPDATE_TRUE;
|
||||||
|
|
||||||
@ -105,4 +113,25 @@ public class FlowableConfiguration {
|
|||||||
return new CustomActivityBehaviorFactory();
|
return new CustomActivityBehaviorFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConditionalOnBean({SqlSessionFactory.class})
|
||||||
|
public static class SpringContext implements SpringContentUtils.SpringContext, ApplicationContextAware {
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
public SpringContext() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getBean(Class<T> clazz) {
|
||||||
|
return this.applicationContext.getBean(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type){
|
||||||
|
return this.applicationContext.getBeansOfType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
package cn.axzo.workflow.core.version;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.axzo.workflow.core.common.utils.SpringContentUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class GetSpecifiedVersionBeanUtils {
|
||||||
|
public static <T extends Versioned> T getSpecialVersionBean(Class<T> clazz, String version) {
|
||||||
|
Map<String, T> beans = SpringContentUtils.getBeansOfType(clazz);
|
||||||
|
if (CollectionUtils.isEmpty(beans)) {
|
||||||
|
throw new NullPointerException("no beans of type " + clazz.getName());
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(version)) {
|
||||||
|
//todo 版本为空,需要一个默认处理类??
|
||||||
|
}
|
||||||
|
//根据版本号排序
|
||||||
|
List<T> sortedList = beans.values().stream().sorted().collect(Collectors.toList());
|
||||||
|
DefaultArtifactVersion targetVersion = new DefaultArtifactVersion(version);
|
||||||
|
for (int i = sortedList.size() - 1; i >= 0; i--) {
|
||||||
|
int flag = sortedList.get(i).getVersion().compareTo(targetVersion);
|
||||||
|
if (flag <= 0) {
|
||||||
|
return sortedList.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NullPointerException("no beans of type " + clazz.getName() + " and version " + version);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package cn.axzo.workflow.core.version;
|
||||||
|
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
|
||||||
|
public interface Versioned {
|
||||||
|
|
||||||
|
DefaultArtifactVersion getVersion();
|
||||||
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
package cn.axzo.workflow.server.controller.listener.task;
|
package cn.axzo.workflow.server.controller.listener.task;
|
||||||
|
|
||||||
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
import cn.axzo.workflow.common.model.request.bpmn.task.ExtHiTaskSearchDTO;
|
|
||||||
import cn.axzo.workflow.core.common.context.TaskOperationContext;
|
import cn.axzo.workflow.core.common.context.TaskOperationContext;
|
||||||
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskCmd;
|
import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskCmd;
|
||||||
@ -11,22 +9,20 @@ import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler;
|
|||||||
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
import cn.axzo.workflow.core.engine.operation.DeleteProcessInstanceOperation;
|
||||||
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
|
import cn.axzo.workflow.core.listener.AbstractBpmnEventListener;
|
||||||
import cn.axzo.workflow.core.listener.BpmnTaskEventListener;
|
import cn.axzo.workflow.core.listener.BpmnTaskEventListener;
|
||||||
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
|
|
||||||
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
|
import cn.axzo.workflow.core.version.GetSpecifiedVersionBeanUtils;
|
||||||
|
import cn.axzo.workflow.server.controller.listener.task.service.CheckApproveService;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.flowable.bpmn.model.FlowElement;
|
|
||||||
import org.flowable.bpmn.model.Process;
|
import org.flowable.bpmn.model.Process;
|
||||||
import org.flowable.bpmn.model.UserTask;
|
import org.flowable.bpmn.model.UserTask;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
import org.flowable.common.engine.impl.interceptor.CommandContext;
|
||||||
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
import org.flowable.common.engine.impl.interceptor.CommandExecutor;
|
||||||
import org.flowable.engine.HistoryService;
|
|
||||||
import org.flowable.engine.RepositoryService;
|
import org.flowable.engine.RepositoryService;
|
||||||
import org.flowable.engine.RuntimeService;
|
import org.flowable.engine.RuntimeService;
|
||||||
import org.flowable.engine.TaskService;
|
import org.flowable.engine.TaskService;
|
||||||
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
import org.flowable.engine.impl.persistence.entity.ActivityInstanceEntity;
|
|
||||||
import org.flowable.engine.impl.util.CommandContextUtil;
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
import org.flowable.job.service.JobService;
|
import org.flowable.job.service.JobService;
|
||||||
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
import org.flowable.job.service.impl.persistence.entity.JobEntity;
|
||||||
@ -37,12 +33,10 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_ADVICE;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.COMMENT_TYPE_OPERATION_DESC;
|
||||||
@ -54,10 +48,8 @@ import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
|
|||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_REJECT;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_PROCESS_TYPE_REJECT;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_TASK_RELATION_ASSIGNEE_INFO;
|
||||||
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.TASK_COMPLETE_OPERATION_TYPE;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
|
import static cn.axzo.workflow.common.constant.BpmnConstants.WORKFLOW_ENGINE_VERSION;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||||
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_TASK;
|
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
|
||||||
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.REJECTED;
|
||||||
import static cn.axzo.workflow.core.common.enums.BpmnProcessTaskResultEnum.REJECTION_AUTO_COMPLETED;
|
import static cn.axzo.workflow.core.common.enums.BpmnProcessTaskResultEnum.REJECTION_AUTO_COMPLETED;
|
||||||
|
|
||||||
@ -80,7 +72,6 @@ public class AutoOperatorEvent_101_Listener extends AbstractBpmnEventListener<Ta
|
|||||||
private final TaskService taskService;
|
private final TaskService taskService;
|
||||||
private final RuntimeService runtimeService;
|
private final RuntimeService runtimeService;
|
||||||
private final RepositoryService repositoryService;
|
private final RepositoryService repositoryService;
|
||||||
private final HistoryService historyService;
|
|
||||||
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -96,9 +87,12 @@ public class AutoOperatorEvent_101_Listener extends AbstractBpmnEventListener<Ta
|
|||||||
UserTask userTask = (UserTask) mainProcess.getFlowElement(delegateTask.getTaskDefinitionKey());
|
UserTask userTask = (UserTask) mainProcess.getFlowElement(delegateTask.getTaskDefinitionKey());
|
||||||
|
|
||||||
Optional<Boolean> autoApprovalOpt = BpmnMetaParserHelper.getAutoApprovalValue(userTask);
|
Optional<Boolean> autoApprovalOpt = BpmnMetaParserHelper.getAutoApprovalValue(userTask);
|
||||||
//自动过审配置为true才执行这段代码,默认为false,老数据默认不跳过审批
|
//自动过审配置为true才执行这段代码,默认为false,老数据默认不自动过审
|
||||||
if (autoApprovalOpt.orElse(false)) {
|
if (autoApprovalOpt.orElse(false)) {
|
||||||
boolean exists = checkApproverExists(delegateTask, userTask, mainProcess);
|
Object versionVar = delegateTask.getVariable(WORKFLOW_ENGINE_VERSION);
|
||||||
|
String version = versionVar == null ? null : String.valueOf(versionVar);
|
||||||
|
CheckApproveService checkApproveService = GetSpecifiedVersionBeanUtils.getSpecialVersionBean(CheckApproveService.class, version);
|
||||||
|
boolean exists = checkApproveService.checkApproverExists(delegateTask, userTask, mainProcess, getContext());
|
||||||
log.info("是否需要自动过程判断 exists:{}", exists);
|
log.info("是否需要自动过程判断 exists:{}", exists);
|
||||||
if (exists) {
|
if (exists) {
|
||||||
taskService.addComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), COMMENT_TYPE_ADVICE,
|
taskService.addComment(delegateTask.getId(), delegateTask.getProcessInstanceId(), COMMENT_TYPE_ADVICE,
|
||||||
@ -144,72 +138,6 @@ public class AutoOperatorEvent_101_Listener extends AbstractBpmnEventListener<Ta
|
|||||||
jobService.scheduleAsyncJob(job);
|
jobService.scheduleAsyncJob(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 校验当前的审批人是否存在过前一个节点
|
|
||||||
*
|
|
||||||
* @param delegateTask
|
|
||||||
* @param userTask
|
|
||||||
* @param mainProcess
|
|
||||||
*/
|
|
||||||
private boolean checkApproverExists(DelegateTask delegateTask, UserTask userTask, Process mainProcess) {
|
|
||||||
AtomicBoolean exists = new AtomicBoolean(false);
|
|
||||||
FlowElement currentFlowElement = mainProcess.getFlowElement(delegateTask.getTaskDefinitionKey());
|
|
||||||
BpmnFlowNodeType currentNodeType = BpmnMetaParserHelper.getNodeType(currentFlowElement).orElse(NODE_EMPTY);
|
|
||||||
if (!Objects.equals(currentNodeType, NODE_TASK)) {
|
|
||||||
return exists.get();
|
|
||||||
}
|
|
||||||
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
|
||||||
processEngineConfiguration.getActivityInstanceEntityManager()
|
|
||||||
.findActivityInstancesByProcessInstanceId(delegateTask.getProcessInstanceId(), false)
|
|
||||||
.stream()
|
|
||||||
.filter(i -> !Objects.equals(i.getActivityId(), userTask.getId()))
|
|
||||||
.filter(i -> !Objects.equals(i.getActivityType(), "exclusiveGateway"))
|
|
||||||
.filter(i -> !Objects.equals(i.getActivityType(), "sequenceFlow"))
|
|
||||||
.max(Comparator.comparing(ActivityInstanceEntity::getStartTime))
|
|
||||||
.ifPresent(i -> {
|
|
||||||
// 与发起人比对
|
|
||||||
if (Objects.equals(NODE_STARTER.getType(), i.getActivityId())) {
|
|
||||||
BpmnTaskDelegateAssigner initiator = BpmnTaskDelegateAssigner.toObjectCompatible(delegateTask.getVariable(INTERNAL_INITIATOR));
|
|
||||||
if (Objects.nonNull(initiator) && initiator.comparePersonIdToOther(delegateTask.getAssignee())) {
|
|
||||||
exists.compareAndSet(false, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
FlowElement flowElement = mainProcess.getFlowElement(i.getActivityId());
|
|
||||||
BpmnMetaParserHelper.getNodeType(flowElement).ifPresent(j -> {
|
|
||||||
if (Objects.equals(NODE_TASK, j)) {
|
|
||||||
ExtHiTaskSearchDTO searchDTO = new ExtHiTaskSearchDTO();
|
|
||||||
searchDTO.setProcessInstanceId(delegateTask.getProcessInstanceId());
|
|
||||||
searchDTO.setTaskDefinitionKey(i.getActivityId());
|
|
||||||
getContext().getExtAxHiTaskInsts(() -> extAxHiTaskInstService.queryList(searchDTO))
|
|
||||||
.stream().filter(e -> Objects.equals(e.getStatus(), APPROVED.getStatus()))
|
|
||||||
.map(ExtAxHiTaskInst::getAssignee)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.filter(StringUtils::hasText)
|
|
||||||
.filter(k -> specialApproverComparison(k, delegateTask.getAssignee()))
|
|
||||||
.findAny().ifPresent(k -> exists.compareAndSet(false, true));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return exists.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 特殊审批人字段的比对, 兼容旧迭代导致的数据格式
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean specialApproverComparison(String compareAssignee, String currentAssignee) {
|
|
||||||
if (StringUtils.hasText(compareAssignee) && StringUtils.hasText(currentAssignee)) {
|
|
||||||
String[] compareSplit = compareAssignee.split("\\|");
|
|
||||||
String[] currentSplit = currentAssignee.split("\\|");
|
|
||||||
if (compareSplit.length == 2 || currentSplit.length == 2) {
|
|
||||||
return Objects.equals(compareSplit[1], currentSplit[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 如果审批人为空时, 读取 approverEmptyHandleType = 自动通过或自动驳回
|
* 如果审批人为空时, 读取 approverEmptyHandleType = 自动通过或自动驳回
|
||||||
*
|
*
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
package cn.axzo.workflow.server.controller.listener.task.service;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.core.common.context.TaskOperationContext;
|
||||||
|
import cn.axzo.workflow.core.version.Versioned;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
import org.flowable.bpmn.model.UserTask;
|
||||||
|
import org.flowable.task.service.delegate.DelegateTask;
|
||||||
|
|
||||||
|
public interface CheckApproveService extends Versioned {
|
||||||
|
boolean checkApproverExists(DelegateTask delegateTask, UserTask userTask, Process mainProcess, TaskOperationContext taskOperationContext);
|
||||||
|
}
|
||||||
@ -0,0 +1,103 @@
|
|||||||
|
package cn.axzo.workflow.server.controller.listener.task.service.impl;
|
||||||
|
|
||||||
|
import cn.axzo.workflow.common.enums.BpmnFlowNodeType;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||||
|
import cn.axzo.workflow.common.model.request.bpmn.task.ExtHiTaskSearchDTO;
|
||||||
|
import cn.axzo.workflow.core.common.context.TaskOperationContext;
|
||||||
|
import cn.axzo.workflow.core.common.utils.BpmnMetaParserHelper;
|
||||||
|
import cn.axzo.workflow.core.repository.entity.ExtAxHiTaskInst;
|
||||||
|
import cn.axzo.workflow.core.service.ExtAxHiTaskInstService;
|
||||||
|
import cn.axzo.workflow.server.controller.listener.task.service.CheckApproveService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
import org.flowable.bpmn.model.FlowElement;
|
||||||
|
import org.flowable.bpmn.model.Process;
|
||||||
|
import org.flowable.bpmn.model.UserTask;
|
||||||
|
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
|
||||||
|
import org.flowable.engine.impl.persistence.entity.ActivityInstanceEntity;
|
||||||
|
import org.flowable.engine.impl.util.CommandContextUtil;
|
||||||
|
import org.flowable.task.service.delegate.DelegateTask;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.FLOW_SERVER_VERSION_130;
|
||||||
|
import static cn.axzo.workflow.common.constant.BpmnConstants.INTERNAL_INITIATOR;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_EMPTY;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_STARTER;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnFlowNodeType.NODE_TASK;
|
||||||
|
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.APPROVED;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class CheckApproverServiceImpl implements CheckApproveService {
|
||||||
|
|
||||||
|
private final ExtAxHiTaskInstService extAxHiTaskInstService;
|
||||||
|
|
||||||
|
public boolean checkApproverExists(DelegateTask delegateTask, UserTask userTask, Process mainProcess, TaskOperationContext taskOperationContext) {
|
||||||
|
AtomicBoolean exists = new AtomicBoolean(false);
|
||||||
|
FlowElement currentFlowElement = mainProcess.getFlowElement(delegateTask.getTaskDefinitionKey());
|
||||||
|
BpmnFlowNodeType currentNodeType = BpmnMetaParserHelper.getNodeType(currentFlowElement).orElse(NODE_EMPTY);
|
||||||
|
if (!Objects.equals(currentNodeType, NODE_TASK)) {
|
||||||
|
return exists.get();
|
||||||
|
}
|
||||||
|
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
|
||||||
|
processEngineConfiguration.getActivityInstanceEntityManager()
|
||||||
|
.findActivityInstancesByProcessInstanceId(delegateTask.getProcessInstanceId(), false)
|
||||||
|
.stream()
|
||||||
|
.filter(i -> !Objects.equals(i.getActivityId(), userTask.getId()))
|
||||||
|
.filter(i -> !Objects.equals(i.getActivityType(), "exclusiveGateway"))
|
||||||
|
.filter(i -> !Objects.equals(i.getActivityType(), "sequenceFlow"))
|
||||||
|
.max(Comparator.comparing(ActivityInstanceEntity::getStartTime))
|
||||||
|
.ifPresent(i -> {
|
||||||
|
// 与发起人比对
|
||||||
|
if (Objects.equals(NODE_STARTER.getType(), i.getActivityId())) {
|
||||||
|
BpmnTaskDelegateAssigner initiator = BpmnTaskDelegateAssigner.toObjectCompatible(delegateTask.getVariable(INTERNAL_INITIATOR));
|
||||||
|
if (Objects.nonNull(initiator) && initiator.comparePersonIdToOther(delegateTask.getAssignee())) {
|
||||||
|
exists.compareAndSet(false, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FlowElement flowElement = mainProcess.getFlowElement(i.getActivityId());
|
||||||
|
BpmnMetaParserHelper.getNodeType(flowElement).ifPresent(j -> {
|
||||||
|
if (Objects.equals(NODE_TASK, j)) {
|
||||||
|
ExtHiTaskSearchDTO searchDTO = new ExtHiTaskSearchDTO();
|
||||||
|
searchDTO.setProcessInstanceId(delegateTask.getProcessInstanceId());
|
||||||
|
searchDTO.setTaskDefinitionKey(i.getActivityId());
|
||||||
|
taskOperationContext.getExtAxHiTaskInsts(() -> extAxHiTaskInstService.queryList(searchDTO))
|
||||||
|
.stream().filter(e -> Objects.equals(e.getStatus(), APPROVED.getStatus()))
|
||||||
|
.map(ExtAxHiTaskInst::getAssignee)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(StringUtils::hasText)
|
||||||
|
.filter(k -> specialApproverComparison(k, delegateTask.getAssignee()))
|
||||||
|
.findAny().ifPresent(k -> exists.compareAndSet(false, true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return exists.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特殊审批人字段的比对, 兼容旧迭代导致的数据格式
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean specialApproverComparison(String compareAssignee, String currentAssignee) {
|
||||||
|
if (StringUtils.hasText(compareAssignee) && StringUtils.hasText(currentAssignee)) {
|
||||||
|
String[] compareSplit = compareAssignee.split("\\|");
|
||||||
|
String[] currentSplit = currentAssignee.split("\\|");
|
||||||
|
if (compareSplit.length == 2 || currentSplit.length == 2) {
|
||||||
|
return Objects.equals(compareSplit[1], currentSplit[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultArtifactVersion getVersion() {
|
||||||
|
return new DefaultArtifactVersion(FLOW_SERVER_VERSION_130);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user