Commit 47221b88 by 王志超

feat: 行动工单流程流转

parent d467bfc5
...@@ -712,205 +712,63 @@ public class ChangeFlowBiz { ...@@ -712,205 +712,63 @@ public class ChangeFlowBiz {
case NEW_CHANGE_FLOW_OWNER_APPROVE: case NEW_CHANGE_FLOW_OWNER_APPROVE:
case NEW_CHANGE_FLOW_ADMIN_APPROVE: case NEW_CHANGE_FLOW_ADMIN_APPROVE:
case NEW_CHANGE_FLOW_QUALITY_APPROVE: case NEW_CHANGE_FLOW_QUALITY_APPROVE:
// 部门负责人、质量部负责人、变更管理员审批节点:检查所有子单是否都已审批通过 // 部门负责人、变更管理员、质量部负责人审批节点
return null; Boolean mainFlowApproved = changeFlowSubmitReq.getApproved();
case NEW_CHANGE_FLOW_EXE: if (mainFlowApproved == null) {
// todo: throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "审批结果不能为空");
// 这些节点检查所有子单是否都已完成(FINISHED或CANCELLED)
if (!checkAllSubFlowsFinishedForMainFlow(changeRecord.getId())) {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST,
"存在子单未完成,无法提交主工单");
} }
// 所有子单都已完成,提交主工单到下一节点 // 使用paramMap控制流转方向
String mainFlowNextNodeId = flowService.submitFlow(flowId.toString(), flowDataDTO, uid, Map<String, Object> mainFlowParamMap = new HashMap<>();
ChangeFlowEnum.NEW_CHANGE_FLOW.getTopoId(), JSON.toJSONString(content), true, String mainFlowNodeId;
FlowxOperationEnum.SUBMIT.getName(), "所有子单已完成,主工单流转", changeRecord.getCreateTime());
changeRecord.setFlowNode(mainFlowNextNodeId); if (mainFlowApproved) {
changeRecord.setUpdateTime(DateUtils.getCurrentTime()); // 审批通过:流转到下一节点(type=1)
changeFlowService.updateRecord(changeRecord); log.info("[{}] 审批通过,flowId:{}", node.getName(), flowId);
log.info("[NEW_CHANGE_FLOW] 主工单流转成功,flowId:{}, node:{}, nextNodeId:{}", mainFlowParamMap.put("type", 1);
flowId, node, mainFlowNextNodeId);
return mainFlowNextNodeId; mainFlowNodeId = flowService.submitFlowWithParamMap(flowId.toString(), flowDataDTO, uid,
case NEW_CHANGE_FLOW_CONFIRM: ChangeFlowEnum.NEW_CHANGE_FLOW.getTopoId(), JSON.toJSONString(content), mainFlowParamMap,
// todo: FlowxOperationEnum.SUBMIT.getName(), "审批通过", changeRecord.getCreateTime());
return null;
case CHANGE_FLOW_CONFIRM: // 更新主工单记录
Integer changeResult = changeFlowSubmitReq.getChangeResult(); changeRecord.setFlowNode(mainFlowNodeId);
ChangeResultEnum changeResultStatus = ChangeResultEnum.getByStatus(changeResult);
Assert.notNull(changeResultStatus, "变更结论类型错误");
// 填写变更结论
changeRecord.setChangeResult(changeResultStatus.getStatus());
// 填写备注
changeRecord.setRemark(changeFlowSubmitReq.getRemark());
List<ChangeFlowFile> finialFiles = changeFlowSubmitReq.getChangeResultFiles();
if (CollectionUtils.isNotEmpty(finialFiles)) {
changeFileService.deleteByChangeRecordIdAndType(changeRecord.getId(), FileTypeEnum.CHANGE_RESULT_INFO);
List<ChangeFile> finialFileList = buildChangeFileRecord(changeRecord.getId(), finialFiles, FileTypeEnum.CHANGE_RESULT_INFO.getType());
finialFileList.forEach(file -> changeFileService.saveRecord(file));
}
switch (changeResultStatus) {
case FINISH_ALL:
case FINISH_PART:
String reason = changeFlowSubmitReq.getCancelReason();
changeRecord.setCancelReason(reason);
List<ChangeExecConfigReq> execProjectList = changeFlowSubmitReq.getChangeExecProjectList();
List<ChangeExecRecord> changeExecRecordList = execProjectList.stream().map(exec -> {
Long changeExecFinishTime = exec.getChangeExecFinishTime();
Assert.notNull(changeExecFinishTime, "行动完成时间不可为空" + exec.getChangeTemplateId());
ChangeExecRecord changeExecRecord = new ChangeExecRecord();
changeExecRecord.setId(exec.getChangeExecId());
changeExecRecord.setChangeExecFinishTime(exec.getChangeExecFinishTime());
changeExecRecord.setChangeExecFinishDesc(exec.getChangeExecFinishDesc());
return changeExecRecord;
}).collect(Collectors.toList());
// 完成直接完结
String confirmNode = flowService.submitFlow(flowId.toString(), flowDataDTO, uid,
ChangeFlowEnum.CHANGE_FLOW_CONFIRM.getTopoId(), JSON.toJSONString(content), true,
FlowxOperationEnum.SUBMIT.getName(), "提交工单", changeRecord.getCreateTime());
changeRecord.setState(ChangeStatusEnum.END.getStatus());
changeRecord.setFlowNode(confirmNode);
changeRecord.setUpdateTime(DateUtils.getCurrentTime()); changeRecord.setUpdateTime(DateUtils.getCurrentTime());
changeFlowService.updateRecord(changeRecord); changeFlowService.updateRecord(changeRecord);
changeExecRecordList.forEach(exec -> changeFlowExecService.update(exec));
// 发送邮件 log.info("[checkUpdateAndSubmit] 主工单流转完成,flowId:{}, 审批节点:{}, 新节点:{}, 审批结果:通过",
HashMap<String, Object> finishPartMap = new HashMap<>(); flowId, node.getName(), mainFlowNodeId);
finishPartMap.put("changeId", changeRecord.getFlowId()); } else {
finishPartMap.put("changeSubject", ChangeSubjectEnum.getChangeSubjectEnum(changeRecord.getChangeSubject()).getDesc()); // 审批不通过:回退到确认变更方案节点(type=3)
finishPartMap.put("flowUrl", changeRecord.getFlowId()); // todo: 实现审批不通过的逻辑(拒绝原因、状态更新、邮件通知等)
ChangeConfigPo changeConfigPo = changeConfigService log.warn("[{}] 审批不通过,flowId:{}", node.getName(), flowId);
.queryInfoPo(changeRecord.getParentChangeClassId(), changeRecord.getSonChangeClassId()); mainFlowParamMap.put("type", 3);
StringBuilder changeType = new StringBuilder();
try { mainFlowNodeId = flowService.submitFlowWithParamMap(flowId.toString(), flowDataDTO, uid,
changeType.append(changeConfigPo.getChangeTypes().get(0).getTypeName()); ChangeFlowEnum.NEW_CHANGE_FLOW.getTopoId(), JSON.toJSONString(content), mainFlowParamMap,
} catch (Exception e) { FlowxOperationEnum.SUBMIT.getName(), "审批不通过", changeRecord.getCreateTime());
log.error("queryInfoPo error:{}", JSON.toJSONString(changeConfigPo));
} // 更新主工单记录(回到确认变更方案节点)
try { changeRecord.setFlowNode(mainFlowNodeId);
changeType.append(changeConfigPo.getChangeTypes().get(1).getTypeName()); changeRecord.setState(ChangeStatusEnum.WAIT_CONFIRM_CHANGE_PLAN.getStatus());
} catch (Exception e) {
log.error("queryInfoPo error:{}", JSON.toJSONString(changeConfigPo));
}
//【已完结】变更主体+变更内容+工单ID 变更风险行动项已完结,请开始执行变更。
String finishSubjectParam = ChangeSubjectEnum
.getChangeSubjectEnum(changeRecord.getChangeSubject()).getDesc()
+ changeRecord.getChangeContent() + changeRecord.getFlowId();
// 变更确认,收件人:变更负责人+变更供应商+所有变更行动人+变更管理QM(cuiyixian@corp.netease.com)
List<ChangeFlowExecVO> execRecord = changeFlowExecService
.getChangeFlowExecRecord(changeRecord.getId());
List<String> userEmailList = execRecord.stream().map(ChangeFlowExecVO::getChangeExecUserEmail)
.collect(Collectors.toList());
// 变更确认,抄送人:所有变更行动人上一级LEADER+变更管理委员会(yx_change_SC@qun.mail.163.com)
List<String> list = departmentLeaderBiz.getDepartmentLeaders(userEmailList);
list.add(appConfig.getChangeCommittee());
userEmailList.add(changeRecord.getChangeCommander());
userEmailList.add(appConfig.getChangeManageQM());
qcSendEmail(userEmailList, list, finishSubjectParam,
EmailTemplateEnum.YX_QC_CHANGE_FINISH, finishPartMap);
// 如果是供应商,再次发送供应商邮件
if (changeRecord.getCreateSource().equals(CreateSourceEnum.TONG_ZHOU.getType())) {
sendSupplierEmail.sendSupplierEmail(changeRecord.getCreateSupplier(), finishSubjectParam,
EmailTemplateEnum.YX_QC_CHANGE_FINISH, finishPartMap);
}
// 如果是其他端发起但是是供应商变更,再次发送供应商邮件
if (!changeRecord.getCreateSource().equals(CreateSourceEnum.TONG_ZHOU.getType())
&& ChangeSubjectEnum.SUPPLIER.getType().equals(changeRecord.getChangeSubject())) {
sendSupplierEmail.sendSupplierEmail(changeRecord.getChangeSupplier(), finishSubjectParam,
EmailTemplateEnum.YX_QC_CHANGE_FINISH, finishPartMap);
}
return confirmNode;
case CANCEL:
// 取消填写取消原因
String cancelReason = changeFlowSubmitReq.getCancelReason();
Assert.isTrue(StringUtils.isNotBlank(cancelReason), "变更取消原因不可为空");
changeRecord.setCancelReason(cancelReason);
List<ChangeExecRecord> cancelChangeExecRecordList = changeFlowSubmitReq
.getChangeExecProjectList().stream().map(exec -> {
Long changeExecFinishTime = exec.getChangeExecFinishTime();
Assert.notNull(changeExecFinishTime, "行动完成时间不可为空" + exec.getChangeTemplateId());
ChangeExecRecord changeExecRecord = new ChangeExecRecord();
changeExecRecord.setId(exec.getChangeExecId());
changeExecRecord.setChangeExecFinishTime(exec.getChangeExecFinishTime());
changeExecRecord.setChangeExecFinishDesc(exec.getChangeExecFinishDesc());
return changeExecRecord;
}).collect(Collectors.toList());
String cancelNode = flowService.submitFlow(flowId.toString(), flowDataDTO, uid,
ChangeFlowEnum.CHANGE_FLOW_CONFIRM.getTopoId(), JSON.toJSONString(content), true,
FlowxOperationEnum.SUBMIT.getName(), "提交工单", changeRecord.getCreateTime());
changeRecord.setState(ChangeStatusEnum.END.getStatus());
changeRecord.setFlowNode(cancelNode);
changeRecord.setUpdateTime(DateUtils.getCurrentTime()); changeRecord.setUpdateTime(DateUtils.getCurrentTime());
changeFlowService.updateRecord(changeRecord); changeFlowService.updateRecord(changeRecord);
cancelChangeExecRecordList.forEach(exec -> changeFlowExecService.update(exec));
// 发送邮件 log.info("[checkUpdateAndSubmit] 主工单流转完成,flowId:{}, 审批节点:{}, 新节点:确认变更方案, 审批结果:不通过",
HashMap<String, Object> cancelMap = new HashMap<>(); flowId, node.getName());
cancelMap.put("changeId", changeRecord.getFlowId());
cancelMap.put("changeSubject", ChangeSubjectEnum.getChangeSubjectEnum(changeRecord.getChangeSubject()).getDesc());
cancelMap.put("flowUrl", changeRecord.getFlowId());
ChangeConfigPo changeConfigPo1 = changeConfigService
.queryInfoPo(changeRecord.getParentChangeClassId(), changeRecord.getSonChangeClassId());
StringBuilder changeType1 = new StringBuilder();
try {
changeType1.append(changeConfigPo1.getChangeTypes().get(0).getTypeName());
} catch (Exception e) {
log.error("queryInfoPo error:{}", JSON.toJSONString(changeConfigPo1));
}
try {
changeType1.append(changeConfigPo1.getChangeTypes().get(1).getTypeName());
} catch (Exception e) {
log.error("queryInfoPo error:{}", JSON.toJSONString(changeConfigPo1));
}
//【已完结】变更主体+变更内容+工单ID 变更风险行动项已完结,请开始执行变更。
String cancelFinishSubjectParam = ChangeSubjectEnum
.getChangeSubjectEnum(changeRecord.getChangeSubject()).getDesc()
+ changeRecord.getChangeContent() + changeRecord.getFlowId();
// 变更确认,收件人:变更负责人+变更供应商+所有变更行动人+变更管理QM(cuiyixian@corp.netease.com)
List<ChangeFlowExecVO> execRecordList = changeFlowExecService
.getChangeFlowExecRecord(changeRecord.getId());
List<String> userEmails = execRecordList.stream().map(ChangeFlowExecVO::getChangeExecUserEmail)
.collect(Collectors.toList());
// 变更确认,抄送人:所有变更行动人上一级LEADER+变更管理委员会(yx_change_SC@qun.mail.163.com)
List<String> departmentInfoList = departmentLeaderBiz.getDepartmentLeaders(userEmails);
departmentInfoList.add(appConfig.getChangeCommittee());
userEmails.add(changeRecord.getChangeCommander());
userEmails.add(appConfig.getChangeManageQM());
qcSendEmail(userEmails, departmentInfoList, cancelFinishSubjectParam,
EmailTemplateEnum.YX_QC_CHANGE_FINISH, cancelMap);
// 如果是供应商,再次发送供应商邮件
if (changeRecord.getCreateSource().equals(CreateSourceEnum.TONG_ZHOU.getType())) {
sendSupplierEmail.sendSupplierEmail(changeRecord.getCreateSupplier(), cancelFinishSubjectParam,
EmailTemplateEnum.YX_QC_CHANGE_FINISH, cancelMap);
}
// 如果是其他端发起但是是供应商变更,再次发送供应商邮件
if (!changeRecord.getCreateSource().equals(CreateSourceEnum.TONG_ZHOU.getType())
&& ChangeSubjectEnum.SUPPLIER.getType().equals(changeRecord.getChangeSubject())) {
sendSupplierEmail.sendSupplierEmail(changeRecord.getChangeSupplier(), cancelFinishSubjectParam,
EmailTemplateEnum.YX_QC_CHANGE_FINISH, cancelMap);
} }
return cancelNode;
case DELAY: return mainFlowNodeId;
// 延期不流转工单 case NEW_CHANGE_FLOW_EXE:
Long changeConfirmResultTime = changeFlowSubmitReq.getChangeConfirmResultTime(); // 执行变更方案节点:等待所有子单完成后自动流转,不允许主动提交
Long tomorrowSpecificTime = DateUtils.getTomorrowSpecificTime("00:00:00"); throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST,
Assert.isTrue( "该节点不允许主动提交,需等待所有行动工单执行变更方案后自动流转");
changeConfirmResultTime != null && changeConfirmResultTime >= tomorrowSpecificTime, case NEW_CHANGE_FLOW_CONFIRM:
"时间不可晚于下次执行时间"); // todo: 确认变更结果节点待实现
// 更改变更结果确认时间
changeRecord.setChangeConfirmResultTime(changeConfirmResultTime);
changeRecord.setUpdateTime(DateUtils.getCurrentTime());
// 延期需要重新发邮件,改变执行邮件状态
changeRecord.setAutoSubmitEmail(0);
changeFlowService.updateRecord(changeRecord);
return null;
default:
return null; return null;
}
// 其他几点,不可提交
case CHANGE_FLOW_EXE:
case CHANGE_FLOW_START:
case END:
default: default:
throw ExceptionFactory.createBiz(ResponseCode.NODE_ERROR, "不可提交节点" + currentNode); throw ExceptionFactory.createBiz(ResponseCode.NODE_ERROR, "不可提交节点" + currentNode);
} }
} }
...@@ -1784,9 +1642,13 @@ public class ChangeFlowBiz { ...@@ -1784,9 +1642,13 @@ public class ChangeFlowBiz {
content.put("updateTime", System.currentTimeMillis()); content.put("updateTime", System.currentTimeMillis());
content.put(CommonConstants.FLOW_OPERATION_KEY, FlowOperationTypeEnum.PASS.getValue()); content.put(CommonConstants.FLOW_OPERATION_KEY, FlowOperationTypeEnum.PASS.getValue());
// 使用paramMap控制流转方向(type=1表示所有子单审批通过)
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("type", 1);
// 流转主工单到部门负责人审批节点 // 流转主工单到部门负责人审批节点
String ownerApproveNodeId = flowService.submitFlow(flowId.toString(), flowDataDTO, uid, String ownerApproveNodeId = flowService.submitFlowWithParamMap(flowId.toString(), flowDataDTO, uid,
ChangeFlowEnum.NEW_CHANGE_FLOW.getTopoId(), JSON.toJSONString(content), true, ChangeFlowEnum.NEW_CHANGE_FLOW.getTopoId(), JSON.toJSONString(content), paramMap,
FlowxOperationEnum.SUBMIT.getName(), "所有子单审批通过,主工单流转", changeRecord.getCreateTime()); FlowxOperationEnum.SUBMIT.getName(), "所有子单审批通过,主工单流转", changeRecord.getCreateTime());
changeRecord.setFlowNode(ownerApproveNodeId); changeRecord.setFlowNode(ownerApproveNodeId);
......
...@@ -483,6 +483,8 @@ public class ChangeSubFlowBiz { ...@@ -483,6 +483,8 @@ public class ChangeSubFlowBiz {
// 发送邮件 // 发送邮件
sendSubFlowFinishEmail(subFlowRecord); sendSubFlowFinishEmail(subFlowRecord);
// todo: 检查所有子单是否都已完成,如果是则流转主工单
return endNodeId; return endNodeId;
} }
...@@ -518,6 +520,8 @@ public class ChangeSubFlowBiz { ...@@ -518,6 +520,8 @@ public class ChangeSubFlowBiz {
// 发送邮件 // 发送邮件
sendSubFlowFinishEmail(subFlowRecord); sendSubFlowFinishEmail(subFlowRecord);
// todo: 检查所有子单是否都已完成,如果是则流转主工单
return cancelNodeId; return cancelNodeId;
} }
......
...@@ -120,4 +120,14 @@ public class ChangeFlowSubmitReq { ...@@ -120,4 +120,14 @@ public class ChangeFlowSubmitReq {
* 变更收益金额 * 变更收益金额
*/ */
private String changeProfitAmount; private String changeProfitAmount;
/**
* 审批结果(审批节点使用:true-通过,false-不通过)
*/
private Boolean approved;
/**
* 拒绝原因(审批不通过时必填)
*/
private String rejectReason;
} }
\ No newline at end of file
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