在 b369527 之上增量移植 FL2.0 后端能力,不改既有线级停发/指派预览/流程图入口:
- 部门目录:FlowDepartmentController(/admin/department/{groups,options,resolve,members})
+ UserBaseDepartmentDirectory(先按会话校域解析引用,再读成员;目录不可用 fail-closed)
- 退回重提 D14:POST /oapi/flow/instance/{instanceId}/resubmit,仅原提交人 CAS 路径放行,
OAPI 侧 submitterId 路径继续 fail-closed
- 授权管理:/api/flow/admin/usage-grant/{schoolList,summary}(校域取管理员会话,无 schId 入参)
- 来源主体:解析器派生 ub-app:{applicationInfo.id},不再读取 UserBase 的 sourcePrincipalId 字段
- 回调来源策略:SELF 身份强校验;NULL 来源不广播;复合幂等键 (event_id,reg_id)
- 测试夹具:许可/主体/开通桩按新契约修正,FlowEngineIT/FormalApplyCommandIT/
CallbackDispatchIT/OapiFlowContractIT 共 117 例在真实 MySQL 8 通过
不含:FlSourceAuthorizationTest(其断言的两个 Repository 派生方法属另一实现线)
This commit is contained in:
@@ -0,0 +1,423 @@
|
||||
package com.yunhai.flowcenter.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yunhai.flowcenter.engine.AssigneeRef;
|
||||
import com.yunhai.flowcenter.engine.AssigneeResolver;
|
||||
import com.yunhai.flowcenter.engine.DefValidator;
|
||||
import com.yunhai.flowcenter.engine.FlowDefModel;
|
||||
import com.yunhai.platform.apistd.BizException;
|
||||
import com.yunhai.platform.openapi.base.OpenApiGroupClient;
|
||||
import com.yunhai.platform.openapi.base.OpenApiUserClient;
|
||||
import com.yunhai.platform.openapi.base.model.DepartmentEntry;
|
||||
import com.yunhai.platform.openapi.base.model.DepartmentRef;
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
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.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* UserBase 部门权威化与审批主体规则(工作包 C,2026-10-29)。
|
||||
*
|
||||
* <p>测试替身边界:{@link OpenApiGroupClient}/{@link OpenApiUserClient} 按 UserBase
|
||||
* {@code /oapi/departments/**} 的真实契约打桩(响应形状=SDK 的 DepartmentEntry/BoaUser),
|
||||
* <b>这不是跨服务联调</b>——真实 UserBase 可达性、SYSTEM/CUSTOM 数据齐备性由后续 WorkBuddy 验证。</p>
|
||||
*
|
||||
* <p>钉住的红线:</p>
|
||||
* <ul>
|
||||
* <li>部门是<b>审批授权主体</b>,不是"前端筛出来的一堆人";解析出的候选仍逐人过 D11 资格终审;</li>
|
||||
* <li>一个用户可属多个部门 → 多部门引用按用户去重,只发一条待办;</li>
|
||||
* <li>目录不可用一律抛错,<b>不静默退回 flw_dept</b>,也不把空候选当成功;</li>
|
||||
* <li>展示口径(显示人员/显示部门)与审批主体分开配置并独立生效。</li>
|
||||
* </ul>
|
||||
*/
|
||||
@DisplayName("UserBase 部门主体解析 + 展示规则(C1/C2/C3)")
|
||||
class FlDepartmentSubjectTest {
|
||||
@Test void foreignSchoolReferenceCannotExposeMembers() {
|
||||
assertThatThrownBy(() -> directory.resolve(SCH,
|
||||
Arrays.asList(new DepartmentRef((int) SCH + 1, SYSTEM, 42))))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("学校");
|
||||
DepartmentEntry foreign = entry(SYSTEM, 42, true, false);
|
||||
foreign.setSchoolId((int) SCH + 1); foreign.setName("foreign");
|
||||
when(groupClient.resolveDepartments(any())).thenReturn(Arrays.asList(foreign));
|
||||
assertThatThrownBy(() -> directory.membersAtSchool(SCH, SYSTEM, 42, "select"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("学校");
|
||||
org.mockito.Mockito.verify(groupClient, org.mockito.Mockito.never()).getDepartmentMembers(any(), any(), any());
|
||||
}
|
||||
|
||||
private static final long SCH = 5L;
|
||||
private static final String SYSTEM = "SYSTEM";
|
||||
private static final String CUSTOM = "CUSTOM";
|
||||
|
||||
private OpenApiGroupClient groupClient;
|
||||
private OpenApiUserClient userClient;
|
||||
private UserBaseDepartmentDirectory directory;
|
||||
private AssigneeResolver resolver;
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
groupClient = mock(OpenApiGroupClient.class);
|
||||
userClient = mock(OpenApiUserClient.class);
|
||||
directory = new UserBaseDepartmentDirectory(groupClient);
|
||||
when(groupClient.resolveDepartments(any())).thenAnswer(call -> {
|
||||
java.util.List<DepartmentRef> refs = call.getArgument(0);
|
||||
if (refs == null) return java.util.Collections.emptyList();
|
||||
java.util.List<DepartmentEntry> rows = new java.util.ArrayList<>();
|
||||
for (DepartmentRef ref : refs) {
|
||||
DepartmentEntry e = entry(ref.getDepartmentType(), ref.getDepartmentId(), true, false);
|
||||
e.setSchoolId(ref.getSchoolId()); e.setName("department"); rows.add(e);
|
||||
}
|
||||
return rows;
|
||||
});
|
||||
resolver = new AssigneeResolver(mock(FlowDeptAdminService.class), userClient);
|
||||
resolver.setDepartmentDirectory(directory);
|
||||
givenEligibleUsers(101, 102, 103, 104);
|
||||
}
|
||||
|
||||
// ==================== C1 权威目录接入 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("DEPT 主体从 UserBase 目录解析候选人(scope=select 严档,不读 flw_dept_member)")
|
||||
void departmentSubjectResolvesFromUserBase() {
|
||||
when(groupClient.getDepartmentMembers(SYSTEM, 42, "select"))
|
||||
.thenReturn(Arrays.asList(user(101, "张老师"), user(102, "李老师")));
|
||||
|
||||
List<AssigneeRef> refs = resolver.resolve(SCH, approvalNode(deptAssignee(SYSTEM, 42)));
|
||||
|
||||
assertThat(refs).extracting(AssigneeRef::getUserId).containsExactly(101, 102);
|
||||
verify(groupClient).getDepartmentMembers(SYSTEM, 42, "select");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("同一用户归属多个被选部门:只产出一条待办(多组归属不是模型禁忌)")
|
||||
void overlappingMembershipDeduplicatesUser() {
|
||||
when(groupClient.getDepartmentMembers(SYSTEM, 42, "select"))
|
||||
.thenReturn(Arrays.asList(user(101, "张老师"), user(102, "李老师")));
|
||||
when(groupClient.getDepartmentMembers(CUSTOM, 7, "select"))
|
||||
.thenReturn(Arrays.asList(user(102, "李老师"), user(103, "王老师")));
|
||||
|
||||
FlowDefModel.Assignee assignee = new FlowDefModel.Assignee();
|
||||
assignee.type = FlowDefModel.ASSIGNEE_DEPT;
|
||||
assignee.deptRefs = new ArrayList<>(Arrays.asList(deptRef(SYSTEM, 42), deptRef(CUSTOM, 7)));
|
||||
|
||||
List<AssigneeRef> refs = resolver.resolve(SCH, approvalNode(assignee));
|
||||
|
||||
assertThat(refs).extracting(AssigneeRef::getUserId).containsExactly(101, 102, 103);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("目录不可用:拒绝并说明原因,绝不退回 FL 本地科室(双权威 fallback 已禁)")
|
||||
void directoryOutageFailsClosed() {
|
||||
when(groupClient.getDepartmentMembers(anyString(), anyInt(), anyString()))
|
||||
.thenThrow(new RuntimeException("userbase unreachable"));
|
||||
FlowDefModel.Node node = approvalNode(deptAssignee(SYSTEM, 42));
|
||||
|
||||
assertThatThrownBy(() -> resolver.resolve(SCH, node))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("不可用");
|
||||
// 未装配目录通道同样拒绝,而不是回读本地表
|
||||
AssigneeResolver unwired = new AssigneeResolver(mock(FlowDeptAdminService.class), userClient);
|
||||
assertThatThrownBy(() -> unwired.resolve(SCH, node))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("未装配");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("部门解析出 0 人:按「无可用办理人」拒绝,不把空候选当成功")
|
||||
void emptyDepartmentIsRejected() {
|
||||
when(groupClient.getDepartmentMembers(SYSTEM, 42, "select")).thenReturn(new ArrayList<>());
|
||||
|
||||
assertThatThrownBy(() -> resolver.resolve(SCH, approvalNode(deptAssignee(SYSTEM, 42))))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("无可用办理人");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("部门里全是禁用/跨校账号:整体拒绝并点名原因(存在≠有资格,D11)")
|
||||
void ineligibleMembersAreFilteredAndEmptyIsRejected() {
|
||||
when(groupClient.getDepartmentMembers(SYSTEM, 42, "select"))
|
||||
.thenReturn(Arrays.asList(user(101, "张老师"), user(102, "李老师")));
|
||||
when(userClient.getUserById("101")).thenReturn(disabled(101));
|
||||
when(userClient.getUserById("102")).thenReturn(otherSchool(102));
|
||||
|
||||
assertThatThrownBy(() -> resolver.resolve(SCH, approvalNode(deptAssignee(SYSTEM, 42))))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("不具备办理资格");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("部分成员不合格:剔除不合格者继续,不因个别人卡死整条流程")
|
||||
void partiallyIneligibleKeepsEligibleOnes() {
|
||||
when(groupClient.getDepartmentMembers(SYSTEM, 42, "select"))
|
||||
.thenReturn(Arrays.asList(user(101, "张老师"), user(102, "李老师")));
|
||||
when(userClient.getUserById("102")).thenReturn(disabled(102));
|
||||
|
||||
List<AssigneeRef> refs = resolver.resolve(SCH, approvalNode(deptAssignee(SYSTEM, 42)));
|
||||
|
||||
assertThat(refs).extracting(AssigneeRef::getUserId).containsExactly(101);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("部门引用缺类型消歧位:拒绝(同值 id 在 SYSTEM/CUSTOM 不等价)")
|
||||
void untypedReferenceRejected() {
|
||||
FlowDefModel.Assignee assignee = new FlowDefModel.Assignee();
|
||||
assignee.type = FlowDefModel.ASSIGNEE_DEPT;
|
||||
FlowDefModel.DeptRef bad = new FlowDefModel.DeptRef();
|
||||
bad.departmentId = 42;
|
||||
assignee.deptRefs = new ArrayList<>(Arrays.asList(bad));
|
||||
|
||||
assertThatThrownBy(() -> resolver.resolve(SCH, approvalNode(assignee)))
|
||||
.isInstanceOf(BizException.class);
|
||||
|
||||
assertThatThrownBy(() -> directory.members("OTHER", 42, "select"))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("SYSTEM/CUSTOM");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("历史口径与选择口径分开:resolve-batch 取停用部门名称,select 不返回停用项")
|
||||
void historyAndSelectionScopesAreSeparate() {
|
||||
when(groupClient.getDepartmentMembers(CUSTOM, 9, "history"))
|
||||
.thenReturn(Arrays.asList(user(103, "王老师")));
|
||||
assertThat(directory.members(CUSTOM, 9, "history"))
|
||||
.extracting(BoaUser::getId).containsExactly(103);
|
||||
|
||||
DepartmentEntry deleted = new DepartmentEntry();
|
||||
deleted.setDepartmentType(CUSTOM);
|
||||
deleted.setDepartmentId(9);
|
||||
deleted.setName("已撤销的课题组");
|
||||
deleted.setSelectable(false);
|
||||
deleted.setDeleted(true);
|
||||
deleted.setSchoolId((int) SCH);
|
||||
when(groupClient.resolveDepartments(any())).thenReturn(Arrays.asList(deleted));
|
||||
|
||||
List<DepartmentEntry> resolved = directory.resolve(SCH,
|
||||
Arrays.asList(new DepartmentRef(null, CUSTOM, 9)));
|
||||
|
||||
assertThat(resolved).hasSize(1);
|
||||
assertThat(resolved.get(0).getName()).isEqualTo("已撤销的课题组");
|
||||
assertThat(resolved.get(0).getSelectable()).isFalse();
|
||||
// 学校范围由服务端会话派生并补进引用,不接受前端传别校 id
|
||||
assertThat(resolved.get(0).getSchoolId()).isEqualTo((int) SCH);
|
||||
ArgumentCaptor<List<DepartmentRef>> sent = ArgumentCaptor.forClass(List.class);
|
||||
verify(groupClient).resolveDepartments(sent.capture());
|
||||
assertThat(sent.getValue().get(0).getSchoolId()).as("校域由服务端会话派生并补进引用").isEqualTo((int) SCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("发布校验白名单来自目录 selectable 项,停用部门不可被新选中")
|
||||
void selectableKeysOnlyCatalogSelectable() {
|
||||
DepartmentEntry live = entry(SYSTEM, 42, true, false);
|
||||
DepartmentEntry stopped = entry(SYSTEM, 43, false, false);
|
||||
DepartmentEntry softDeleted = entry(CUSTOM, 9, true, true);
|
||||
when(groupClient.getDepartments(eq((int) SCH), any(), any(), any()))
|
||||
.thenReturn(Arrays.asList(live, stopped, softDeleted));
|
||||
|
||||
assertThat(directory.selectableKeys(SCH)).containsExactly("SYSTEM:42");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("空引用批量解析本地短路,不出站也不报错")
|
||||
void emptyResolveBatchShortCircuits() {
|
||||
assertThat(directory.resolve(SCH, new ArrayList<>())).isEmpty();
|
||||
verify(groupClient, never()).resolveDepartments(any());
|
||||
}
|
||||
|
||||
// ==================== C3 展示规则 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("显示部门:任务节点名取独立展示名;未配展示字段=沿用节点名(历史定义零变化)")
|
||||
void displayLabelDrivesTaskNodeName() throws Exception {
|
||||
FlowDefModel model = FlowDefModel.parse(mapper, "{\"nodes\":[],\"edges\":[]}");
|
||||
FlowDefModel.Node legacy = approvalNode(deptAssignee(SYSTEM, 42));
|
||||
assertThat(legacy.displayName()).isEqualTo("二级审批");
|
||||
|
||||
legacy.displayMode = FlowDefModel.DISPLAY_MODE_DEPT;
|
||||
legacy.displayLabel = "校长室";
|
||||
assertThat(legacy.displayName()).isEqualTo("校长室");
|
||||
|
||||
// 按人员展示时不受 displayLabel 影响(只展示本节点自己配置/解析到的人)
|
||||
legacy.displayMode = FlowDefModel.DISPLAY_MODE_USER;
|
||||
assertThat(legacy.displayName()).isEqualTo("二级审批");
|
||||
assertThat(model).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("发布校验:显示部门必须填展示名;未知 displayMode 取值拒绝")
|
||||
void publishRejectsMissingDisplayLabel() {
|
||||
FlowDefModel model = twoLevelModel(deptAssignee(SYSTEM, 42));
|
||||
model.nodes.get(1).displayMode = FlowDefModel.DISPLAY_MODE_DEPT;
|
||||
|
||||
assertThatThrownBy(() -> DefValidator.validate(model, null, null,
|
||||
new java.util.HashSet<>(Arrays.asList("SYSTEM:42"))))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("展示名称");
|
||||
|
||||
model.nodes.get(1).displayMode = "BOTH";
|
||||
model.nodes.get(1).displayLabel = "校长室";
|
||||
assertThatThrownBy(() -> DefValidator.validate(model, null, null,
|
||||
new java.util.HashSet<>(Arrays.asList("SYSTEM:42"))))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("displayMode");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("发布校验:部门不在本校可选目录内(跨校/停用/已删)即拦;引用齐备则放行")
|
||||
void publishChecksDepartmentAgainstDirectoryWhitelist() {
|
||||
FlowDefModel model = twoLevelModel(deptAssignee(SYSTEM, 42));
|
||||
|
||||
DefValidator.validate(model, null, null, new java.util.HashSet<>(Arrays.asList("SYSTEM:42")));
|
||||
|
||||
assertThatThrownBy(() -> DefValidator.validate(model, null, null,
|
||||
new java.util.HashSet<>(Arrays.asList("SYSTEM:99"))))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("不在本校可选部门目录内");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("会签/或签对部门主体与人员主体同样可配(D07/D08 主体定候选,策略定完成条件)")
|
||||
void countersignConfigurableForBothSubjects() {
|
||||
Set<String> whitelist = new java.util.HashSet<>(Arrays.asList("SYSTEM:42"));
|
||||
// 部门主体 + 或签:合法(会签/或签不是只对部门生效)
|
||||
FlowDefModel deptModel = twoLevelModel(deptAssignee(SYSTEM, 42));
|
||||
deptModel.nodes.get(2).countersign = FlowDefModel.COUNTERSIGN_ANY;
|
||||
DefValidator.validate(deptModel, null, null, whitelist);
|
||||
assertThat(deptModel.nodes.get(2).countersign).isEqualTo(FlowDefModel.COUNTERSIGN_ANY);
|
||||
|
||||
// 人员主体 + 或签:同样合法
|
||||
FlowDefModel usersModel = twoLevelModel(usersAssignee(101, 102));
|
||||
usersModel.nodes.get(2).countersign = FlowDefModel.COUNTERSIGN_ANY;
|
||||
DefValidator.validate(usersModel, null, null, whitelist);
|
||||
|
||||
// 非法策略值:两类主体都拦
|
||||
deptModel.nodes.get(2).countersign = "MOST";
|
||||
assertThatThrownBy(() -> DefValidator.validate(deptModel, null, null, whitelist))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("countersign");
|
||||
}
|
||||
|
||||
// ==================== fixtures ====================
|
||||
|
||||
private void givenEligibleUsers(int... ids) {
|
||||
for (int id : ids) {
|
||||
when(userClient.getUserById(String.valueOf(id))).thenReturn(sameSchool(id, "教师" + id));
|
||||
}
|
||||
}
|
||||
|
||||
private FlowDefModel.Node approvalNode(FlowDefModel.Assignee assignee) {
|
||||
FlowDefModel.Node node = new FlowDefModel.Node();
|
||||
node.id = "n2";
|
||||
node.type = FlowDefModel.TYPE_APPROVAL;
|
||||
node.name = "二级审批";
|
||||
node.assignee = assignee;
|
||||
return node;
|
||||
}
|
||||
|
||||
private FlowDefModel twoLevelModel(FlowDefModel.Assignee assignee) {
|
||||
FlowDefModel model = FlowDefModel.parse(mapper, "{\"start\":\"start\",\"nodes\":["
|
||||
+ "{\"id\":\"start\",\"type\":\"START\"},"
|
||||
+ "{\"id\":\"n1\",\"type\":\"APPROVAL\",\"name\":\"一级\",\"assignee\":{\"type\":\"USERS\",\"userIds\":[101]}},"
|
||||
+ "{\"id\":\"end\",\"type\":\"END\"}],\"edges\":["
|
||||
+ "{\"from\":\"start\",\"to\":\"n1\"},{\"from\":\"n1\",\"to\":\"end\"}]}");
|
||||
FlowDefModel.Node deptNode = new FlowDefModel.Node();
|
||||
deptNode.id = "n2";
|
||||
deptNode.type = FlowDefModel.TYPE_APPROVAL;
|
||||
deptNode.name = "二级审批";
|
||||
deptNode.assignee = assignee;
|
||||
model.nodes.add(2, deptNode);
|
||||
model.edges.add(edge("n1", "n2"));
|
||||
model.edges.add(edge("n2", "end"));
|
||||
// 一级→end 的原边由 n1→n2 取代
|
||||
model.edges.removeIf(e -> "n1".equals(e.from) && "end".equals(e.to));
|
||||
return model;
|
||||
}
|
||||
|
||||
private FlowDefModel.Edge edge(String from, String to) {
|
||||
FlowDefModel.Edge e = new FlowDefModel.Edge();
|
||||
e.from = from;
|
||||
e.to = to;
|
||||
return e;
|
||||
}
|
||||
|
||||
private FlowDefModel.Assignee deptAssignee(String type, int id) {
|
||||
FlowDefModel.Assignee assignee = new FlowDefModel.Assignee();
|
||||
assignee.type = FlowDefModel.ASSIGNEE_DEPT;
|
||||
assignee.deptRefs = new ArrayList<>(Arrays.asList(deptRef(type, id)));
|
||||
return assignee;
|
||||
}
|
||||
|
||||
private FlowDefModel.Assignee usersAssignee(int... ids) {
|
||||
FlowDefModel.Assignee assignee = new FlowDefModel.Assignee();
|
||||
assignee.type = FlowDefModel.ASSIGNEE_USERS;
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for (int id : ids) {
|
||||
list.add(id);
|
||||
}
|
||||
assignee.userIds = list;
|
||||
return assignee;
|
||||
}
|
||||
|
||||
private FlowDefModel.DeptRef deptRef(String type, int id) {
|
||||
FlowDefModel.DeptRef ref = new FlowDefModel.DeptRef();
|
||||
ref.departmentType = type;
|
||||
ref.departmentId = id;
|
||||
return ref;
|
||||
}
|
||||
|
||||
private DepartmentEntry entry(String type, int id, boolean enabled, boolean deleted) {
|
||||
DepartmentEntry e = new DepartmentEntry();
|
||||
e.setSchoolId((int) SCH);
|
||||
e.setDepartmentType(type);
|
||||
e.setDepartmentId(id);
|
||||
e.setName(type + "-" + id);
|
||||
e.setEnabled(enabled);
|
||||
e.setDeleted(deleted);
|
||||
e.setSelectable(enabled && !deleted);
|
||||
return e;
|
||||
}
|
||||
|
||||
private BoaUser user(int id, String name) {
|
||||
return sameSchool(id, name);
|
||||
}
|
||||
|
||||
private BoaUser sameSchool(int id, String name) {
|
||||
BoaUser u = new BoaUser();
|
||||
u.setId(id);
|
||||
u.setName(name);
|
||||
u.setStatus(1);
|
||||
com.yunhai.platform.utils.model.BoaGroup school = new com.yunhai.platform.utils.model.BoaGroup();
|
||||
school.setId((int) SCH);
|
||||
u.setSchool(school);
|
||||
return u;
|
||||
}
|
||||
|
||||
private BoaUser disabled(int id) {
|
||||
BoaUser u = sameSchool(id, "停用账号");
|
||||
u.setStatus(0);
|
||||
return u;
|
||||
}
|
||||
|
||||
private BoaUser otherSchool(int id) {
|
||||
BoaUser u = sameSchool(id, "他校账号");
|
||||
u.getSchool().setId((int) SCH + 1);
|
||||
return u;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user