Commit 479f9a08 by 王志超

feat: 子工单分批审核,所有到达待审批时,自动流转到待提交工单,主工单流转到待负责人审批

parent 498a3295
Pipeline #86446 passed with stages
in 1 minute 26 seconds
......@@ -58,6 +58,7 @@ import com.netease.mail.yanxuan.change.dal.entity.ChangeRecord;
import com.netease.mail.yanxuan.change.dal.entity.ChangeSubFlowRecord;
import com.netease.mail.yanxuan.change.dal.entity.ChangeType;
import com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper;
import com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper;
import com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeCommanderPO;
import com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeConfigPo;
import com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeGoodsPrincipalPO;
......@@ -131,6 +132,9 @@ public class ChangeFlowBiz {
private ChangeRecordMapper changeRecordMapper;
@Autowired
private ChangeSubFlowRecordMapper changeSubFlowRecordMapper;
@Autowired
private ItemService itemService;
@Autowired
......@@ -699,6 +703,24 @@ public class ChangeFlowBiz {
createAndBindSubFlows(changeRecord, flowName);
buildAndSendEmail.buildAndSendEmailSubmit(changeRecord, changeExecRecords);
return submitNode;
case NEW_CHANGE_FLOW_CONFIRM_EXEC_PLAN:
// 确认变更方案节点:检查所有子单是否都已审批通过
if (!checkAllSubFlowsApprovedForMainFlow(changeRecord.getId())) {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST,
"存在子单未审批通过,无法流转主工单");
}
// 所有子单都已审批通过,流转主工单到部门负责人审批节点
String ownerApproveNodeId = flowService.submitFlow(flowId.toString(), flowDataDTO, uid,
ChangeFlowEnum.NEW_CHANGE_FLOW.getTopoId(), JSON.toJSONString(content), true,
FlowxOperationEnum.SUBMIT.getName(), "所有子单审批通过,主工单流转", changeRecord.getCreateTime());
changeRecord.setFlowNode(ownerApproveNodeId);
changeRecord.setState(ChangeStatusEnum.WAIT_DEPT_LEADER_APPROVE.getStatus());
changeRecord.setUpdateTime(DateUtils.getCurrentTime());
changeFlowService.updateRecord(changeRecord);
log.info("[NEW_CHANGE_FLOW_CONFIRM_EXEC_PLAN] 主工单流转成功,flowId:{}, nextNodeId:{}",
flowId, ownerApproveNodeId);
return ownerApproveNodeId;
case CHANGE_FLOW_CONFIRM:
Integer changeResult = changeFlowSubmitReq.getChangeResult();
ChangeResultEnum changeResultStatus = ChangeResultEnum.getByStatus(changeResult);
......@@ -1688,4 +1710,26 @@ public class ChangeFlowBiz {
changeExecUserEmail, changeExecDepartment);
}
}
/**
* 检查主工单下所有子单是否都已审批通过(供主工单流转时调用)
* 条件:节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true
*
* @param changeRecordId 主工单ID
* @return true 表示所有子单都已审批通过
*/
public boolean checkAllSubFlowsApprovedForMainFlow(Long changeRecordId) {
// 查询该主工单下所有子单
List<ChangeSubFlowRecord> allSubFlows = changeSubFlowRecordMapper.selectByChangeRecordId(changeRecordId);
if (CollectionUtils.isEmpty(allSubFlows)) {
return false;
}
// 检查是否所有子单都满足条件:节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true
return allSubFlows.stream().allMatch(subFlow ->
ChangeFlowEnum.CHANGE_SUB_FLOW_EXE.getNodeId().equals(subFlow.getSubFlowNode())
&& Boolean.TRUE.equals(subFlow.getChangePlanApproved())
);
}
}
......@@ -28,6 +28,7 @@ import com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper;
import com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper;
import com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeExecConfigReq;
import com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeFlowListQueryReq;
import com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeFlowSubmitReq;
import com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowCreateReq;
import com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowListQueryReq;
import com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowSubmitReq;
......@@ -261,6 +262,7 @@ public class ChangeSubFlowBiz {
subFlowRecord.setStatus(ChangeSubFlowStatusEnum.WAIT_APPROVE_CHANGE_PLAN.getStatus());
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlowRecord);
// todo:非名单中部门无需审批,行动人确认提交后邮件同步负责人上级对应变更信息
return autoNextNodeId;
case CHANGE_SUB_FLOW_SUBMIT:
......@@ -296,16 +298,51 @@ public class ChangeSubFlowBiz {
return approveNodeId;
case CHANGE_SUB_FLOW_EXE:
// 执行行动方案节点,直接提交到提交执行结果节点
String confirmNodeId = flowService.submitFlow(subFlowId, flowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), true,
FlowxOperationEnum.SUBMIT.getName(), "提交工单", subFlowRecord.getCreateTime());
// 更新行动工单节点ID
subFlowRecord.setSubFlowNode(confirmNodeId);
// TODO: 根据业务逻辑设置状态 subFlowRecord.setStatus(...)
// 审批变更方案节点
Boolean execApproved = changeSubFlowSubmitReq.getApproved();
if (execApproved == null) {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "审批结果不能为空");
}
if (!execApproved) {
// 审批不通过,拒绝原因必填
String execRejectReason = changeSubFlowSubmitReq.getRejectReason();
if (StringUtils.isBlank(execRejectReason)) {
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST, "拒绝原因不能为空");
}
subFlowRecord.setChangePlanApproved(false);
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);
} else {
// 审批通过,只标记 changePlanApproved=true,暂不更新状态和流转工单
subFlowRecord.setChangePlanApproved(true);
subFlowRecord.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlowRecord);
return confirmNodeId;
log.info("[CHANGE_SUB_FLOW_EXE] 审批通过,subFlowId:{}, 标记changePlanApproved=true", subFlowId);
// 检查该主工单下所有子单是否都已审批通过
if (changeFlowBiz.checkAllSubFlowsApprovedForMainFlow(subFlowRecord.getChangeRecordId())) {
// 所有子单都通过,批量流转所有子单并更新状态
batchSubmitAllSubFlows(subFlowRecord.getChangeRecordId(), flowDataDTO, uid, content);
log.info("[CHANGE_SUB_FLOW_EXE] 所有子单均已审批通过,批量流转子单到下一节点");
// 所有子单流转完成后,流转主工单
ChangeRecord mainRecord = changeRecordMapper.selectByPrimaryKey(subFlowRecord.getChangeRecordId());
if (mainRecord != null) {
ChangeFlowSubmitReq mainFlowSubmitReq = new ChangeFlowSubmitReq();
mainFlowSubmitReq.setFlowId(mainRecord.getFlowId());
mainFlowSubmitReq.setCurrentNodeId(mainRecord.getFlowNode());
changeFlowBiz.submit(mainFlowSubmitReq);
log.info("[CHANGE_SUB_FLOW_EXE] 主工单流转成功,changeRecordId:{}, flowId:{}",
subFlowRecord.getChangeRecordId(), mainRecord.getFlowId());
}
}
}
return subFlowRecord.getSubFlowNode();
case CHANGE_SUB_FLOW_CONFIRM:
// 提交执行结果节点,需要填写完成时间和完成情况
......@@ -382,6 +419,45 @@ public class ChangeSubFlowBiz {
}
/**
* 批量流转所有子单到下一节点,并流转主工单
*
* @param changeRecordId 主工单ID
* @param flowDataDTO 流程数据
* @param uid 操作人
* @param content 内容
*/
private void batchSubmitAllSubFlows(Long changeRecordId, FlowDataDTO flowDataDTO, String uid, Object content) {
// 查询该主工单下所有子单
List<ChangeSubFlowRecord> allSubFlows = changeSubFlowRecordMapper.selectByChangeRecordId(changeRecordId);
if (CollectionUtils.isEmpty(allSubFlows)) {
return;
}
// 批量流转所有子单
for (ChangeSubFlowRecord subFlow : allSubFlows) {
try {
// 提交子单流程到下一节点
String nextNodeId = flowService.submitFlow(subFlow.getSubFlowId(), flowDataDTO, uid,
ChangeFlowEnum.CHANGE_SUB_FLOW.getTopoId(), JSON.toJSONString(content), true,
FlowxOperationEnum.SUBMIT.getName(), "所有子单审批通过,自动流转", subFlow.getCreateTime());
// 更新子单节点和状态
subFlow.setSubFlowNode(nextNodeId);
subFlow.setStatus(ChangeSubFlowStatusEnum.WAIT_SUBMIT_RESULT.getStatus());
subFlow.setUpdateTime(DateUtils.getCurrentTime());
changeSubFlowRecordService.update(subFlow);
log.info("[batchSubmitAllSubFlows] 子单流转成功,subFlowId:{}, nextNodeId:{}",
subFlow.getSubFlowId(), nextNodeId);
} catch (Exception e) {
log.error("[batchSubmitAllSubFlows] 子单流转失败,subFlowId:{}", subFlow.getSubFlowId(), e);
throw ExceptionFactory.createBiz(ResponseCode.BAD_REQUEST,
String.format("子单[%s]流转失败:%s", subFlow.getSubFlowId(), e.getMessage()));
}
}
}
/**
* 根据变更行动工单ID查询详情
* 说明:展示内容和主单的detail一样,但行动项只展示该变更行动工单下绑定的行动项
*
......
......@@ -79,6 +79,11 @@ public class ChangeSubFlowRecord {
private String changeCommander;
/**
* 变更方案是否审批通过(仅在审批变更方案节点使用)
*/
private Boolean changePlanApproved;
/**
* 拒绝原因(审批不通过时填写)
*/
private String rejectReason;
......
......@@ -11,13 +11,14 @@
<result column="change_exec_user_email" jdbcType="VARCHAR" property="changeExecUserEmail" />
<result column="change_exec_department" jdbcType="VARCHAR" property="changeExecDepartment" />
<result column="change_commander" jdbcType="VARCHAR" property="changeCommander" />
<result column="change_plan_approved" jdbcType="TINYINT" property="changePlanApproved" />
<result column="reject_reason" jdbcType="VARCHAR" property="rejectReason" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
</resultMap>
<sql id="Base_Column_List">
id, change_record_id, sub_flow_id, sub_flow_node, status, approver, change_exec_user_email, change_exec_department, change_commander, reject_reason, create_time, update_time
id, change_record_id, sub_flow_id, sub_flow_node, status, approver, change_exec_user_email, change_exec_department, change_commander, change_plan_approved, reject_reason, create_time, update_time
</sql>
<select id="selectByCondition" resultMap="BaseResultMap" parameterType="com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowListQueryReq">
......
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