Kaynağa Gözat

新增自定义流程属性-并行/串行会签驳回

wangliang 3 yıl önce
ebeveyn
işleme
265b7dd9a3

+ 2 - 1
distributed-print-business/src/main/java/com/qmth/distributed/print/business/activiti/custom/service/AbstractMultiWorkFlowService.java

@@ -19,7 +19,6 @@ import org.springframework.beans.BeanUtils;
 import javax.annotation.Resource;
 import java.text.MessageFormat;
 import java.util.StringJoiner;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * @Description: 并行/串行业务service
@@ -75,6 +74,7 @@ public abstract class AbstractMultiWorkFlowService implements DefaultInstanceCon
     public UserTask createMultiInstanceBehavior(UserTask userTask, boolean sequential) {
         String id = userTask.getId().substring(userTask.getId().length() - 1, userTask.getId().length());
         MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = this.createMultiInstanceLoopCharacteristics(id, sequential);
+        multiInstanceLoopCharacteristics.setCompletionCondition("${nrOfCompletedInstances/nrOfInstances == 1 || reject == 1}");
         userTask.setAssignee(new StringJoiner("").add(MessageFormat.format("{0}{1}{2}", ASSIGNEE_USER_EXP, id, EXP_SUFFIX)).toString());
         userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
         return createMultiInstanceBehavior(userTask, sequential, new StringJoiner("").add(MessageFormat.format("{0}{1}{2}", DEFAULT_ASSIGNEE_LIST_EXP, id, EXP_SUFFIX)).toString(), new StringJoiner("").add(MessageFormat.format("{0}{1}", ASSIGNEE_USER, id)).toString());
@@ -100,6 +100,7 @@ public abstract class AbstractMultiWorkFlowService implements DefaultInstanceCon
         //设置表达式变量
         behavior.setCollectionExpression(expressionManager.createExpression(assigneeListExp));
         behavior.setCollectionElementVariable(assignee);
+//        behavior.setCompletionConditionExpression();
         return userTask;
     }
 

+ 7 - 0
distributed-print-business/src/main/java/com/qmth/distributed/print/business/activiti/custom/service/impl/MultiWorkFlowService.java

@@ -14,6 +14,13 @@ import org.springframework.stereotype.Service;
 @Service
 public class MultiWorkFlowService extends AbstractMultiWorkFlowService {
 
+    /**
+     * 创建多实例行为解释器
+     *
+     * @param userTask
+     * @param sequential
+     * @return
+     */
     @Override
     public UserTask createMultiInstanceLoopCharacteristics(UserTask userTask, boolean sequential) {
         return createMultiInstanceBehavior(userTask, sequential);

+ 84 - 46
distributed-print-business/src/main/java/com/qmth/distributed/print/business/service/impl/ActivitiServiceImpl.java

@@ -3,6 +3,7 @@ package com.qmth.distributed.print.business.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
 import com.qmth.boot.api.exception.ApiException;
 import com.qmth.distributed.print.business.activiti.custom.service.DefaultInstanceConvertToMultiInstance;
 import com.qmth.distributed.print.business.activiti.custom.service.MultiWorkFlow;
@@ -33,6 +34,7 @@ import org.activiti.engine.RepositoryService;
 import org.activiti.engine.RuntimeService;
 import org.activiti.engine.TaskService;
 import org.activiti.engine.impl.RepositoryServiceImpl;
+import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
 import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
 import org.activiti.engine.repository.Deployment;
 import org.activiti.engine.repository.DeploymentBuilder;
@@ -197,8 +199,9 @@ public class ActivitiServiceImpl implements ActivitiService {
         String id = (String) map.get(SystemConstant.ID);
         BpmnModel model = (BpmnModel) map.get(SystemConstant.MODEL);
         Map flowProcessVarMap = (Map) map.get(SystemConstant.FLOW_PROCESS_VAR_MAP);
+        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
         Map<String, Object> varMap = new HashMap<>();
-        flowProcessVarMap.forEach((k, v) -> {
+        agginessMap.forEach((k, v) -> {
             if (v instanceof CustomFlowVarDto) {
                 CustomFlowVarDto customFlowVarDto = (CustomFlowVarDto) v;
                 varMap.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), s -> customFlowVarDto.getApproveIds().size() == 1 ? customFlowVarDto.getApproveIds().get(0) : customFlowVarDto.getApproveIds());
@@ -410,44 +413,59 @@ public class ActivitiServiceImpl implements ActivitiService {
                     tfFlowApproveLog = new TFFlowApproveLog(sysUser.getSchoolId(), sysUser.getOrgId(), SystemConstant.convertIdToLong(processInstanceId), examTask.getId(), sysUser.getId(), sysUser.getId());
                 }
                 FlowApprovePassEnum approvePass = (FlowApprovePassEnum) map.get(SystemConstant.APPROVE_OPERATION);
-                if (Objects.nonNull(map.get(SystemConstant.USER_TASK_ID)) && !Objects.equals(map.get(SystemConstant.USER_TASK_ID), "")) {
-                    String usertaskId = (String) map.get(SystemConstant.USER_TASK_ID);
-                    if (Objects.nonNull(flowProcessVarMap.get(usertaskId))) {
-                        List<Object> tempMap = (List<Object>) flowProcessVarMap.get(usertaskId);
-                        Gson gson = new Gson();
-                        CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(tempMap.get(0)), CustomFlowVarDto.class);
-                        map.computeIfAbsent(SystemConstant.APPROVE, v -> usertaskId);
-                        map.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), v -> customFlowVarDto.getApproveIds().size() == 1 ? customFlowVarDto.getApproveIds().get(0) : customFlowVarDto.getApproveIds());
-                    } else {
-                        map.computeIfAbsent(SystemConstant.APPROVE, v -> "end");
+                //判断流程审批是通过还是驳回
+                Gson gson = new Gson();
+                String usertaskId = null;
+                Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
+                if (approvePass == FlowApprovePassEnum.PASS) {
+                    Map<String, List<CustomFlowGatewayDto>> approvePassMap = (Map<String, List<CustomFlowGatewayDto>>) flowProcessVarMap.get(SystemConstant.APPROVE_PASS_MAP);
+                    if (Objects.nonNull(approvePassMap.get(userTask.getId())) && !Objects.equals(approvePassMap.get(userTask.getId()), "")) {
+                        List<CustomFlowGatewayDto> customFlowGatewayDtoList = gson.fromJson(gson.toJson(approvePassMap.get(userTask.getId())), new TypeToken<List<CustomFlowGatewayDto>>() {
+                        }.getType());
+                        boolean pass = false;
+                        for (CustomFlowGatewayDto c : customFlowGatewayDtoList) {
+                            if (Objects.equals(c.getFlowTaskId(), userTask.getId())) {
+                                usertaskId = c.getConditionExp().substring(c.getConditionExp().indexOf("'") + 1, c.getConditionExp().lastIndexOf("'"));
+                                pass = true;
+                                break;
+                            }
+                        }
+                        if (!pass) {
+                            throw ExceptionResultEnum.ERROR.exception("该节点不能通过");
+                        }
+                        map.put(SystemConstant.APPROVE, usertaskId);
+                        if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {
+                            map.computeIfAbsent(CustomFlowElementEnum.REJECT.getId(), v -> 0);
+                        }
+                    }
+                } else if (approvePass == FlowApprovePassEnum.REJECT) {
+                    if (Objects.isNull(map.get(SystemConstant.USER_TASK_ID)) || Objects.equals(map.get(SystemConstant.USER_TASK_ID), "")) {
+                        throw ExceptionResultEnum.ERROR.exception("流转节点不能为空");
+                    }
+                    usertaskId = (String) map.get(SystemConstant.USER_TASK_ID);
+                    Map<String, List<CustomFlowGatewayDto>> approveRejectMap = (Map<String, List<CustomFlowGatewayDto>>) flowProcessVarMap.get(SystemConstant.APPROVE_REJECT_MAP);
+                    List<CustomFlowGatewayDto> customFlowGatewayDtoList = gson.fromJson(gson.toJson(approveRejectMap.get(userTask.getId())), new TypeToken<List<CustomFlowGatewayDto>>() {
+                    }.getType());
+                    boolean reject = false;
+                    for (CustomFlowGatewayDto c : customFlowGatewayDtoList) {
+                        if (Objects.equals(c.getFlowTaskId(), usertaskId)) {
+                            reject = true;
+                            break;
+                        }
+                    }
+                    if (!reject) {
+                        throw ExceptionResultEnum.ERROR.exception("该节点不能驳回");
+                    }
+                    map.put(SystemConstant.APPROVE, usertaskId);
+                    if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {
+                        map.computeIfAbsent(CustomFlowElementEnum.REJECT.getId(), v -> 1);
                     }
-                } else {
-                    map.computeIfAbsent(SystemConstant.APPROVE, v -> "end");
                 }
-//                //广东医科大学流程
-//                if (Objects.nonNull(processDefinitionEntity) && (processDefinitionEntity.getKey().contains(SystemConstant.GDYKDX_FLOW_KEY)
-//                        || processDefinitionEntity.getKey().contains(SystemConstant.GDYKDX_SUB_FLOW_KEY))) {
-//                    if (setupEnum == FlowApproveSetupEnum.SUBMIT) {//命题提交
-//                        this.assignSubmit(task, sysUser, tfFlowApprove, tfFlowLog, map);
-//                    } else if (setupEnum == FlowApproveSetupEnum.PRIMARY_APPROVE) {//主任提交
-//                        this.directorApprove(task, sysUser, tfFlowApprove, tfFlowApproveLog, tfFlowLog, remark, processDefinitionEntity, map);
-//                    } else if (setupEnum == FlowApproveSetupEnum.SECOND_APPROVE) {//院长提交
-//                        this.presidentApprove(task, sysUser, tfFlowApprove, tfFlowApproveLog, tfFlowLog, remark, map, objectMap, processInstanceId);
-//                    } else if (setupEnum == FlowApproveSetupEnum.THREE_APPROVE) {//命题提交
-//                        this.teacherApprove(task, sysUser, tfFlowApprove, tfFlowApproveLog, tfFlowLog, remark, map);
-//                    } else if (setupEnum == FlowApproveSetupEnum.FOUR_APPROVE) {//印刷员提交
-//                        this.printApprove(task, sysUser, tfFlowApprove, tfFlowApproveLog, tfFlowLog, remark, map);
-//                    }
-//                }//江西中医药大学
-//                else if (Objects.nonNull(processDefinitionEntity) && processDefinitionEntity.getKey().contains(SystemConstant.JXZYY_FLOW_KEY)) {
-//                    if (setupEnum == FlowApproveSetupEnum.SUBMIT) {//命题提交
-//                        this.assignSubmit(task, sysUser, tfFlowApprove, tfFlowLog, map);
-//                    } else if (setupEnum == FlowApproveSetupEnum.PRIMARY_APPROVE) {//主任提交
-//                        this.directorApprove(task, sysUser, tfFlowApprove, tfFlowApproveLog, tfFlowLog, remark, processDefinitionEntity, map);
-//                    }
-//                } else {
-//                    throw ExceptionResultEnum.ERROR.exception("未配置流程学校code");
-//                }
+                //获取流程变量
+                if (Objects.nonNull(agginessMap.get(usertaskId))) {
+                    CustomFlowVarDto customFlowVarDto = gson.fromJson(gson.toJson(agginessMap.get(usertaskId)), CustomFlowVarDto.class);
+                    map.computeIfAbsent(customFlowVarDto.getFlowTaskVar(), v -> customFlowVarDto.getApproveIds().size() == 1 ? customFlowVarDto.getApproveIds().get(0) : customFlowVarDto.getApproveIds());
+                }
             }
             tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
             tfFlowApprove.setSetup(FlowApproveSetupEnum.PRIMARY_APPROVE.getSetup());
@@ -1512,7 +1530,12 @@ public class ActivitiServiceImpl implements ActivitiService {
         FlowTaskLink flowTaskLink = new FlowTaskLink();
         Map<String, Object> flowProcessVarMap = new HashMap<>();
         Map<String, Map<String, List<CustomFlowGatewayDto>>> gatewayMap = new HashMap<>();
-        flowProcessVarMap.computeIfAbsent(SystemConstant.GATEWAY_MAP, v -> gatewayMap);
+        Map<String, CustomFlowVarDto> agginessMap = new HashMap<>();
+        Map<String, List<CustomFlowGatewayDto>> approvePassMap = new HashMap<>();
+        Map<String, List<CustomFlowGatewayDto>> approveRejectMap = new HashMap<>();
+        flowProcessVarMap.computeIfAbsent(SystemConstant.AGGINESS_MAP, v -> agginessMap);
+        flowProcessVarMap.computeIfAbsent(SystemConstant.APPROVE_PASS_MAP, v -> approvePassMap);
+        flowProcessVarMap.computeIfAbsent(SystemConstant.APPROVE_REJECT_MAP, v -> approveRejectMap);
         AtomicInteger gatewayId = new AtomicInteger(1);
         AtomicInteger sequenceId = new AtomicInteger(1);
         CustomFlowDto customFlowDefaultDto = null;
@@ -1531,7 +1554,7 @@ public class ActivitiServiceImpl implements ActivitiService {
                     process.addFlowElement(createStartEvent());
                     //默认在开始节点后新增一个审批节点
                     customFlowDefaultDto = multiWorkFlow.createDefaultUserTask(customFlowDto, flowTaskLink, DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK);
-                    flowProcessVarMap.computeIfAbsent(customFlowDefaultDto.getFlowTaskId(), v -> new CustomFlowVarDto(SystemConstant.APPROVE_ID, Arrays.asList("")));
+                    agginessMap.computeIfAbsent(customFlowDefaultDto.getFlowTaskId(), v -> new CustomFlowVarDto(SystemConstant.APPROVE_ID, Arrays.asList("")));
                     process.addFlowElement(createUserTask(CustomFlowDynamicBuildEnum.USER_TASK.getId() + DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK, Objects.nonNull(flowTaskLink.getLast().getTask().getContent()) && !Objects.equals(flowTaskLink.getLast().getTask().getContent(), "") ? flowTaskLink.getLast().getTask().getContent() : DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK_NAME, DefaultInstanceConvertToMultiInstance.APPROVE_ID_EXP));
                     break;
                 case PROCESS://过程节点
@@ -1561,17 +1584,18 @@ public class ActivitiServiceImpl implements ActivitiService {
                             case ORDER://依次审批
                             case ALL://会签审批
                                 int finalI = i;
-                                flowProcessVarMap.computeIfAbsent(node.getTask().getFlowTaskId(), v -> new CustomFlowVarDto(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST + finalI, approveUserIds));
+                                agginessMap.computeIfAbsent(node.getTask().getFlowTaskId(), v -> new CustomFlowVarDto(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST + finalI, approveUserIds));
                                 break;
                             default:
                                 break;
                         }
                         if (Objects.nonNull(customFlowPropertyDto.getRejectType()) && !Objects.equals(customFlowPropertyDto.getRejectType(), "")) {
+                            List<CustomFlowGatewayDto> flowTaskIds = new ArrayList<>();
+                            approveRejectMap.put(node.getTask().getFlowTaskId(), flowTaskIds);
                             //驳回属性
                             switch (customFlowPropertyDto.getRejectType()) {
                                 case PREV://上一节点
                                     FlowTaskNode flowTaskNode = node.getBefore();
-                                    List<CustomFlowGatewayDto> flowTaskIds = new ArrayList<>();
                                     boolean isProcess = false;
                                     while (!isProcess) {
                                         if (flowTaskNode.getTask().getType() == CustomFlowTypeEnum.PROCESS) {
@@ -1588,16 +1612,16 @@ public class ActivitiServiceImpl implements ActivitiService {
                                             flowTaskIds);
                                     break;
                                 case START://发起人节点
+                                    flowTaskIds.add(new CustomFlowGatewayDto(customFlowDefaultDto.getFlowTaskId(), "${" + SystemConstant.APPROVE + "=='" + customFlowDefaultDto.getFlowTaskId() + "'}"));
                                     createCustomFlowExclusiveGateway(flowTaskLink,
                                             gatewayMap,
                                             process,
                                             gatewayId,
                                             customFlowDto.getFlowTaskId(),
-                                            Arrays.asList(new CustomFlowGatewayDto(customFlowDefaultDto.getFlowTaskId(), "${" + SystemConstant.APPROVE + "=='" + customFlowDefaultDto.getFlowTaskId() + "'}")));
+                                            flowTaskIds);
                                     break;
                                 case PREV_ALL://该节点前全部节点
                                     flowTaskNode = node.getBefore();
-                                    flowTaskIds = new ArrayList<>();
                                     while (Objects.nonNull(flowTaskNode)) {
                                         if (flowTaskNode.getTask().getType() == CustomFlowTypeEnum.PROCESS) {
                                             flowTaskIds.add(new CustomFlowGatewayDto(flowTaskNode.getTask().getFlowTaskId(), "${" + SystemConstant.APPROVE + "=='" + flowTaskNode.getTask().getFlowTaskId() + "'}"));
@@ -1614,6 +1638,7 @@ public class ActivitiServiceImpl implements ActivitiService {
                                 default:
                                     break;
                             }
+
                             //驳回再提交属性
                             switch (customFlowPropertyDto.getRejectResubmitType()) {
                                 case NORMAL://按正常流程提交
@@ -1651,7 +1676,18 @@ public class ActivitiServiceImpl implements ActivitiService {
             normalSequenceId = DefaultInstanceConvertToMultiInstance.SEQUENCE_NAME + sequenceId.getAndIncrement();
             log.info("1 start:{},end:{}", flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId());
             if (flowTaskNode.getBefore().getTask().getType() == CustomFlowTypeEnum.EXCLUSIVE_GATE_WAY) {
-                process.addFlowElement(createSequenceFlow(flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId(), normalSequenceId, FlowApprovePassEnum.PASS.getTitle(), "${" + SystemConstant.APPROVE + "=='" + flowTaskNode.getTask().getFlowTaskId() + "'}"));
+                FlowTaskNode flowTaskNodeTemp = flowTaskNode.getBefore();
+                boolean isProcess = false;
+                CustomFlowGatewayDto customFlowGatewayDto = null;
+                while (!isProcess) {
+                    if (flowTaskNodeTemp.getTask().getType() == CustomFlowTypeEnum.PROCESS) {
+                        isProcess = true;
+                        customFlowGatewayDto = new CustomFlowGatewayDto(flowTaskNodeTemp.getTask().getFlowTaskId(), "${" + SystemConstant.APPROVE + "=='" + flowTaskNode.getTask().getFlowTaskId() + "'}");
+                    }
+                    flowTaskNodeTemp = flowTaskNodeTemp.getBefore();
+                }
+                approvePassMap.put(customFlowGatewayDto.getFlowTaskId(), Arrays.asList(customFlowGatewayDto));
+                process.addFlowElement(createSequenceFlow(flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId(), normalSequenceId, FlowApprovePassEnum.PASS.getTitle(), customFlowGatewayDto.getConditionExp()));
             } else {
                 process.addFlowElement(createSequenceFlow(flowTaskNode.getBefore().getTask().getFlowTaskId(), flowTaskNode.getTask().getFlowTaskId(), normalSequenceId, FlowApprovePassEnum.PASS.getTitle(), null));
             }
@@ -1724,12 +1760,14 @@ public class ActivitiServiceImpl implements ActivitiService {
     @Transactional
     public void customFlowStartUpdateApproveId(Long customFlowId, Long approveId) {
         TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(customFlowId);
+        Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlow);
         Task task = taskService.createTaskQuery().processInstanceId(String.valueOf(tfCustomFlow.getFlowId())).singleResult();
         task.setAssignee(String.valueOf(approveId));
         taskService.saveTask(task);
-        Map<String, Object> flowProcessVarMap = this.getFlowProcessVarMap(tfCustomFlow);
         Map<String, Object> map = JacksonUtil.readJson(tfCustomFlow.getFlowProcessVar(), Map.class);
-        flowProcessVarMap.put(CustomFlowDynamicBuildEnum.USER_TASK.getId() + DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK, Arrays.asList(new CustomFlowVarDto(SystemConstant.APPROVE_ID, Arrays.asList(String.valueOf(approveId)))));
+        Map<String, CustomFlowVarDto> agginessMap = (Map<String, CustomFlowVarDto>) flowProcessVarMap.get(SystemConstant.AGGINESS_MAP);
+        agginessMap.put(CustomFlowDynamicBuildEnum.USER_TASK.getId() + DefaultInstanceConvertToMultiInstance.DEFAULT_USER_TASK, new CustomFlowVarDto(SystemConstant.APPROVE_ID, Arrays.asList(String.valueOf(approveId))));
+        flowProcessVarMap.put(SystemConstant.AGGINESS_MAP, agginessMap);
         map.put(SystemConstant.FLOW_PROCESS_VAR_MAP, flowProcessVarMap);
         tfCustomFlow.setFlowProcessVar(JacksonUtil.parseJson(map));
         tfCustomFlowService.updateById(tfCustomFlow);

+ 3 - 1
teachcloud-common/src/main/java/com/qmth/teachcloud/common/contant/SystemConstant.java

@@ -209,7 +209,9 @@ public class SystemConstant {
     public static final String FLOW_ID = "flowId";//流程id
     public static final String FLOW_TASK_ID = "flowTaskId";//流程任务id
     public static final String APPROVE = "approve";//流程审核变量
-    public static final String GATEWAY_MAP = "gatewayMap";//流程网关变量
+    public static final String AGGINESS_MAP = "agginessMap";//流程审批人变量
+    public static final String APPROVE_PASS_MAP = "approvePassMap";//流程审批通过变量
+    public static final String APPROVE_REJECT_MAP = "approveRejectMap";//流程审批驳回变量
     public static final String APPROVE_SETUP = "approveSetup";//流程节点
     public static final String APPROVE_USER_IDS = "approveUserIds";//流程审批人列表
     public static final String APPROVE_DIRECTOR_USER_IDS = "approveDirectorUserIds";//流程主任审批人列表