增加系统自动执行的自动化审批节点
This commit is contained in:
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.lanyuanxiaoyao.flowable.example;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowInstance;
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowStatus;
|
||||
|
||||
/**
|
||||
* 流程断言工具类
|
||||
* 用于验证流程执行状态是否符合预期
|
||||
*/
|
||||
public class FlowAssert {
|
||||
|
||||
public static void assertEquals(String message, Object expected, Object actual) {
|
||||
if (!expected.equals(actual)) {
|
||||
throw new AssertionError(String.format("%s: 期望值=%s, 实际值=%s", message, expected, actual));
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertStatus(String message, FlowStatus expectedStatus, FlowInstance instance) {
|
||||
assertEquals(message + " - 状态检查", expectedStatus, instance.getStatus());
|
||||
}
|
||||
|
||||
public static void assertNode(String message, String expectedNode, FlowInstance instance) {
|
||||
assertEquals(message + " - 节点检查", expectedNode, instance.getCurrentNode());
|
||||
}
|
||||
|
||||
public static void assertVariable(String message, Object expectedValue, String key, FlowInstance instance) {
|
||||
Object actualValue = instance.getContextVariables().get(key);
|
||||
assertEquals(message + " - <20><><EFBFBD>量[" + key + "]检查", expectedValue, actualValue);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.lanyuanxiaoyao.flowable.example;
|
||||
import com.lanyuanxiaoyao.flowable.example.node.LeaveRequestNode;
|
||||
import com.lanyuanxiaoyao.flowable.example.node.ManagerApprovalNode;
|
||||
import com.lanyuanxiaoyao.flowable.example.node.SimpleFlowNode;
|
||||
import com.lanyuanxiaoyao.flowable.example.node.LeaveSystemCheckNode;
|
||||
import com.lanyuanxiaoyao.flowable.model.Flow;
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowInstance;
|
||||
import com.lanyuanxiaoyao.flowable.repository.FlowInstanceRepository;
|
||||
@@ -10,6 +11,7 @@ import com.lanyuanxiaoyao.flowable.repository.FlowRepository;
|
||||
import com.lanyuanxiaoyao.flowable.repository.memory.MemoryFlowInstanceRepository;
|
||||
import com.lanyuanxiaoyao.flowable.repository.memory.MemoryFlowRepository;
|
||||
import com.lanyuanxiaoyao.flowable.service.FlowService;
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowStatus;
|
||||
|
||||
public class FlowExample {
|
||||
public static void main(String[] args) {
|
||||
@@ -36,6 +38,9 @@ public class FlowExample {
|
||||
|
||||
// 演示带有自定义节点操作的请假流程
|
||||
demonstrateLeaveFlowWithCustomNodes(flowService);
|
||||
|
||||
// 演示系统节点审批流程
|
||||
demonstrateSystemNodeFlow(flowService);
|
||||
}
|
||||
|
||||
private static Flow createLeaveFlow(FlowService flowService) {
|
||||
@@ -155,4 +160,82 @@ public class FlowExample {
|
||||
instance = flowService.reject(instance.getId());
|
||||
System.out.println("\n经理审批拒绝,流程状态:" + instance.getStatus());
|
||||
}
|
||||
|
||||
private static void demonstrateSystemNodeFlow(FlowService flowService) {
|
||||
System.out.println("\n=== 开始系统节点审批流程演示 ===");
|
||||
|
||||
// 创建流程定义
|
||||
Flow flow = new Flow();
|
||||
flow.setName("带系统审核的请假流程");
|
||||
flow.setDescription("包含系统自动审核的请假流程示例");
|
||||
|
||||
// 添加节点
|
||||
flow.addNode(new LeaveRequestNode()); // 请假申请
|
||||
flow.addNode(new LeaveSystemCheckNode(5)); // 系统审核(允许5天内自动通过)
|
||||
flow.addNode(new ManagerApprovalNode()); // 经理审批
|
||||
|
||||
Flow savedFlow = flowService.createFlow(flow);
|
||||
System.out.println("创建流程:" + savedFlow.getName());
|
||||
|
||||
// 演示自动通过的情况(3天请假)
|
||||
demonstrateSystemApproveFlow(flowService, savedFlow.getId());
|
||||
|
||||
// 演示自动拒绝的情况(7天请假)
|
||||
demonstrateSystemRejectFlow(flowService, savedFlow.getId());
|
||||
}
|
||||
|
||||
private static void demonstrateSystemApproveFlow(FlowService flowService, String flowId) {
|
||||
System.out.println("\n=== 演示系统自动通过流程 ===");
|
||||
|
||||
// 启动流程实例(LeaveRequestNode设置3天请假)
|
||||
FlowInstance instance = flowService.startFlow(flowId);
|
||||
System.out.println("\n启动流程实例,当前节点:" + instance.getCurrentNode());
|
||||
|
||||
// 验证初始状态
|
||||
FlowAssert.assertStatus("流程启动", FlowStatus.PENDING, instance);
|
||||
FlowAssert.assertNode("流程启动", "请假申请", instance);
|
||||
FlowAssert.assertVariable("流程启动", 3, "days", instance);
|
||||
FlowAssert.assertVariable("流程启动", "年假", "reason", instance);
|
||||
|
||||
// 请假申请通过后会自动执行系统审核
|
||||
instance = flowService.approve(instance.getId());
|
||||
System.out.println("\n请假申请通过后,当前节点:" + instance.getCurrentNode());
|
||||
|
||||
// 验证系统审核通过
|
||||
FlowAssert.assertStatus("系统审核", FlowStatus.PENDING, instance);
|
||||
FlowAssert.assertNode("系统审核", "经理审批", instance);
|
||||
FlowAssert.assertVariable("系统审核", "系统自动通过", "systemComment", instance);
|
||||
|
||||
// 经理最终审批
|
||||
instance = flowService.approve(instance.getId());
|
||||
System.out.println("\n经理审批通过,流程状态:" + instance.getStatus());
|
||||
|
||||
// 验证流程完成
|
||||
FlowAssert.assertStatus("流程完成", FlowStatus.APPROVED, instance);
|
||||
FlowAssert.assertVariable("流程完成", "同意", "managerComment", instance);
|
||||
}
|
||||
|
||||
private static void demonstrateSystemRejectFlow(FlowService flowService, String flowId) {
|
||||
System.out.println("\n=== 演示系统自动拒绝流程 ===");
|
||||
|
||||
// 修改LeaveRequestNode中的请假天数为7天
|
||||
LeaveRequestNode.setTestDays(7);
|
||||
|
||||
// 启动流程实例
|
||||
FlowInstance instance = flowService.startFlow(flowId);
|
||||
System.out.println("\n启动流程实例,当前节点:" + instance.getCurrentNode());
|
||||
|
||||
// 验证初始状态
|
||||
FlowAssert.assertStatus("流程启动", FlowStatus.PENDING, instance);
|
||||
FlowAssert.assertNode("流程启动", "请假申请", instance);
|
||||
FlowAssert.assertVariable("流程启动", 7, "days", instance);
|
||||
|
||||
// 请假申请通过后系统会自动拒绝
|
||||
instance = flowService.approve(instance.getId());
|
||||
System.out.println("\n请假申请后,流程状态:" + instance.getStatus());
|
||||
|
||||
// 验证系统拒绝
|
||||
FlowAssert.assertStatus("系统拒绝", FlowStatus.REJECTED, instance);
|
||||
FlowAssert.assertVariable("系统拒绝", "请假天数(7)超过系统限制(5),需要额外审批", "systemComment", instance);
|
||||
}
|
||||
}
|
||||
@@ -5,17 +5,20 @@ import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class LeaveRequestNode extends AbstractFlowNode {
|
||||
// 用于测试的请假天数
|
||||
private static int testDays = 3;
|
||||
|
||||
public LeaveRequestNode() {
|
||||
super("请假申请");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(FlowContext context) {
|
||||
// 模拟设置请假信息
|
||||
context.setVariable("days", 3);
|
||||
// 模拟设置请假信息,使用testDays而不是硬编码的值
|
||||
context.setVariable("days", testDays);
|
||||
context.setVariable("reason", "年假");
|
||||
context.setVariable("requestTime", LocalDateTime.now());
|
||||
System.out.println("执行请假申请节点:设置请假天数为3天,请假理由为年假");
|
||||
System.out.println("执行请假申请节点:设置请假天数为" + testDays + "天,请假理由为年假");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -27,4 +30,12 @@ public class LeaveRequestNode extends AbstractFlowNode {
|
||||
public void onReject(FlowContext context) {
|
||||
System.out.println("请假申请被撤销");
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置测试用的请假天数
|
||||
* @param days 请假天数
|
||||
*/
|
||||
public static void setTestDays(int days) {
|
||||
testDays = days;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.lanyuanxiaoyao.flowable.example.node;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.node.SystemFlowNode;
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 请假系统自动审核节点
|
||||
* 根据请假天数自动判断是否通过
|
||||
*/
|
||||
public class LeaveSystemCheckNode extends SystemFlowNode {
|
||||
private final int maxDays; // 最大允许请假天数
|
||||
|
||||
public LeaveSystemCheckNode(int maxDays) {
|
||||
super("系统审核");
|
||||
this.maxDays = maxDays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean autoApprove(FlowContext context) {
|
||||
Integer days = context.getVariable("days", Integer.class);
|
||||
return days != null && days <= maxDays;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRejectionReason(FlowContext context) {
|
||||
Integer days = context.getVariable("days", Integer.class);
|
||||
return String.format("请假天数(%d)超过系统限制(%d),需要额外审批", days, maxDays);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApprove(FlowContext context) {
|
||||
Integer days = context.getVariable("days", Integer.class);
|
||||
String reason = context.getVariable("reason", String.class);
|
||||
|
||||
System.out.println("执行系统审核节点:");
|
||||
System.out.println("- 请假天数:" + days);
|
||||
System.out.println("- 请假理由:" + reason);
|
||||
System.out.println("- 系统限制:" + maxDays + "天");
|
||||
|
||||
context.setVariable("systemComment", "系统自动通过");
|
||||
context.setVariable("systemCheckTime", LocalDateTime.now());
|
||||
System.out.println("系统自动审核通过");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReject(FlowContext context) {
|
||||
Integer days = context.getVariable("days", Integer.class);
|
||||
String reason = context.getVariable("reason", String.class);
|
||||
|
||||
System.out.println("执行系统审核节点:");
|
||||
System.out.println("- 请假天数:" + days);
|
||||
System.out.println("- 请假理由:" + reason);
|
||||
System.out.println("- 系统限制:" + maxDays + "天");
|
||||
|
||||
String rejectionReason = getRejectionReason(context);
|
||||
context.setVariable("systemComment", rejectionReason);
|
||||
context.setVariable("systemCheckTime", LocalDateTime.now());
|
||||
System.out.println("系统自动审核拒绝:" + rejectionReason);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.lanyuanxiaoyao.flowable.node;
|
||||
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||
|
||||
/**
|
||||
* 系统自动审批节点
|
||||
* 根据预设规则自动执行审批操作
|
||||
*/
|
||||
public abstract class SystemFlowNode extends AbstractFlowNode {
|
||||
public SystemFlowNode(String nodeId) {
|
||||
super(nodeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统自动判断是否通过
|
||||
* @param context 流程上下文
|
||||
* @return true表示通过,false表示拒绝
|
||||
*/
|
||||
public abstract boolean autoApprove(FlowContext context);
|
||||
|
||||
/**
|
||||
* 获取拒绝原因
|
||||
* @param context 流程上下文
|
||||
* @return 拒绝原因
|
||||
*/
|
||||
protected abstract String getRejectionReason(FlowContext context);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowStatus;
|
||||
import com.lanyuanxiaoyao.flowable.model.FlowContext;
|
||||
import com.lanyuanxiaoyao.flowable.node.FlowNode;
|
||||
import com.lanyuanxiaoyao.flowable.node.SystemFlowNode;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class FlowService {
|
||||
@@ -51,7 +52,13 @@ public class FlowService {
|
||||
FlowContext context = createContext(instance);
|
||||
|
||||
// 执行第一个节点
|
||||
flow.getNodes().get(0).execute(context);
|
||||
FlowNode firstNode = flow.getNodes().get(0);
|
||||
firstNode.execute(context);
|
||||
|
||||
// 如果是系统节点,自动执行审批
|
||||
if (firstNode instanceof SystemFlowNode) {
|
||||
instance = handleSystemNode(instance, firstNode, context);
|
||||
}
|
||||
|
||||
// 保存上下文变量
|
||||
saveContext(instance, context);
|
||||
@@ -95,6 +102,11 @@ public class FlowService {
|
||||
FlowNode nextNode = nodes.get(currentIndex + 1);
|
||||
instance.setCurrentNode(nextNode.getNodeId());
|
||||
nextNode.execute(context);
|
||||
|
||||
// 如果下一个是系统节点,自动执行审批
|
||||
if (nextNode instanceof SystemFlowNode) {
|
||||
instance = handleSystemNode(instance, nextNode, context);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存上下文变量
|
||||
@@ -175,4 +187,50 @@ public class FlowService {
|
||||
instance.getContextVariables().clear();
|
||||
instance.getContextVariables().putAll(context.getVariables());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理系统节点的自动审批
|
||||
*/
|
||||
private FlowInstance handleSystemNode(FlowInstance instance, FlowNode node, FlowContext context) {
|
||||
SystemFlowNode systemNode = (SystemFlowNode) node;
|
||||
if (systemNode.autoApprove(context)) {
|
||||
// 自动通过
|
||||
systemNode.onApprove(context);
|
||||
// 如果<E5A682><E69E9C>最后一个节点,标记为完成
|
||||
if (isLastNode(instance.getFlowId(), node.getNodeId())) {
|
||||
instance.setStatus(FlowStatus.APPROVED);
|
||||
} else {
|
||||
// 否则移动到下一个节点
|
||||
FlowNode nextNode = getNextNode(instance.getFlowId(), node.getNodeId());
|
||||
instance.setCurrentNode(nextNode.getNodeId());
|
||||
nextNode.execute(context);
|
||||
// 如果下一个还是系统节点,继续自动处理
|
||||
if (nextNode instanceof SystemFlowNode) {
|
||||
instance = handleSystemNode(instance, nextNode, context);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 自动拒绝
|
||||
systemNode.onReject(context);
|
||||
instance.setStatus(FlowStatus.REJECTED);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private boolean isLastNode(String flowId, String nodeId) {
|
||||
Flow flow = flowRepository.findById(flowId);
|
||||
List<FlowNode> nodes = flow.getNodes();
|
||||
return nodes.get(nodes.size() - 1).getNodeId().equals(nodeId);
|
||||
}
|
||||
|
||||
private FlowNode getNextNode(String flowId, String currentNodeId) {
|
||||
Flow flow = flowRepository.findById(flowId);
|
||||
List<FlowNode> nodes = flow.getNodes();
|
||||
for (int i = 0; i < nodes.size() - 1; i++) {
|
||||
if (nodes.get(i).getNodeId().equals(currentNodeId)) {
|
||||
return nodes.get(i + 1);
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("找不到下一个节点");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user