build / build-push (push) Successful in 5m11s
- 多出口:FlwTask 增 edge_name 列(sql/20260916),FlwTaskRepository.claimAndFinish
同步落列;FlowTaskService.handle 出度>1 时 edgeName 必填;FlowEngine.continueAdvance
按 edge name 选路(单出口原路径逐字节兼容,未命中不推进);FlowAdvanceService/
FlowNodeAdvanceListener 透传;BranchScope 从 FlowEngine 提取
- DefValidator:多出口出口命名必填且同节点唯一;跨分支连线发布期明确拒绝
- 退回 POST /task/{id}/returnBack:默认退主管线最近已批节点,精确失效当前节点待办,
split 幂等 upsert 使退回重走并行段不撞 flw_branch uk
- 移交 POST /task/{id}/transfer:TRANSFERRED(5)+新建待办,AssigneeResolver.requireUserName
- 或签 ANY 补齐:首个同意失效同节点兄弟待办
- 已办口径/撤回守卫:status in (1,2,4,5);新事件 flow.returned/flow.transferred
- FlowDiagramService:EdgeVo.name/NodeVo.state/DiagramVo.layout,办件图状态计算
- 新 IT:多出口×3、ANY 或签、退回重走并行段、退回/移交/撤回
mvn test 84/84 绿
166 lines
7.5 KiB
Java
166 lines
7.5 KiB
Java
package com.yunhai.flowcenter.service;
|
|
|
|
import com.yunhai.flowcenter.entity.FlwAssigneeMap;
|
|
import com.yunhai.flowcenter.repository.FlwAssigneeMapRepository;
|
|
import com.yunhai.platform.openapi.base.OpenApiGroupClient;
|
|
import com.yunhai.platform.openapi.base.OpenApiUserClient;
|
|
import com.yunhai.platform.utils.model.BoaGroup;
|
|
import com.yunhai.platform.utils.model.BoaUser;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.anyString;
|
|
import static org.mockito.ArgumentMatchers.eq;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
/**
|
|
* 一键拉取教师组(办理人映射批量导入)单测:容器组语义(type=7 容器→子组为科室 / 无子组容器
|
|
* 自身为科室,与 svc-hall buildDeptTree 同口径)、deptKey=组 id、成员批量落库、
|
|
* 已存在且启用中的映射跳过、UserBase 不可达抛业务异常。
|
|
*/
|
|
class FlowMapAdminServiceGroupImportTest {
|
|
|
|
private FlwAssigneeMapRepository mapRepository;
|
|
private OpenApiUserClient userClient;
|
|
private OpenApiGroupClient groupClient;
|
|
private FlowMapAdminService service;
|
|
|
|
private static BoaGroup group(int id, String name, Integer type, BoaGroup... children) {
|
|
BoaGroup g = new BoaGroup();
|
|
g.setId(id);
|
|
g.setName(name);
|
|
g.setType(type);
|
|
g.setChildren(Arrays.asList(children));
|
|
return g;
|
|
}
|
|
|
|
private static BoaUser user(int id, String name) {
|
|
BoaUser u = new BoaUser();
|
|
u.setId(id);
|
|
u.setName(name);
|
|
return u;
|
|
}
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
mapRepository = mock(FlwAssigneeMapRepository.class);
|
|
userClient = mock(OpenApiUserClient.class);
|
|
groupClient = mock(OpenApiGroupClient.class);
|
|
service = new FlowMapAdminService(mapRepository, userClient, groupClient);
|
|
ReflectionTestUtils.setField(service, "deptGroupType", 7);
|
|
}
|
|
|
|
@Test
|
|
void preview_containerChildrenBecomeDepts() {
|
|
// 云海中学(3) → 教师组(4,type7 容器) → 校长室(6)/教务处(7);学生组(5,type8) 不参与
|
|
BoaGroup school = group(3, "云海中学", 2,
|
|
group(4, "教师组", 7, group(6, "校长室", 1), group(7, "教务处", 1)),
|
|
group(5, "学生组", 8));
|
|
when(groupClient.getGroupById(3, true)).thenReturn(school);
|
|
when(groupClient.getGroupUsers(eq(6), eq(false), any())).thenReturn(Arrays.asList(user(10006, "陈星1")));
|
|
when(groupClient.getGroupUsers(eq(7), eq(false), any())).thenReturn(Arrays.asList(user(10045, "测试教师2")));
|
|
|
|
List<FlowMapAdminService.GroupDeptVo> depts = service.previewGroupDepts(3L);
|
|
|
|
assertEquals(2, depts.size());
|
|
assertEquals("6", depts.get(0).getDeptKey());
|
|
assertEquals("校长室", depts.get(0).getDeptName());
|
|
assertEquals(1, depts.get(0).getUsers().size());
|
|
assertEquals(Integer.valueOf(10006), depts.get(0).getUsers().get(0).getUserId());
|
|
assertEquals("7", depts.get(1).getDeptKey());
|
|
}
|
|
|
|
@Test
|
|
void preview_childlessContainerItselfIsDept() {
|
|
// 教师组容器无子组 → 容器自身即科室
|
|
BoaGroup school = group(3, "云海中学", 2, group(9, "教研组", 7));
|
|
when(groupClient.getGroupById(3, true)).thenReturn(school);
|
|
when(groupClient.getGroupUsers(eq(9), eq(false), any())).thenReturn(Arrays.asList(user(1, "张三")));
|
|
|
|
List<FlowMapAdminService.GroupDeptVo> depts = service.previewGroupDepts(3L);
|
|
assertEquals(1, depts.size());
|
|
assertEquals("9", depts.get(0).getDeptKey());
|
|
assertEquals("教研组", depts.get(0).getDeptName());
|
|
}
|
|
|
|
@Test
|
|
void importGroups_writesAllMembersAndSkipsExistingEnabled() {
|
|
BoaGroup school = group(3, "云海中学", 2,
|
|
group(4, "教师组", 7, group(6, "校长室", 1)));
|
|
when(groupClient.getGroupById(3, true)).thenReturn(school);
|
|
when(groupClient.getGroupUsers(eq(6), eq(false), any()))
|
|
.thenReturn(Arrays.asList(user(10006, "陈星1"), user(10008, "李晶")));
|
|
// 10006 已有启用映射 → 跳过;10008 不存在 → 新增
|
|
FlwAssigneeMap existing = new FlwAssigneeMap();
|
|
existing.setStatus(0);
|
|
when(mapRepository.findBySchIdAndDeptKeyAndUserId(3L, "6", 10006)).thenReturn(existing);
|
|
when(mapRepository.findBySchIdAndDeptKeyAndUserId(3L, "6", 10008)).thenReturn(null);
|
|
|
|
FlowMapAdminService.GroupImportResultVo result = service.importGroups(3L);
|
|
|
|
assertEquals(1, result.getDepts());
|
|
assertEquals(1, result.getUsers());
|
|
assertEquals(1, result.getSkippedExisting());
|
|
ArgumentCaptor<FlwAssigneeMap> captor = ArgumentCaptor.forClass(FlwAssigneeMap.class);
|
|
verify(mapRepository, times(1)).save(captor.capture());
|
|
assertEquals("6", captor.getValue().getDeptKey());
|
|
assertEquals("校长室", captor.getValue().getDeptName());
|
|
assertEquals(Integer.valueOf(10008), captor.getValue().getUserId());
|
|
}
|
|
|
|
@Test
|
|
void importGroups_disabledExistingRowIsRefreshedNotSkipped() {
|
|
BoaGroup school = group(3, "云海中学", 2, group(6, "校长室", 7));
|
|
when(groupClient.getGroupById(3, true)).thenReturn(school);
|
|
when(groupClient.getGroupUsers(eq(6), eq(false), any())).thenReturn(Arrays.asList(user(1, "张三")));
|
|
FlwAssigneeMap disabled = new FlwAssigneeMap();
|
|
disabled.setStatus(1); // 停用中的历史行 → 重新启用而非跳过
|
|
when(mapRepository.findBySchIdAndDeptKeyAndUserId(3L, "6", 1)).thenReturn(disabled);
|
|
|
|
FlowMapAdminService.GroupImportResultVo result = service.importGroups(3L);
|
|
|
|
assertEquals(1, result.getUsers());
|
|
assertEquals(0, result.getSkippedExisting());
|
|
verify(mapRepository).save(any(FlwAssigneeMap.class));
|
|
}
|
|
|
|
@Test
|
|
void preview_userBaseUnreachableThrowsBizException() {
|
|
when(groupClient.getGroupById(3, true)).thenThrow(new RuntimeException("connect refused"));
|
|
assertThrows(com.yunhai.platform.apistd.BizException.class, () -> service.previewGroupDepts(3L));
|
|
verify(mapRepository, never()).save(any(FlwAssigneeMap.class));
|
|
}
|
|
|
|
@Test
|
|
void preview_schoolGroupMissingThrows() {
|
|
when(groupClient.getGroupById(99, true)).thenReturn(null);
|
|
assertThrows(com.yunhai.platform.apistd.BizException.class, () -> service.previewGroupDepts(99L));
|
|
}
|
|
|
|
@Test
|
|
void preview_memberFetchFailureDoesNotAbortOtherDepts() {
|
|
BoaGroup school = group(3, "云海中学", 2,
|
|
group(4, "教师组", 7, group(6, "校长室", 1), group(7, "教务处", 1)));
|
|
when(groupClient.getGroupById(3, true)).thenReturn(school);
|
|
when(groupClient.getGroupUsers(eq(6), eq(false), any())).thenThrow(new RuntimeException("boom"));
|
|
when(groupClient.getGroupUsers(eq(7), eq(false), any())).thenReturn(Arrays.asList(user(2, "李四")));
|
|
|
|
List<FlowMapAdminService.GroupDeptVo> depts = service.previewGroupDepts(3L);
|
|
assertEquals(2, depts.size());
|
|
assertEquals(0, depts.get(0).getUsers().size());
|
|
assertEquals(1, depts.get(1).getUsers().size());
|
|
}
|
|
}
|