Commit d467bfc5 by 王志超

feat: 行动工单流程流转

parent 5cb06801
Pipeline #86538 passed with stages
in 1 minute 29 seconds
...@@ -58,7 +58,6 @@ import org.springframework.beans.BeanUtils; ...@@ -58,7 +58,6 @@ import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import javax.validation.Valid;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -221,19 +220,26 @@ public class ChangeSubFlowBiz { ...@@ -221,19 +220,26 @@ public class ChangeSubFlowBiz {
subFlowRecord.getChangeRecordId(), changeExecProjectList, subFlowId, subFlowRecord.getId()); subFlowRecord.getChangeRecordId(), changeExecProjectList, subFlowId, subFlowRecord.getId());
newExecRecords.forEach(changeFlowExecService::saveRecord); newExecRecords.forEach(changeFlowExecService::saveRecord);
// 提交到下一节点 // 检查是否需要审批,通过paramMap控制流转方向
String nextNodeId = flowService.submitFlow(subFlowId, flowDataDTO, uid, Map<String, Object> paramMap = new HashMap<>();
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), true, String nextNodeId;
FlowxOperationEnum.SUBMIT.getName(), "提交工单", subFlowRecord.getCreateTime());
// 检查是否需要审批
if (needApprove(expectedDepartment)) { if (needApprove(expectedDepartment)) {
// 需要审批:流转到审批行动方案节点,设置上级领导为审批人
log.info("[CHANGE_SUB_FLOW_START] 部门[{}]需要审批,等待上级审批", expectedDepartment); log.info("[CHANGE_SUB_FLOW_START] 部门[{}]需要审批,等待上级审批", expectedDepartment);
// 需要审批:设置上级领导为审批人,停留在审批节点 paramMap.put("type", 1);
// 提交到审批行动方案节点
nextNodeId = flowService.submitFlowWithParamMap(subFlowId, flowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), paramMap,
FlowxOperationEnum.SUBMIT.getName(), "提交工单", subFlowRecord.getCreateTime());
// 更新子单记录
subFlowRecord.setSubFlowNode(nextNodeId); subFlowRecord.setSubFlowNode(nextNodeId);
subFlowRecord.setStatus(ChangeSubFlowStatusEnum.WAIT_APPROVE_ACTION_PLAN.getStatus()); subFlowRecord.setStatus(ChangeSubFlowStatusEnum.WAIT_APPROVE_ACTION_PLAN.getStatus());
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime()); subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
// 获取上级领导并设置为审批人
String execUserEmail = subFlowRecord.getChangeExecUserEmail(); String execUserEmail = subFlowRecord.getChangeExecUserEmail();
if (StringUtils.isBlank(execUserEmail)) { if (StringUtils.isBlank(execUserEmail)) {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "行动人邮箱不能为空"); throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "行动人邮箱不能为空");
...@@ -243,39 +249,33 @@ public class ChangeSubFlowBiz { ...@@ -243,39 +249,33 @@ public class ChangeSubFlowBiz {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST,
String.format("行动人[%s]的部门上级领导不存在", execUserEmail)); String.format("行动人[%s]的部门上级领导不存在", execUserEmail));
} }
// 设置审批人为上级领导(JSON 数组格式)
subFlowRecord.setApprover(JSON.toJSONString(Collections.singletonList(leaderEmail))); subFlowRecord.setApprover(JSON.toJSONString(Collections.singletonList(leaderEmail)));
changeSubFlowRecordService.update(subFlowRecord);
log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批行动方案", log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批行动方案",
subFlowId, oldNodeId, oldNodeName, nextNodeId); subFlowId, oldNodeId, oldNodeName, nextNodeId);
return nextNodeId;
} else { } else {
// 不需要审批,自动提交到下一节点(审批人保持为行动人自己) // 不需要审批:直接跳到审批变更方案节点,审批人保持为行动人自己
log.info("[CHANGE_SUB_FLOW_START] 部门[{}]不需要审批,自动跳过审批", expectedDepartment); log.info("[CHANGE_SUB_FLOW_START] 部门[{}]不需要审批,自动跳过审批", expectedDepartment);
paramMap.put("type", 2);
// 重新查询最新的flowDataDTO,因为第一次submitFlow已经改变了flow状态 // 提交到审批变更方案节点
FlowDataDTO latestFlowDataDTO = flowService.flowDetail(subFlowId); nextNodeId = flowService.submitFlowWithParamMap(subFlowId, flowDataDTO, uid,
if (latestFlowDataDTO == null) {
throw ExceptionFactory.createBiz(ResponseCode.DETAIL_FLOW_ERROR, "子流程工单查询错误,不存在");
}
// 使用paramMap控制流转方向(type=1表示审批通过)
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("type", 1);
String autoNextNodeId = flowService.submitFlowWithParamMap(subFlowId, latestFlowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), paramMap, ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), paramMap,
FlowxOperationEnum.SUBMIT.getName(), "自动审批通过", subFlowRecord.getCreateTime()); FlowxOperationEnum.SUBMIT.getName(), "提交工单", subFlowRecord.getCreateTime());
subFlowRecord.setSubFlowNode(autoNextNodeId);
// 更新子单记录
subFlowRecord.setSubFlowNode(nextNodeId);
subFlowRecord.setStatus(ChangeSubFlowStatusEnum.WAIT_APPROVE_CHANGE_PLAN.getStatus()); subFlowRecord.setStatus(ChangeSubFlowStatusEnum.WAIT_APPROVE_CHANGE_PLAN.getStatus());
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime()); subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlowRecord);
// todo:非名单中部门无需审批,行动人确认提交后邮件同步负责人上级对应变更信息 // todo:非名单中部门无需审批,行动人确认提交后邮件同步负责人上级对应变更信息
log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批变更方案 (自动跳过审批)", log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批变更方案 (自动跳过审批)",
subFlowId, oldNodeId, oldNodeName, autoNextNodeId); subFlowId, oldNodeId, oldNodeName, nextNodeId);
return autoNextNodeId;
} }
changeSubFlowRecordService.update(subFlowRecord);
return nextNodeId;
case CHANGE_SUB_FLOW_SUBMIT: case CHANGE_SUB_FLOW_SUBMIT:
// 审批行动方案节点 // 审批行动方案节点
Boolean approved = changeSubFlowSubmitReq.getApproved(); Boolean approved = changeSubFlowSubmitReq.getApproved();
...@@ -293,10 +293,13 @@ public class ChangeSubFlowBiz { ...@@ -293,10 +293,13 @@ public class ChangeSubFlowBiz {
log.info("[CHANGE_SUB_FLOW_SUBMIT] 审批不通过,subFlowId:{}, rejectReason:{}", subFlowId, rejectReason); log.info("[CHANGE_SUB_FLOW_SUBMIT] 审批不通过,subFlowId:{}, rejectReason:{}", subFlowId, rejectReason);
} }
// 提交工单(根据审批结果流转到不同节点) // 使用paramMap控制流转方向(type=1通过,type=2不通过)
Map<String, Object> approveParamMap = new HashMap<>();
approveParamMap.put("type", approved ? 1 : 2);
String remark = approved ? "审批通过" : "审批不通过"; String remark = approved ? "审批通过" : "审批不通过";
String approveNodeId = flowService.submitFlow(subFlowId, flowDataDTO, uid, String approveNodeId = flowService.submitFlowWithParamMap(subFlowId, flowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), approved, ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), approveParamMap,
FlowxOperationEnum.SUBMIT.getName(), remark, subFlowRecord.getCreateTime()); FlowxOperationEnum.SUBMIT.getName(), remark, subFlowRecord.getCreateTime());
// 更新行动工单 // 更新行动工单
...@@ -318,36 +321,60 @@ public class ChangeSubFlowBiz { ...@@ -318,36 +321,60 @@ public class ChangeSubFlowBiz {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "审批结果不能为空"); throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "审批结果不能为空");
} }
if (!execApproved) { // 使用paramMap控制流转方向
// 审批不通过,拒绝原因必填 Map<String, Object> execParamMap = new HashMap<>();
String execNodeId;
if (execApproved) {
// 审批通过:流转到提交执行结果节点
log.info("[CHANGE_SUB_FLOW_EXE] 审批通过,subFlowId:{}", subFlowId);
execParamMap.put("type", 1);
// 提交到提交执行结果节点
execNodeId = flowService.submitFlowWithParamMap(subFlowId, flowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), execParamMap,
FlowxOperationEnum.SUBMIT.getName(), "审批通过", subFlowRecord.getCreateTime());
// 更新子单记录
subFlowRecord.setSubFlowNode(execNodeId);
subFlowRecord.setStatus(ChangeSubFlowStatusEnum.WAIT_SUBMIT_RESULT.getStatus());
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlowRecord);
log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-提交执行结果, 审批结果:通过",
subFlowId, oldNodeId, oldNodeName, execNodeId);
// 检查所有子单是否都已到达提交执行结果节点,如果是则流转主工单
if (checkAllSubFlowsApproved(subFlowRecord.getChangeRecordId())) {
changeFlowBiz.submitMainFlowAfterAllSubFlowsApproved(subFlowRecord.getChangeRecordId());
log.info("[CHANGE_SUB_FLOW_EXE] 所有子单均已到达提交执行结果节点,主工单已流转");
}
} else {
// 审批不通过:回退到确认行动方案节点,拒绝原因必填
String execRejectReason = changeSubFlowSubmitReq.getRejectReason(); String execRejectReason = changeSubFlowSubmitReq.getRejectReason();
if (StringUtils.isBlank(execRejectReason)) { if (StringUtils.isBlank(execRejectReason)) {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "拒绝原因不能为空"); throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "拒绝原因不能为空");
} }
subFlowRecord.setChangePlanApproved(false);
subFlowRecord.setRejectReason(execRejectReason); subFlowRecord.setRejectReason(execRejectReason);
subFlowRecord.setStatus(ChangeSubFlowStatusEnum.CANCELLED.getStatus());
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlowRecord);
log.info("[CHANGE_SUB_FLOW_EXE] 审批不通过,subFlowId:{}, rejectReason:{}", subFlowId, execRejectReason); log.info("[CHANGE_SUB_FLOW_EXE] 审批不通过,subFlowId:{}, rejectReason:{}", subFlowId, execRejectReason);
} else { execParamMap.put("type", 2);
// 审批通过,只标记 changePlanApproved=true,子单不流转
subFlowRecord.setChangePlanApproved(true); // 提交到确认行动方案节点
execNodeId = flowService.submitFlowWithParamMap(subFlowId, flowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), execParamMap,
FlowxOperationEnum.SUBMIT.getName(), "审批不通过", subFlowRecord.getCreateTime());
// 更新子单记录
subFlowRecord.setSubFlowNode(execNodeId);
subFlowRecord.setStatus(ChangeSubFlowStatusEnum.CANCELLED.getStatus());
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime()); subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlowRecord); changeSubFlowRecordService.update(subFlowRecord);
log.info("[CHANGE_SUB_FLOW_EXE] 审批通过,subFlowId:{}, 标记changePlanApproved=true", subFlowId);
// 检查该主工单下所有子单是否都已审批通过 log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-确认行动方案, 审批结果:不通过",
if (checkAllSubFlowsApproved(subFlowRecord.getChangeRecordId())) { subFlowId, oldNodeId, oldNodeName, execNodeId);
// 所有子单都通过,流转主工单
changeFlowBiz.submitMainFlowAfterAllSubFlowsApproved(subFlowRecord.getChangeRecordId());
log.info("[CHANGE_SUB_FLOW_EXE] 所有子单均已审批通过,主工单已流转");
}
} }
log.info("[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 节点保持:{}-{}, 审批结果:{}", return execNodeId;
subFlowId, oldNodeId, oldNodeName, execApproved ? "通过" : "不通过");
return subFlowRecord.getSubFlowNode();
case CHANGE_SUB_FLOW_CONFIRM: case CHANGE_SUB_FLOW_CONFIRM:
// 提交执行结果节点,填写变更结论 // 提交执行结果节点,填写变更结论
...@@ -543,11 +570,11 @@ public class ChangeSubFlowBiz { ...@@ -543,11 +570,11 @@ public class ChangeSubFlowBiz {
} }
/** /**
* 检查主工单下所有子单是否都已审批通过 * 检查主工单下所有子单是否都已到达提交执行结果节点
* 条件:节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true * 条件:status = WAIT_SUBMIT_RESULT 且 subFlowNode = CHANGE_SUB_FLOW_CONFIRM
* *
* @param changeRecordId 主工单ID * @param changeRecordId 主工单ID
* @return true 表示所有子单都已审批通过 * @return true 表示所有子单都已到达提交执行结果节点
*/ */
private boolean checkAllSubFlowsApproved(Long changeRecordId) { private boolean checkAllSubFlowsApproved(Long changeRecordId) {
// 查询该主工单下所有子单 // 查询该主工单下所有子单
...@@ -556,10 +583,10 @@ public class ChangeSubFlowBiz { ...@@ -556,10 +583,10 @@ public class ChangeSubFlowBiz {
return false; return false;
} }
// 检查是否所有子单都满足条件:节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true // 检查是否所有子单都满足条件:status = WAIT_SUBMIT_RESULT 且 subFlowNode = CHANGE_SUB_FLOW_CONFIRM
return allSubFlows.stream().allMatch(subFlow -> return allSubFlows.stream().allMatch(subFlow ->
ChangeFlowEnum.CHANGE_SUB_FLOW_EXE.getNodeId().equals(subFlow.getSubFlowNode()) ChangeSubFlowStatusEnum.WAIT_SUBMIT_RESULT.getStatus().equals(subFlow.getStatus())
&& Boolean.TRUE.equals(subFlow.getChangePlanApproved()) && ChangeFlowEnum.CHANGE_SUB_FLOW_CONFIRM.getNodeId().equals(subFlow.getSubFlowNode())
); );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment