Files
wenzi/src/main/java/com/mosquito/project/permission/ApprovalFlowService.java

375 lines
14 KiB
Java
Raw Normal View History

package com.mosquito.project.permission;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
/**
* 审批流服务
*/
@Service
public class ApprovalFlowService {
// 审批状态常量
public static final String STATUS_PENDING = "PENDING";
public static final String STATUS_APPROVED = "APPROVED";
public static final String STATUS_REJECTED = "REJECTED";
public static final String STATUS_PROCESSING = "PROCESSING";
public static final String STATUS_CANCELLED = "CANCELLED";
// 审批动作
public static final String ACTION_SUBMIT = "SUBMIT";
public static final String ACTION_APPROVE = "APPROVE";
public static final String ACTION_REJECT = "REJECT";
public static final String ACTION_TRANSFER = "TRANSFER";
private final ApprovalFlowRepository flowRepository;
private final ApprovalRecordRepository recordRepository;
private final ApprovalHistoryRepository historyRepository;
private final ObjectMapper objectMapper;
public ApprovalFlowService(
ApprovalFlowRepository flowRepository,
ApprovalRecordRepository recordRepository,
ApprovalHistoryRepository historyRepository,
ObjectMapper objectMapper) {
this.flowRepository = flowRepository;
this.recordRepository = recordRepository;
this.historyRepository = historyRepository;
this.objectMapper = objectMapper;
}
/**
* 提交审批申请
*/
@Transactional
public Map<String, Object> submitApproval(Long flowId, String bizType, Long bizId,
String title, Long applicantId, String applyReason) {
// 获取审批流程配置
Optional<SysApprovalFlow> flowOpt = flowRepository.findById(flowId);
if (!flowOpt.isPresent()) {
throw new IllegalArgumentException("审批流程不存在: " + flowId);
}
SysApprovalFlow flow = flowOpt.get();
if (!"ENABLED".equals(flow.getStatus())) {
throw new IllegalArgumentException("审批流程已禁用");
}
// 检查是否已有待处理的审批
List<SysApprovalRecord> existing = recordRepository.findByBizTypeAndBizId(bizType, bizId);
for (SysApprovalRecord record : existing) {
if (STATUS_PENDING.equals(record.getStatus()) || STATUS_PROCESSING.equals(record.getStatus())) {
throw new IllegalArgumentException("该业务已存在待处理的审批申请");
}
}
// 解析审批节点,获取第一个审批人
Long firstApproverId = resolveFirstApprover(flow, applicantId);
// 创建审批记录
SysApprovalRecord record = new SysApprovalRecord();
record.setFlowId(flowId);
record.setBizType(bizType);
record.setBizId(bizId);
record.setCurrentNode(0);
record.setApplicantId(applicantId);
record.setCurrentApproverId(firstApproverId);
record.setStatus(STATUS_PROCESSING);
record.setCreatedAt(LocalDateTime.now());
record.setUpdatedAt(LocalDateTime.now());
record = recordRepository.save(record);
// 记录审批历史
SysApprovalHistory history = new SysApprovalHistory();
history.setRecordId(record.getId());
history.setNodeIndex(0);
history.setApproverId(applicantId);
history.setAction(ACTION_SUBMIT);
history.setComment(applyReason);
history.setCreatedAt(LocalDateTime.now());
historyRepository.save(history);
Map<String, Object> result = new HashMap<>();
result.put("recordId", record.getId());
result.put("status", record.getStatus());
result.put("currentNode", record.getCurrentNode());
result.put("currentApproverId", firstApproverId);
return result;
}
/**
* 通过触发事件提交审批
*/
@Transactional
public Map<String, Object> submitApprovalByEvent(String triggerEvent, String bizType, Long bizId,
String title, Long applicantId, String applyReason) {
Optional<SysApprovalFlow> flowOpt = flowRepository.findByTriggerEventAndStatus(triggerEvent, "ENABLED");
if (!flowOpt.isPresent()) {
throw new IllegalArgumentException("未找到触发事件对应的审批流程: " + triggerEvent);
}
return submitApproval(flowOpt.get().getId(), bizType, bizId, title, applicantId, applyReason);
}
/**
* 处理审批
*/
@Transactional
public Map<String, Object> handleApproval(Long recordId, String action, Long operatorId, String comment) {
Optional<SysApprovalRecord> recordOpt = recordRepository.findById(recordId);
if (!recordOpt.isPresent()) {
throw new IllegalArgumentException("审批记录不存在: " + recordId);
}
SysApprovalRecord record = recordOpt.get();
if (!STATUS_PROCESSING.equals(record.getStatus())) {
throw new IllegalArgumentException("审批记录状态不是处理中: " + record.getStatus());
}
// 验证审批人权限
if (!operatorId.equals(record.getCurrentApproverId())) {
throw new IllegalArgumentException("您不是当前审批人,无权处理此审批");
}
// 获取流程配置
Optional<SysApprovalFlow> flowOpt = flowRepository.findById(record.getFlowId());
if (!flowOpt.isPresent()) {
throw new IllegalArgumentException("审批流程配置不存在");
}
SysApprovalFlow flow = flowOpt.get();
// 解析节点配置
List<Map<String, Object>> nodes = parseNodes(flow.getNodes());
int currentNode = record.getCurrentNode();
// 记录审批历史
SysApprovalHistory history = new SysApprovalHistory();
history.setRecordId(recordId);
history.setNodeIndex(currentNode);
history.setApproverId(operatorId);
history.setAction(action);
history.setComment(comment);
history.setCreatedAt(LocalDateTime.now());
historyRepository.save(history);
Map<String, Object> result = new HashMap<>();
if (ACTION_APPROVE.equals(action)) {
// 批准 - 检查是否还有下一个节点
if (currentNode + 1 >= nodes.size()) {
// 审批完成
record.setStatus(STATUS_APPROVED);
record.setUpdatedAt(LocalDateTime.now());
recordRepository.save(record);
result.put("status", STATUS_APPROVED);
result.put("message", "审批已通过");
} else {
// 进入下一个节点
int nextNode = currentNode + 1;
Long nextApproverId = resolveNextApprover(nodes, nextNode, record);
record.setCurrentNode(nextNode);
record.setCurrentApproverId(nextApproverId);
record.setUpdatedAt(LocalDateTime.now());
recordRepository.save(record);
result.put("status", STATUS_PROCESSING);
result.put("currentNode", nextNode);
result.put("currentApproverId", nextApproverId);
result.put("message", "已提交给下一审批人");
}
} else if (ACTION_REJECT.equals(action)) {
// 拒绝
record.setStatus(STATUS_REJECTED);
record.setUpdatedAt(LocalDateTime.now());
recordRepository.save(record);
result.put("status", STATUS_REJECTED);
result.put("message", "审批已拒绝");
} else if (ACTION_TRANSFER.equals(action)) {
// 转交
// 转交目标ID在comment中传递格式: "transfer:userId"
if (comment != null && comment.startsWith("transfer:")) {
Long transferToId = Long.parseLong(comment.substring(9));
record.setCurrentApproverId(transferToId);
record.setUpdatedAt(LocalDateTime.now());
recordRepository.save(record);
result.put("status", STATUS_PROCESSING);
result.put("currentApproverId", transferToId);
result.put("message", "已转交给其他审批人");
} else {
throw new IllegalArgumentException("转交操作需要指定目标审批人,格式: transfer:userId");
}
} else {
throw new IllegalArgumentException("无效的审批动作: " + action);
}
return result;
}
/**
* 获取待审批列表
*/
public List<SysApprovalRecord> getPendingApprovals(Long userId) {
return recordRepository.findPendingByApproverId(userId);
}
/**
* 获取已审批列表我审批过的
*/
public List<SysApprovalRecord> getApprovedList(Long userId) {
return recordRepository.findProcessedByApplicantId(userId);
}
/**
* 获取我发起的审批
*/
public List<SysApprovalRecord> getMyApplications(Long userId) {
return recordRepository.findByApplicantId(userId);
}
/**
* 获取审批记录详情
*/
public Map<String, Object> getRecordById(Long recordId) {
Optional<SysApprovalRecord> recordOpt = recordRepository.findById(recordId);
if (!recordOpt.isPresent()) {
return null;
}
SysApprovalRecord record = recordOpt.get();
Map<String, Object> result = new HashMap<>();
result.put("id", record.getId());
result.put("flowId", record.getFlowId());
result.put("bizType", record.getBizType());
result.put("bizId", record.getBizId());
result.put("currentNode", record.getCurrentNode());
result.put("applicantId", record.getApplicantId());
result.put("status", record.getStatus());
result.put("currentApproverId", record.getCurrentApproverId());
result.put("createdAt", record.getCreatedAt());
result.put("updatedAt", record.getUpdatedAt());
// 获取流程信息
Optional<SysApprovalFlow> flowOpt = flowRepository.findById(record.getFlowId());
if (flowOpt.isPresent()) {
SysApprovalFlow flow = flowOpt.get();
result.put("flowName", flow.getFlowName());
result.put("flowCode", flow.getFlowCode());
}
// 获取审批历史
List<SysApprovalHistory> histories = historyRepository.findByRecordIdOrderByNodeIndexDesc(recordId);
result.put("history", histories);
return result;
}
/**
* 获取审批历史
*/
public List<SysApprovalHistory> getApprovalHistory(Long recordId) {
return historyRepository.findByRecordIdOrderByNodeIndexDesc(recordId);
}
/**
* 取消审批
*/
@Transactional
public boolean cancelApproval(Long recordId, Long operatorId) {
Optional<SysApprovalRecord> recordOpt = recordRepository.findById(recordId);
if (!recordOpt.isPresent()) {
throw new IllegalArgumentException("审批记录不存在: " + recordId);
}
SysApprovalRecord record = recordOpt.get();
if (!operatorId.equals(record.getApplicantId())) {
throw new IllegalArgumentException("只有申请人可以取消审批");
}
if (!STATUS_PROCESSING.equals(record.getStatus())) {
throw new IllegalArgumentException("只有处理中的审批可以取消");
}
record.setStatus(STATUS_CANCELLED);
record.setUpdatedAt(LocalDateTime.now());
recordRepository.save(record);
return true;
}
/**
* 获取所有审批流程配置
*/
public List<SysApprovalFlow> getAllFlows() {
return flowRepository.findAll();
}
/**
* 获取启用的审批流程
*/
public List<SysApprovalFlow> getEnabledFlows() {
return flowRepository.findByStatus("ENABLED");
}
/**
* 解析节点配置JSON
*/
@SuppressWarnings("unchecked")
private List<Map<String, Object>> parseNodes(String nodesJson) {
try {
return objectMapper.readValue(nodesJson, List.class);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("审批节点配置解析失败", e);
}
}
/**
* 解析第一个审批人
*/
private Long resolveFirstApprover(SysApprovalFlow flow, Long applicantId) {
List<Map<String, Object>> nodes = parseNodes(flow.getNodes());
if (nodes.isEmpty()) {
throw new IllegalArgumentException("审批流程节点配置为空");
}
return resolveApproverFromNode(nodes.get(0), applicantId);
}
/**
* 解析下一个审批人
*/
private Long resolveNextApprover(List<Map<String, Object>> nodes, int nodeIndex, SysApprovalRecord record) {
if (nodeIndex >= nodes.size()) {
return null;
}
return resolveApproverFromNode(nodes.get(nodeIndex), record.getApplicantId());
}
/**
* 从节点配置中解析审批人
*/
@SuppressWarnings("unchecked")
private Long resolveApproverFromNode(Map<String, Object> node, Long applicantId) {
String approverType = (String) node.get("approverType");
if ("SELF".equals(approverType)) {
return applicantId;
} else if ("ROLE".equals(approverType)) {
// 根据角色ID查找用户这里需要UserRoleService暂时返回null
return null;
} else if ("DEPARTMENT_HEAD".equals(approverType)) {
// 查找部门负责人需要DepartmentService暂时返回null
return null;
} else if ("SPECIFIC".equals(approverType)) {
// 指定用户
Object approverId = node.get("approverId");
if (approverId != null) {
return ((Number) approverId).longValue();
}
}
// 默认返回null需要手动分配
return null;
}
}