From 793db8d7e94d64a3ac8d2c4e28ef2ea5e4b5653c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B8=B8=E7=86=9F=E5=90=B4=E5=BD=A6=E7=A5=96?= Date: Tue, 16 Jun 2026 18:05:48 +0800 Subject: [PATCH] 1 --- .../mapper/ErfFlowInstanceMapper.java | 51 +-- .../service/ErfFlowInstanceService.java | 6 + .../impl/ErfFlowInstanceServiceImpl.java | 194 ++++++--- .../mapper/workFlow/ErfFlowInstanceMapper.xml | 375 +++++++++--------- 4 files changed, 354 insertions(+), 272 deletions(-) diff --git a/src/main/java/com/xujie/modules/workFlow/mapper/ErfFlowInstanceMapper.java b/src/main/java/com/xujie/modules/workFlow/mapper/ErfFlowInstanceMapper.java index 6fbbf7c..0d13270 100644 --- a/src/main/java/com/xujie/modules/workFlow/mapper/ErfFlowInstanceMapper.java +++ b/src/main/java/com/xujie/modules/workFlow/mapper/ErfFlowInstanceMapper.java @@ -29,7 +29,7 @@ public interface ErfFlowInstanceMapper extends BaseMapper { * 查询节点实例列表 */ List searchNodeInstanceList(@Param("applyNo") String applyNo, - @Param("site") String site, @Param("orderType") String orderType); + @Param("site") String site, @Param("orderType") String orderType); /** * 插入流程实例 @@ -45,73 +45,78 @@ public interface ErfFlowInstanceMapper extends BaseMapper { * 更新流程实例状态 */ void updateInstanceStatus(@Param("applyNo") String applyNo, @Param("site") String site, - @Param("orderType") String orderType, @Param("status") String status, - @Param("currentNodeCode") String currentNodeCode); + @Param("orderType") String orderType, @Param("status") String status, + @Param("currentNodeCode") String currentNodeCode); /** * 更新流程实例完成 */ void updateInstanceCompleted(@Param("applyNo") String applyNo, @Param("site") String site, - @Param("orderType") String orderType); + @Param("orderType") String orderType); /** * 更新节点实例状态 */ void updateNodeInstanceStatus(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, - @Param("attemptNo") Integer attemptNo, @Param("taskSeq") Integer taskSeq, @Param("site") String site, - @Param("orderType") String orderType, @Param("status") String status, @Param("comment") String comment, - @Param("specialRelease") String specialRelease); + @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType, + @Param("status") String status, @Param("comment") String comment, @Param("specialRelease") String specialRelease, + @Param("assigneeUsername") String assigneeUsername); /** * 获取节点实例详情 */ ErfFlowNodeInstanceData getNodeInstanceDetail(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, - @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType); + @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType); /** * 获取流程实例 */ ErfFlowInstanceData getInstanceByApplyNo(@Param("applyNo") String applyNo, @Param("site") String site, - @Param("orderType") String orderType); + @Param("orderType") String orderType); /** * 获取当前节点的最大尝试次数 */ Integer getMaxAttemptNo(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, - @Param("site") String site, @Param("orderType") String orderType); + @Param("site") String site, @Param("orderType") String orderType); /** - * 获取待审批的节点实例(按当前登录用户名/展示名匹配审批人) - rqrq + * 获取待审批的节点实例 */ ErfFlowNodeInstanceData getPendingNodeInstance(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, - @Param("site") String site, @Param("orderType") String orderType, - @Param("assigneeUsername") String assigneeUsername, @Param("assigneeDisplayName") String assigneeDisplayName); + @Param("site") String site, @Param("orderType") String orderType, + @Param("assigneeUsername") String assigneeUsername, @Param("assigneeName") String assigneeName); /** - * 统计节点当前轮次下仍为待办的任务数 - rqrq + * 指定节点下仍为 PENDING 的任务总数(不区分审批人,用于先判断是否有待办) */ - int countPendingNodeTasks(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, - @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType); + int countPendingForNode(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, + @Param("site") String site, @Param("orderType") String orderType); /** - * 将同节点同轮次下除指定序号外的待办任务批量更新为指定状态 - rqrq + * 当前节点、当前轮次下仍为待办的任务数(会签 ALL 用) */ - void updateOtherPendingNodeTasks(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, - @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType, - @Param("excludeTaskSeq") Integer excludeTaskSeq, @Param("newStatus") String newStatus, - @Param("comment") String comment); + int countPendingNodeInstances(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, + @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType); + + /** + * 或签 ANY:当前审批人已处理完毕后,将其余仍为 PENDING 的同节点同轮次任务批量关闭(不删行,便于审计) + */ + void skipRemainingPendingOnSameNodeAttempt(@Param("applyNo") String applyNo, @Param("nodeCode") String nodeCode, + @Param("attemptNo") Integer attemptNo, @Param("site") String site, @Param("orderType") String orderType, + @Param("targetStatus") String targetStatus, @Param("comment") String comment); /** * 删除指定单据的所有节点实例 - rqrq */ void deleteNodeInstancesByApplyNo(@Param("applyNo") String applyNo, @Param("site") String site, - @Param("orderType") String orderType); + @Param("orderType") String orderType); /** * 重启流程实例 - rqrq */ void restartInstance(@Param("applyNo") String applyNo, @Param("site") String site, - @Param("orderType") String orderType, @Param("currentNodeCode") String currentNodeCode); + @Param("orderType") String orderType, @Param("currentNodeCode") String currentNodeCode); ErfFlowInstance getInstanceByOrderRef1(@Param("orderRef1") String orderRef1, @Param("site") String site,@Param("orderType") String orderType); diff --git a/src/main/java/com/xujie/modules/workFlow/service/ErfFlowInstanceService.java b/src/main/java/com/xujie/modules/workFlow/service/ErfFlowInstanceService.java index bfe1998..aebdf88 100644 --- a/src/main/java/com/xujie/modules/workFlow/service/ErfFlowInstanceService.java +++ b/src/main/java/com/xujie/modules/workFlow/service/ErfFlowInstanceService.java @@ -46,4 +46,10 @@ public interface ErfFlowInstanceService { List getNodeInstanceList(String orderRef1, String site, String orderType); ErfFlowNodeInstanceData getWaitApproveNode(String applyNo,String site,String orderType); + + /** + * 根据审批单号获取流程实例 + */ + ErfFlowInstanceData getInstanceByApplyNo(String applyNo, String site, String orderType); + } diff --git a/src/main/java/com/xujie/modules/workFlow/service/impl/ErfFlowInstanceServiceImpl.java b/src/main/java/com/xujie/modules/workFlow/service/impl/ErfFlowInstanceServiceImpl.java index ac1167d..ab83ffb 100644 --- a/src/main/java/com/xujie/modules/workFlow/service/impl/ErfFlowInstanceServiceImpl.java +++ b/src/main/java/com/xujie/modules/workFlow/service/impl/ErfFlowInstanceServiceImpl.java @@ -18,9 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * 流程实例Service实现类 - rqrq @@ -36,7 +34,6 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl approverList = erfFlowTemplateMapper.getApproverListByNodeId(firstApproveNode.getId()); + if (approverList == null || approverList.isEmpty()) { + throw new RuntimeException("流程配置错误:审批节点未配置审批人"); + } + validateApproverUsernamesForNode(approverList); + // 创建流程实例 - rqrq ErfFlowInstance instance = new ErfFlowInstance(); instance.setApplyNo(applyNo); @@ -101,8 +105,23 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl approverList = erfFlowTemplateMapper.getApproverListByNodeId(node.getId()); - if (approverList == null || approverList.isEmpty()) { - throw new RuntimeException("流程配置错误:审批节点未配置审批人"); - } - int taskSeq = 1; + // 获取审批人并创建节点实例 + List approverList = erfFlowTemplateMapper.getApproverListByNodeId(nextNode.getId()); + validateApproverUsernamesForNode(approverList); for (ErfFlowNodeApproverData approver : approverList) { ErfFlowNodeInstance nodeInstance = new ErfFlowNodeInstance(); - nodeInstance.setApplyNo(applyNo); - nodeInstance.setNodeCode(node.getNodeCode()); - nodeInstance.setAttemptNo(attemptNo); - nodeInstance.setTaskSeq(taskSeq++); - nodeInstance.setSite(site); - nodeInstance.setOrderType(orderType); - nodeInstance.setDepartmentId(node.getDepartmentId()); - nodeInstance.setDepartmentName(node.getDepartmentName()); - nodeInstance.setAssigneeUsername(approver.getApproverUsername()); + nodeInstance.setApplyNo(instance.getApplyNo()); + nodeInstance.setNodeCode(nextNode.getNodeCode()); + nodeInstance.setAttemptNo(1); + nodeInstance.setSite(instance.getSite()); + nodeInstance.setOrderType(instance.getOrderType()); + nodeInstance.setAssigneeUsername(resolveApproverUsername(approver)); + // 设置部门信息(从节点配置获取)- rqrq + nodeInstance.setDepartmentId(nextNode.getDepartmentId()); + nodeInstance.setDepartmentName(nextNode.getDepartmentName()); nodeInstance.setAssigneeName(approver.getApproverName()); nodeInstance.setStatus("PENDING"); nodeInstance.setSpecialRelease("N"); @@ -234,6 +251,33 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl approverList) { + if (approverList == null || approverList.size() <= 1) { + return; + } + Set seen = new HashSet<>(); + for (ErfFlowNodeApproverData approver : approverList) { + String key = resolveApproverUsername(approver); + if (key.isEmpty()) { + throw new RuntimeException("会签/多人节点须为每位审批人配置登录账号(approver_username)"); + } + if (!seen.add(key)) { + throw new RuntimeException("同一审批节点内审批人登录账号不能重复:" + key); + } + } + } + @Override public ErfFlowTemplateData getFlowPreview(String flowCode, Integer flowVersion, String site) { System.out.println("获取流程预览,流程编码:" + flowCode + ",版本:" + flowVersion); @@ -273,7 +317,7 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl approverList = erfFlowTemplateMapper.getApproverListByNodeId(firstApproveNode.getId()); + if (approverList == null || approverList.isEmpty()) { + throw new RuntimeException("流程配置错误:审批节点未配置审批人"); + } + validateApproverUsernamesForNode(approverList); + // 删除原有的所有节点实例 erfFlowInstanceMapper.deleteNodeInstancesByApplyNo(applyNo, site, orderType); // 重置流程实例状态 erfFlowInstanceMapper.restartInstance(applyNo, site, orderType, firstApproveNode.getNodeCode()); - insertPendingNodeInstances(applyNo, site, orderType, 1, firstApproveNode); + // 创建第一个节点实例(为每个审批人创建一条记录) + for (ErfFlowNodeApproverData approver : approverList) { + ErfFlowNodeInstance nodeInstance = new ErfFlowNodeInstance(); + nodeInstance.setApplyNo(applyNo); + nodeInstance.setNodeCode(firstApproveNode.getNodeCode()); + nodeInstance.setAttemptNo(1); + nodeInstance.setSite(site); + nodeInstance.setOrderType(orderType); + nodeInstance.setAssigneeUsername(resolveApproverUsername(approver)); + // 设置部门信息(从节点配置获取)- rqrq + nodeInstance.setDepartmentId(firstApproveNode.getDepartmentId()); + nodeInstance.setDepartmentName(firstApproveNode.getDepartmentName()); + nodeInstance.setAssigneeName(approver.getApproverName()); + nodeInstance.setStatus("PENDING"); + nodeInstance.setSpecialRelease("N"); + erfFlowInstanceMapper.insertNodeInstance(nodeInstance); + } System.out.println("重新审批流程实例结束"); } @@ -340,5 +407,10 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl - - SELECT - ni.apply_no, - ni.node_code, - ni.attempt_no, - ni.task_seq, - ni.site, - ni.order_type, - ni.department_id, - ni.department_name, - ni.assignee_user_id, - ni.assignee_username, - ni.assignee_name, - ni.status, - ni.comment, - ni.special_release, - ni.receive_time, - ni.complete_time, - ni.duration_seconds, - n.node_name, - n.node_order, - n.approve_type + ni.apply_no, + ni.node_code, + ni.attempt_no, + ni.site, + ni.order_type, + ni.assignee_username, + ni.department_id, + ni.department_name, + ni.assignee_user_id, + ni.assignee_name, + ni.status, + ni.comment, + ni.special_release, + ni.receive_time, + ni.complete_time, + ni.duration_seconds, + n.node_name, + n.node_order, + n.approve_type FROM erf_flow_node_instance ni LEFT JOIN erf_flow_instance i ON i.apply_no = ni.apply_no AND i.site = ni.site AND i.order_type = ni.order_type LEFT JOIN erf_flow_node n ON n.flow_code = i.flow_code AND n.flow_version = i.flow_version - AND n.site = i.site AND n.node_code = ni.node_code + AND n.site = i.site AND n.node_code = ni.node_code WHERE ni.apply_no = #{applyNo} - AND ni.site = #{site} - AND ni.order_type = #{orderType} - ORDER BY n.node_order, ni.attempt_no, ni.task_seq + AND ni.site = #{site} + AND ni.order_type = #{orderType} + ORDER BY n.node_order, ni.attempt_no INSERT INTO erf_flow_instance ( - apply_no, order_ref1, site, order_type, flow_code, flow_version, - status, current_node_code, start_time + apply_no, order_ref1, site, order_type, flow_code, flow_version, + status, current_node_code, start_time ) VALUES ( - #{applyNo}, #{orderRef1}, #{site}, #{orderType}, #{flowCode}, #{flowVersion}, - #{status}, #{currentNodeCode}, GETDATE() + #{applyNo}, #{orderRef1}, #{site}, #{orderType}, #{flowCode}, #{flowVersion}, + #{status}, #{currentNodeCode}, GETDATE() ) - INSERT INTO erf_flow_node_instance ( - apply_no, node_code, attempt_no, task_seq, site, order_type, - department_id, department_name, assignee_user_id, assignee_username, assignee_name, status, receive_time + apply_no, node_code, attempt_no, site, order_type, assignee_username, + department_id, department_name, assignee_user_id, assignee_name, status, receive_time, special_release ) VALUES ( - #{applyNo}, #{nodeCode}, #{attemptNo}, #{taskSeq}, #{site}, #{orderType}, - #{departmentId}, #{departmentName}, #{assigneeUserId}, #{assigneeUsername}, #{assigneeName}, #{status}, GETDATE() + #{applyNo}, #{nodeCode}, #{attemptNo}, #{site}, #{orderType}, #{assigneeUsername}, + #{departmentId}, #{departmentName}, #{assigneeUserId}, #{assigneeName}, #{status}, GETDATE(), #{specialRelease} ) @@ -103,89 +100,87 @@ UPDATE erf_flow_instance SET status = #{status}, - current_node_code = #{currentNodeCode} + current_node_code = #{currentNodeCode} WHERE apply_no = #{applyNo} - AND site = #{site} - AND order_type = #{orderType} + AND site = #{site} + AND order_type = #{orderType} UPDATE erf_flow_instance SET status = 'COMPLETED', - end_time = GETDATE() + end_time = GETDATE() WHERE apply_no = #{applyNo} - AND site = #{site} - AND order_type = #{orderType} + AND site = #{site} + AND order_type = #{orderType} UPDATE erf_flow_node_instance SET status = #{status}, - comment = #{comment}, - special_release = #{specialRelease}, - complete_time = GETDATE() + comment = #{comment}, + special_release = #{specialRelease}, + complete_time = GETDATE() WHERE apply_no = #{applyNo} - AND node_code = #{nodeCode} - AND attempt_no = #{attemptNo} - AND task_seq = #{taskSeq} - AND site = #{site} - AND order_type = #{orderType} + AND node_code = #{nodeCode} + AND attempt_no = #{attemptNo} + AND site = #{site} + AND order_type = #{orderType} + AND assignee_username = #{assigneeUsername} @@ -193,120 +188,123 @@ SELECT ISNULL(MAX(attempt_no), 0) FROM erf_flow_node_instance WHERE apply_no = #{applyNo} - AND node_code = #{nodeCode} - AND site = #{site} - AND order_type = #{orderType} + AND node_code = #{nodeCode} + AND site = #{site} + AND order_type = #{orderType} - - + - - SELECT COUNT(1) FROM erf_flow_node_instance WHERE apply_no = #{applyNo} - AND node_code = #{nodeCode} - AND attempt_no = #{attemptNo} - AND site = #{site} - AND order_type = #{orderType} - AND status = 'PENDING' + AND node_code = #{nodeCode} + AND site = #{site} + AND order_type = #{orderType} + AND status = 'PENDING' - - + + + UPDATE erf_flow_node_instance - SET status = #{newStatus}, - comment = #{comment}, - complete_time = GETDATE() + SET status = #{targetStatus}, + comment = #{comment}, + complete_time = GETDATE() WHERE apply_no = #{applyNo} - AND node_code = #{nodeCode} - AND attempt_no = #{attemptNo} - AND site = #{site} - AND order_type = #{orderType} - AND status = 'PENDING' - AND task_seq <> #{excludeTaskSeq} + AND node_code = #{nodeCode} + AND attempt_no = #{attemptNo} + AND site = #{site} + AND order_type = #{orderType} + AND status = 'PENDING' - DELETE FROM erf_flow_node_instance WHERE apply_no = #{applyNo} - AND site = #{site} - AND order_type = #{orderType} + AND site = #{site} + AND order_type = #{orderType} UPDATE erf_flow_instance SET status = 'RUNNING', - current_node_code = #{currentNodeCode}, - start_time = GETDATE(), - end_time = NULL + current_node_code = #{currentNodeCode}, + start_time = GETDATE(), + end_time = NULL WHERE apply_no = #{applyNo} - AND site = #{site} - AND order_type = #{orderType} + AND site = #{site} + AND order_type = #{orderType} SELECT apply_no, order_ref1, site, order_type, flow_code, flow_version, - status, current_node_code + status, current_node_code FROM erf_flow_instance WHERE order_ref1 = #{orderRef1} - AND site = #{site} - AND order_type = #{orderType} + AND site = #{site} + AND order_type = #{orderType} +