|
|
|
@ -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<ErfFlowInstanceMappe |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private SrmSupplierMapper srmSupplierMapper; |
|
|
|
|
|
|
|
@Override |
|
|
|
public PageUtils searchInstanceList(ErfFlowInstanceData data) { |
|
|
|
System.out.println("开始查询流程实例列表"); |
|
|
|
@ -89,6 +86,13 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl<ErfFlowInstanceMappe |
|
|
|
throw new RuntimeException("流程配置错误:未找到审批节点"); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取审批人 |
|
|
|
List<ErfFlowNodeApproverData> 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<ErfFlowInstanceMappe |
|
|
|
instance.setCurrentNodeCode(firstApproveNode.getNodeCode()); |
|
|
|
erfFlowInstanceMapper.insertInstance(instance); |
|
|
|
|
|
|
|
//创建节点实例(会签/或签为每个审批人一行,主键含 task_seq) - rqrq |
|
|
|
insertPendingNodeInstances(applyNo, site, orderType, 1, firstApproveNode); |
|
|
|
// 创建节点实例(为每个审批人创建一条记录;主键含 assignee_username) |
|
|
|
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("创建流程实例结束"); |
|
|
|
return applyNo; |
|
|
|
@ -118,8 +137,6 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl<ErfFlowInstanceMappe |
|
|
|
if (currentUser == null) { |
|
|
|
throw new RuntimeException("获取当前用户信息失败,请重新登录"); |
|
|
|
} |
|
|
|
String currentUserDisplay = currentUser.getUserDisplay(); |
|
|
|
|
|
|
|
// 获取流程实例 |
|
|
|
ErfFlowInstanceData instance = erfFlowInstanceMapper.getInstanceByApplyNo( |
|
|
|
data.getApplyNo(), data.getSite(), data.getOrderType()); |
|
|
|
@ -127,47 +144,57 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl<ErfFlowInstanceMappe |
|
|
|
throw new RuntimeException("流程实例不存在"); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取当前登录用户对应的待审批任务(会签多人时按用户名匹配) - rqrq |
|
|
|
String operatorUsername = currentUser.getUsername() != null ? currentUser.getUsername() : ""; |
|
|
|
String operatorDisplay = currentUser.getUserDisplay() != null ? currentUser.getUserDisplay() : ""; |
|
|
|
// 先判断该节点是否还有待办(不区分审批人) |
|
|
|
int pendingOnNode = erfFlowInstanceMapper.countPendingForNode( |
|
|
|
data.getApplyNo(), data.getNodeCode(), data.getSite(), data.getOrderType()); |
|
|
|
if (pendingOnNode <= 0) { |
|
|
|
throw new RuntimeException("未找到待审批的节点"); |
|
|
|
} |
|
|
|
// 再匹配当前登录人自己的任务(会签/或签多人时每人一行) |
|
|
|
ErfFlowNodeInstanceData nodeInstance = erfFlowInstanceMapper.getPendingNodeInstance( |
|
|
|
data.getApplyNo(), data.getNodeCode(), data.getSite(), data.getOrderType(), |
|
|
|
operator, currentUserDisplay); |
|
|
|
operatorUsername, operatorDisplay); |
|
|
|
if (nodeInstance == null) { |
|
|
|
throw new RuntimeException("未找到待审批的节点"); |
|
|
|
throw new RuntimeException("该节点不需要您审批"); |
|
|
|
} |
|
|
|
|
|
|
|
if (nodeInstance.getAssigneeUsername() != null && !nodeInstance.getAssigneeUsername().equals(operator)) { |
|
|
|
throw new RuntimeException("您不是该节点的审批人,无法进行审批操作"); |
|
|
|
} |
|
|
|
if (nodeInstance.getAssigneeUsername() == null && nodeInstance.getAssigneeName() != null |
|
|
|
&& !nodeInstance.getAssigneeName().equals(currentUserDisplay)) { |
|
|
|
throw new RuntimeException("您不是该节点的审批人,无法进行审批操作"); |
|
|
|
} |
|
|
|
String assigneeUsernameKey = nodeInstance.getAssigneeUsername() != null ? nodeInstance.getAssigneeUsername() : ""; |
|
|
|
|
|
|
|
// 更新节点实例状态(含特殊放行标记)- rqrq |
|
|
|
erfFlowInstanceMapper.updateNodeInstanceStatus( |
|
|
|
data.getApplyNo(), data.getNodeCode(), nodeInstance.getAttemptNo(), nodeInstance.getTaskSeq(), |
|
|
|
data.getSite(), data.getOrderType(), data.getAction(), data.getComment(), data.getSpecialRelease()); |
|
|
|
data.getApplyNo(), data.getNodeCode(), nodeInstance.getAttemptNo(), |
|
|
|
data.getSite(), data.getOrderType(), data.getAction(), data.getComment(), data.getSpecialRelease(), |
|
|
|
assigneeUsernameKey); |
|
|
|
|
|
|
|
// 处理审批结果 |
|
|
|
if ("APPROVED".equals(data.getAction())) { |
|
|
|
String approveType = nodeInstance.getApproveType() != null ? nodeInstance.getApproveType() : "SINGLE"; |
|
|
|
nodeInstance.setSpecialRelease(data.getSpecialRelease()); |
|
|
|
if ("ALL".equals(approveType)) { |
|
|
|
int pendingLeft = erfFlowInstanceMapper.countPendingNodeTasks(data.getApplyNo(), data.getNodeCode(), |
|
|
|
nodeInstance.getAttemptNo(), data.getSite(), data.getOrderType()); |
|
|
|
if (pendingLeft == 0) { |
|
|
|
activateNextNode(instance, nodeInstance); |
|
|
|
} |
|
|
|
} else if ("ANY".equals(approveType)) { |
|
|
|
erfFlowInstanceMapper.updateOtherPendingNodeTasks(data.getApplyNo(), data.getNodeCode(), |
|
|
|
nodeInstance.getAttemptNo(), data.getSite(), data.getOrderType(), nodeInstance.getTaskSeq(), |
|
|
|
"SKIPPED", "或签:已有他人审批通过"); |
|
|
|
activateNextNode(instance, nodeInstance); |
|
|
|
} else { |
|
|
|
// 或签 ANY:一人通过即流转;其余待办关闭为 SKIPPED(当前行已变为 APPROVED,不在 PENDING 中) |
|
|
|
if ("ANY".equals(nodeInstance.getApproveType())) { |
|
|
|
erfFlowInstanceMapper.skipRemainingPendingOnSameNodeAttempt( |
|
|
|
data.getApplyNo(), data.getNodeCode(), nodeInstance.getAttemptNo(), |
|
|
|
data.getSite(), data.getOrderType(), "SKIPPED", "或签:已由他人审批通过"); |
|
|
|
} |
|
|
|
// 会签 ALL:须本节点本 attempt 下无其它 PENDING 才流转 |
|
|
|
boolean advance = true; |
|
|
|
if ("ALL".equals(nodeInstance.getApproveType())) { |
|
|
|
int pendingLeft = erfFlowInstanceMapper.countPendingNodeInstances( |
|
|
|
data.getApplyNo(), data.getNodeCode(), nodeInstance.getAttemptNo(), |
|
|
|
data.getSite(), data.getOrderType()); |
|
|
|
advance = pendingLeft <= 0; |
|
|
|
} |
|
|
|
if (advance) { |
|
|
|
nodeInstance.setSpecialRelease(data.getSpecialRelease()); |
|
|
|
activateNextNode(instance, nodeInstance); |
|
|
|
} |
|
|
|
} else if ("REJECTED".equals(data.getAction())) { |
|
|
|
erfFlowInstanceMapper.updateOtherPendingNodeTasks(data.getApplyNo(), data.getNodeCode(), |
|
|
|
nodeInstance.getAttemptNo(), data.getSite(), data.getOrderType(), nodeInstance.getTaskSeq(), |
|
|
|
"CANCELLED", "节点已驳回,任务关闭"); |
|
|
|
if ("ANY".equals(nodeInstance.getApproveType())) { |
|
|
|
erfFlowInstanceMapper.skipRemainingPendingOnSameNodeAttempt( |
|
|
|
data.getApplyNo(), data.getNodeCode(), nodeInstance.getAttemptNo(), |
|
|
|
data.getSite(), data.getOrderType(), "SKIPPED", "或签:流程已驳回,待办关闭"); |
|
|
|
} |
|
|
|
// 终止流程 |
|
|
|
erfFlowInstanceMapper.updateInstanceStatus( |
|
|
|
data.getApplyNo(), data.getSite(), data.getOrderType(), |
|
|
|
"TERMINATED", nodeInstance.getNodeCode()); |
|
|
|
@ -203,30 +230,20 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl<ErfFlowInstanceMappe |
|
|
|
erfFlowInstanceMapper.updateInstanceStatus(instance.getApplyNo(), instance.getSite(), |
|
|
|
instance.getOrderType(), "RUNNING", nextNode.getNodeCode()); |
|
|
|
|
|
|
|
insertPendingNodeInstances(instance.getApplyNo(), instance.getSite(), instance.getOrderType(), 1, nextNode); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 按节点定义生成待办任务行(每人一行) - rqrq |
|
|
|
*/ |
|
|
|
private void insertPendingNodeInstances(String applyNo, String site, String orderType, int attemptNo, |
|
|
|
ErfFlowNodeData node) { |
|
|
|
List<ErfFlowNodeApproverData> approverList = erfFlowTemplateMapper.getApproverListByNodeId(node.getId()); |
|
|
|
if (approverList == null || approverList.isEmpty()) { |
|
|
|
throw new RuntimeException("流程配置错误:审批节点未配置审批人"); |
|
|
|
} |
|
|
|
int taskSeq = 1; |
|
|
|
// 获取审批人并创建节点实例 |
|
|
|
List<ErfFlowNodeApproverData> 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<ErfFlowInstanceMappe |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static String resolveApproverUsername(ErfFlowNodeApproverData approver) { |
|
|
|
String u = approver.getApproverUsername(); |
|
|
|
if (u == null) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
return u.trim(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 多人节点须配置互不相同的 approver_username,否则无法落库(主键冲突)。 |
|
|
|
*/ |
|
|
|
private void validateApproverUsernamesForNode(List<ErfFlowNodeApproverData> approverList) { |
|
|
|
if (approverList == null || approverList.size() <= 1) { |
|
|
|
return; |
|
|
|
} |
|
|
|
Set<String> 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<ErfFlowInstanceMappe |
|
|
|
} |
|
|
|
|
|
|
|
// 验证状态:只有已完成或已终止的流程才能重新审批 |
|
|
|
if (!"COMPLETED".equals(instance.getStatus()) && !"TERMINATED".equals(instance.getStatus())) { |
|
|
|
if (!"COMPLETED".equals(instance.getStatus()) && !"TERMINATED".equals(instance.getStatus()) && !"REJECTED".equals(instance.getStatus())) { |
|
|
|
throw new RuntimeException("只有已完成或已终止的流程才能重新审批"); |
|
|
|
} |
|
|
|
|
|
|
|
@ -304,13 +348,36 @@ public class ErfFlowInstanceServiceImpl extends ServiceImpl<ErfFlowInstanceMappe |
|
|
|
throw new RuntimeException("流程配置错误:未找到审批节点"); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取审批人 |
|
|
|
List<ErfFlowNodeApproverData> 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<ErfFlowInstanceMappe |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public ErfFlowInstanceData getInstanceByApplyNo(String applyNo, String site, String orderType) { |
|
|
|
return erfFlowInstanceMapper.getInstanceByApplyNo(applyNo, site, orderType); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |