Skip to content

Commit e982904

Browse files
committed
fix #117
1 parent 436c717 commit e982904

File tree

6 files changed

+233
-7
lines changed

6 files changed

+233
-7
lines changed

springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/domain/FlowRelation.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
@AllArgsConstructor
1818
public class FlowRelation {
1919

20+
public static final int DEFAULT_ORDER = -100;
21+
2022
/**
2123
* 关系id
2224
*/
@@ -38,7 +40,7 @@ public class FlowRelation {
3840
private FlowNode target;
3941

4042
/**
41-
* 排序
43+
* 排序 (顺序越大的排序越靠前)
4244
*/
4345
private int order;
4446

@@ -145,12 +147,12 @@ public void verify() {
145147
throw new RuntimeException("outTrigger is null");
146148
}
147149

148-
if(source.getCode().equals(target.getCode())){
150+
if (source.getCode().equals(target.getCode())) {
149151
throw new RuntimeException("source node code is equals target node code");
150152
}
151153

152-
if(back){
153-
if(source.getType() != NodeType.APPROVAL){
154+
if (back) {
155+
if (source.getType() != NodeType.APPROVAL) {
154156
throw new RuntimeException("source node type is not approval");
155157
}
156158
}

springboot-starter-flow/src/main/java/com/codingapi/springboot/flow/service/FlowNodeService.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.codingapi.springboot.flow.record.FlowRecord;
1414
import com.codingapi.springboot.flow.repository.FlowOperatorRepository;
1515
import com.codingapi.springboot.flow.repository.FlowRecordRepository;
16+
import com.codingapi.springboot.flow.trigger.OutTrigger;
1617
import com.codingapi.springboot.flow.user.IFlowOperator;
1718
import com.codingapi.springboot.framework.event.EventPusher;
1819
import lombok.Getter;
@@ -172,7 +173,28 @@ public void loadCustomBackNode(FlowNode flowNode, long parentRecordId) {
172173
* @return 下一个节点
173174
*/
174175
private FlowNode matcherNextNode(FlowNode flowNode, boolean back) {
175-
List<FlowRelation> relations = flowWork.getRelations().stream()
176+
List<FlowRelation> currentRelations = new ArrayList<>(flowWork.getRelations());
177+
if(back){
178+
String preCode = FlowNode.CODE_START;
179+
if(flowRecord.getPreId()!=0){
180+
FlowRecord preRecord = flowRecordRepository.getFlowRecordById(flowRecord.getPreId());
181+
if(preRecord!=null){
182+
preCode = preRecord.getNodeCode();
183+
while (preCode.equals(flowRecord.getNodeCode())){
184+
preRecord = flowRecordRepository.getFlowRecordById(preRecord.getPreId());
185+
if(preRecord==null){
186+
break;
187+
}
188+
preCode = preRecord.getNodeCode();
189+
}
190+
}
191+
}
192+
FlowRelation backRelation = new FlowRelation("defaultId",
193+
"默认回退关系", flowNode, flowWork.getNodeByCode(preCode), OutTrigger.defaultOutTrigger(), FlowRelation.DEFAULT_ORDER, true);
194+
currentRelations.add(backRelation);
195+
}
196+
197+
List<FlowRelation> relations = currentRelations.stream()
176198
.filter(relation -> relation.sourceMatcher(flowNode.getCode()))
177199
.filter(relation -> relation.isBack() == back)
178200
.sorted((o1, o2) -> (o2.getOrder() - o1.getOrder()))
@@ -313,7 +335,7 @@ private List<FlowRecord> errMatcher(FlowNode currentNode, IFlowOperator currentO
313335
List<Long> operatorIds = ((OperatorResult) errorResult).getOperatorIds();
314336
List<? extends IFlowOperator> operators = flowOperatorRepository.findByIds(operatorIds);
315337
for (IFlowOperator operator : operators) {
316-
FlowSession content = new FlowSession(flowRecord, flowWork, currentNode, createOperator, operator, snapshot.toBindData(), opinion, historyRecords);
338+
FlowSession content = new FlowSession(flowRecord, flowWork, currentNode, createOperator, nextOperator, snapshot.toBindData(), opinion, historyRecords);
317339
String recordTitle = currentNode.generateTitle(content);
318340
FlowRecord record = currentNode.createRecord(flowWork.getId(), flowWork.getCode(), processId, preId, recordTitle, createOperator, operator, snapshot, opinion.isWaiting());
319341
recordList.add(record);

springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/ErrorTest.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,84 @@ void errorMatcherNodeTest(){
209209
List<BindDataSnapshot> snapshots = flowBindDataRepository.findAll();
210210
assertEquals(3, snapshots.size());
211211
}
212+
213+
214+
/**
215+
* 相同人审批通过,指定人员审批时遇到异常,走异常节点配置
216+
*/
217+
@Test
218+
void sameUserFlow() {
219+
PageRequest pageRequest = PageRequest.of(0, 1000);
220+
221+
User user = new User("张飞");
222+
userRepository.save(user);
223+
224+
User dept = new User("刘备");
225+
userRepository.save(dept);
226+
227+
User boss = new User("诸葛亮");
228+
userRepository.save(boss);
229+
230+
FlowWork flowWork = FlowWorkBuilder.builder(user)
231+
.title("请假流程")
232+
.skipIfSameApprover(true)
233+
.nodes()
234+
.node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher())
235+
.node("部门领导审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(user.getUserId()))
236+
.node("总经理审批", "manager", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()), new ErrTrigger("" +
237+
"def run(content){" +
238+
" return content.createOperatorErrTrigger(" + dept.getUserId() + ")" +
239+
"}"+
240+
""),true, false)
241+
.node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher())
242+
.relations()
243+
.relation("部门领导审批", "start", "dept")
244+
.relation("总经理审批", "dept", "manager")
245+
.relation("结束节点", "manager", "over")
246+
.build();
247+
248+
flowWorkRepository.save(flowWork);
249+
250+
String workCode = flowWork.getCode();
251+
252+
Leave leave = new Leave("我要出去看看");
253+
leaveRepository.save(leave);
254+
255+
// 创建流程
256+
flowService.startFlow(workCode, user, leave, "发起流程");
257+
258+
// 查看我的待办
259+
List<FlowRecord> userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent();
260+
assertEquals(1, userTodos.size());
261+
262+
// 提交流程
263+
FlowRecord userTodo = userTodos.get(0);
264+
assertEquals(0, userTodo.getTimeoutTime());
265+
266+
flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意").specify(user.getUserId()));
267+
268+
// 查看刘备经理的待办
269+
List<FlowRecord> deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent();
270+
assertEquals(1, deptTodos.size());
271+
272+
// 提交委托dept部门经理的审批
273+
FlowRecord deptTodo = deptTodos.get(0);
274+
flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意"));
275+
276+
// 查看所有流程
277+
List<FlowRecord> records = flowRecordRepository.findAll(pageRequest).getContent();
278+
assertEquals(3, records.size());
279+
280+
userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent();
281+
assertEquals(0, userTodos.size());
282+
283+
records = flowRecordRepository.findAll(pageRequest).getContent();
284+
assertEquals(3, records.size());
285+
// 查看所有流程是否都已经结束
286+
assertTrue(records.stream().allMatch(FlowRecord::isFinish));
287+
288+
List<BindDataSnapshot> snapshots = flowBindDataRepository.findAll();
289+
assertEquals(4, snapshots.size());
290+
291+
}
212292
}

springboot-starter-flow/src/test/java/com/codingapi/springboot/flow/test/FlowTest.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.codingapi.springboot.flow.record.FlowRecord;
1414
import com.codingapi.springboot.flow.repository.*;
1515
import com.codingapi.springboot.flow.service.FlowService;
16+
import com.codingapi.springboot.flow.trigger.OutTrigger;
1617
import com.codingapi.springboot.flow.user.IFlowOperator;
1718
import com.codingapi.springboot.flow.user.User;
1819
import org.junit.jupiter.api.Test;
@@ -1170,4 +1171,93 @@ void noSignContentTest() {
11701171
System.out.println(detail);
11711172

11721173
}
1174+
1175+
1176+
1177+
1178+
/**
1179+
* 退回与自定义退回逻辑
1180+
*/
1181+
@Test
1182+
void rejectDefaultTest() {
1183+
PageRequest pageRequest = PageRequest.of(0, 1000);
1184+
1185+
User user = new User("张飞");
1186+
userRepository.save(user);
1187+
1188+
User dept = new User("诸葛亮");
1189+
userRepository.save(dept);
1190+
1191+
User boss = new User("刘备");
1192+
userRepository.save(boss);
1193+
1194+
FlowWork flowWork = FlowWorkBuilder.builder(user)
1195+
.title("请假流程")
1196+
.nodes()
1197+
.node("开始节点", "start", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher())
1198+
.node("部门经理审批", "dept", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(dept.getUserId()))
1199+
.node("总经理审批", "boss", "default", ApprovalType.UN_SIGN, OperatorMatcher.specifyOperatorMatcher(boss.getUserId()))
1200+
.node("结束节点", "over", "default", ApprovalType.UN_SIGN, OperatorMatcher.anyOperatorMatcher())
1201+
.relations()
1202+
.relation("开始节点->部门经理", "start", "dept")
1203+
.relation("部门经理->总经理", "dept", "boss")
1204+
.relation("总经理退回发起人", "boss", "start", new OutTrigger("""
1205+
def run(content) {
1206+
def days = content.getBindData().getDays();
1207+
if (days > 10) {
1208+
return true;
1209+
}
1210+
return false;
1211+
}
1212+
"""),1,true)
1213+
.relation("结束节点", "boss", "over")
1214+
.build();
1215+
1216+
flowWorkRepository.save(flowWork);
1217+
1218+
String workCode = flowWork.getCode();
1219+
1220+
Leave leave = new Leave("我要出去看看");
1221+
leaveRepository.save(leave);
1222+
1223+
// 创建流程
1224+
flowService.startFlow(workCode, user, leave, "发起流程");
1225+
1226+
// 查看我的待办
1227+
List<FlowRecord> userTodos = flowRecordRepository.findTodoByOperatorId(user.getUserId(), pageRequest).getContent();
1228+
assertEquals(1, userTodos.size());
1229+
1230+
1231+
FlowRecord userTodo = userTodos.get(0);
1232+
flowService.submitFlow(userTodo.getId(), user, leave, Opinion.pass("同意"));
1233+
1234+
List<FlowRecord> deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent();
1235+
assertEquals(1, deptTodos.size());
1236+
1237+
FlowRecord deptTodo = deptTodos.get(0);
1238+
flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意"));
1239+
1240+
List<FlowRecord> bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent();
1241+
assertEquals(1, bossTodos.size());
1242+
1243+
FlowRecord bossTodo = bossTodos.get(0);
1244+
flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.reject("不同意"));
1245+
1246+
deptTodos = flowRecordRepository.findTodoByOperatorId(dept.getUserId(), pageRequest).getContent();
1247+
assertEquals(1, deptTodos.size());
1248+
1249+
deptTodo = deptTodos.get(0);
1250+
flowService.submitFlow(deptTodo.getId(), dept, leave, Opinion.pass("同意"));
1251+
1252+
bossTodos = flowRecordRepository.findTodoByOperatorId(boss.getUserId(), pageRequest).getContent();
1253+
assertEquals(1, bossTodos.size());
1254+
1255+
bossTodo = bossTodos.get(0);
1256+
flowService.submitFlow(bossTodo.getId(), boss, leave, Opinion.pass("同意"));
1257+
1258+
List<FlowRecord> records = flowRecordRepository.findAll(pageRequest).getContent();
1259+
assertEquals(5, records.size());
1260+
assertTrue(records.stream().allMatch(FlowRecord::isFinish));
1261+
1262+
}
11731263
}

springboot-starter/src/main/java/com/codingapi/springboot/framework/event/SpringEventHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public SpringEventHandler(List<IHandler> handlers) {
2626
}
2727

2828
@Override
29-
public void onApplicationEvent(DomainEvent domainEvent) {
29+
public synchronized void onApplicationEvent(DomainEvent domainEvent) {
3030
String traceId = domainEvent.getTraceId();
3131

3232
if (domainEvent.isSync()) {
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.codingapi.springboot.framework.event;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.springframework.boot.test.context.SpringBootTest;
5+
6+
import java.util.concurrent.ExecutorService;
7+
import java.util.concurrent.Executors;
8+
9+
@SpringBootTest
10+
public class EventPusherTest {
11+
12+
private final ExecutorService executorService = Executors.newFixedThreadPool(100);
13+
14+
@Test
15+
void test() {
16+
for (int i = 0; i < 100_0000; i++) {
17+
executorService.execute(() -> {
18+
try {
19+
EventPusher.push(new DemoChangeEvent("before", "current"), true);
20+
} catch (Exception e) {
21+
e.printStackTrace();
22+
}
23+
});
24+
}
25+
26+
try {
27+
Thread.sleep(10000); // 等待所有任务完成
28+
} catch (InterruptedException e) {
29+
Thread.currentThread().interrupt();
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)