Merge branch 'feat/s54-venue' into feat/approval-phase2
This commit is contained in:
@@ -0,0 +1,443 @@
|
||||
package com.gxwebsoft.approval;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.gxwebsoft.support.ApprovalTestData;
|
||||
import com.gxwebsoft.support.TestAuthentication;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* 场地使用申请表(#55):字段/时段校验、场地快照、8 条条款渲染、列表检索与五节点闭环。
|
||||
*
|
||||
* <p>不开启测试事务:提交与审批各自提交,校验跨库的组织/角色解析;数据由
|
||||
* {@link ApprovalTestData#cleanup()} 与本地 {@code approval_venue_form} 清理。</p>
|
||||
*/
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles({"gxtyzx-test", "test"})
|
||||
class ApprovalVenueIT {
|
||||
|
||||
/** 独立租户:角色成员按 (tenant_id, role_code) 匹配,专属租户避免与其它测试类串味。 */
|
||||
private static final int TENANT = 10026;
|
||||
private static final String FLOW = "venue";
|
||||
private static final String LIST = "approval:instance:list";
|
||||
private static final String SUBMIT = "approval:instance:submit";
|
||||
private static final String APPROVE = "approval:instance:approve";
|
||||
private static final String ARCHIVE = "approval:instance:archive";
|
||||
|
||||
private static final String SITE_NAME = "广西体育中心体育场";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
private ApprovalTestData data;
|
||||
private ApprovalTestData.TestUser reporter;
|
||||
private Integer organizationId;
|
||||
private final List<Long> instanceIds = new ArrayList<>();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
data = new ApprovalTestData(dataSource);
|
||||
organizationId = data.createOrganization("场地报送部门" + data.uniqueSuffix(), 136, TENANT);
|
||||
reporter = data.createUser("场地报送人" + data.uniqueSuffix(), organizationId, TENANT);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
for (Long instanceId : instanceIds) {
|
||||
data.master().update("DELETE FROM approval_venue_form WHERE instance_id = ?", instanceId);
|
||||
}
|
||||
instanceIds.clear();
|
||||
data.cleanup();
|
||||
}
|
||||
|
||||
@Test
|
||||
void completesFiveNodeFlowWithVenueSnapshot() throws Exception {
|
||||
ApprovalTestData.TestUser deptLeader = grantDeptRole("dept_leader_", "部门负责人");
|
||||
ApprovalTestData.TestUser deputy = grantDeptRole("dept_deputy_", "分管领导");
|
||||
ApprovalTestData.TestUser generalManager = grantRole("approval_general_manager", "总经理");
|
||||
ApprovalTestData.TestUser archivist = grantRole("approval_archivist", "收文员");
|
||||
|
||||
long instanceId = saveVenue("广西某某文化传媒有限公司", "ORG", "2026-11-08 09:00:00",
|
||||
"2026-11-08 18:00:00", "举办企业运动会", "1234.5");
|
||||
|
||||
// 草稿:标题=申请单位(人),无单号,场地快照落库
|
||||
assertThat(instanceStatus(instanceId)).isEqualTo("DRAFT");
|
||||
assertThat(bizNo(instanceId)).isNull();
|
||||
assertThat(data.queryMaster("SELECT doc_type FROM approval_instance WHERE id = ?",
|
||||
String.class, instanceId)).isEqualTo("venue");
|
||||
assertThat(data.queryMaster("SELECT flow_code FROM approval_instance WHERE id = ?",
|
||||
String.class, instanceId)).isEqualTo("venue");
|
||||
assertThat(data.queryMaster("SELECT title FROM approval_instance WHERE id = ?",
|
||||
String.class, instanceId)).isEqualTo("广西某某文化传媒有限公司");
|
||||
assertThat(data.queryMaster("SELECT applicant_type FROM approval_venue_form WHERE instance_id = ?",
|
||||
String.class, instanceId)).isEqualTo("ORG");
|
||||
assertThat(data.queryMaster("SELECT site_id FROM approval_venue_form WHERE instance_id = ?",
|
||||
Integer.class, instanceId)).isEqualTo(88001);
|
||||
assertThat(data.queryMaster("SELECT site_name FROM approval_venue_form WHERE instance_id = ?",
|
||||
String.class, instanceId)).isEqualTo(SITE_NAME);
|
||||
assertThat(data.queryMaster("SELECT activity_fee FROM approval_venue_form WHERE instance_id = ?",
|
||||
java.math.BigDecimal.class, instanceId)).isEqualByComparingTo("1234.50");
|
||||
|
||||
// 节点定义:五个节点按顺序发布,存档节点为报送人(JSON 列会重排空格,按关键片段断言)
|
||||
String nodes = data.queryMaster("SELECT nodes_json FROM approval_flow_definition "
|
||||
+ "WHERE tenant_id = ? AND flow_code = 'venue' ORDER BY version DESC LIMIT 1", String.class, TENANT);
|
||||
assertThat(nodes).contains("reporterOrgLeader").contains("reporterOrgDeputy")
|
||||
.contains("roleGeneralManager").contains("archivist");
|
||||
assertThat(nodes.indexOf("deptLeader")).isLessThan(nodes.indexOf("deputyLeader"));
|
||||
assertThat(nodes.indexOf("deputyLeader")).isLessThan(nodes.indexOf("generalManager"));
|
||||
assertThat(nodes.indexOf("generalManager")).isLessThan(nodes.indexOf("confirm"));
|
||||
assertThat(nodes.indexOf("confirm")).isLessThan(nodes.indexOf("archive"));
|
||||
|
||||
uploadAttachment(instanceId);
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + instanceId + "/submit"), reporter, organizationId, SUBMIT))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.status").value("PENDING"))
|
||||
.andExpect(jsonPath("$.data.currentNodeName").value("报送部门负责人"))
|
||||
.andExpect(jsonPath("$.data.attachments.length()").value(1));
|
||||
assertThat(bizNo(instanceId)).matches("CD\\d{8}-\\d{4,}");
|
||||
|
||||
approve(instanceId, deptLeader, "分管领导", "同意使用");
|
||||
approve(instanceId, deputy, "总经理", "同意");
|
||||
approve(instanceId, generalManager, "报送人存档", "批准");
|
||||
|
||||
// 存档节点:报送人确认后才进入归档
|
||||
long confirmTask = pendingTaskId(instanceId, reporter.userId);
|
||||
mockMvc.perform(authed(post("/api/approval/task/" + confirmTask + "/confirm"), reporter, organizationId, APPROVE))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.status").value("APPROVED"))
|
||||
.andExpect(jsonPath("$.data.statusName").value("审批完成"))
|
||||
.andExpect(jsonPath("$.data.currentNodeName").value("归档"));
|
||||
|
||||
long archiveTask = pendingTaskId(instanceId, archivist.userId);
|
||||
mockMvc.perform(authed(post("/api/approval/task/" + archiveTask + "/archive"), archivist, organizationId, ARCHIVE))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.status").value("ARCHIVED"))
|
||||
.andExpect(jsonPath("$.data.statusName").value("已归档"))
|
||||
.andExpect(jsonPath("$.data.archivistName").value(archivist.username));
|
||||
|
||||
assertThat(data.countMaster("SELECT COUNT(*) FROM approval_record WHERE instance_id = ? "
|
||||
+ "AND action = 'APPROVE'", instanceId)).isEqualTo(3);
|
||||
assertThat(data.countMaster("SELECT COUNT(*) FROM approval_record WHERE instance_id = ? "
|
||||
+ "AND action = 'CONFIRM'", instanceId)).isEqualTo(1);
|
||||
assertThat(data.countMaster("SELECT COUNT(*) FROM approval_record WHERE instance_id = ? "
|
||||
+ "AND action = 'ARCHIVE'", instanceId)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsCrossDayAndReversedUseTime() throws Exception {
|
||||
// 跨自然日:起止不在同一天
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + FLOW), reporter, organizationId, SUBMIT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body("跨天单位", "ORG", "2026-11-08 09:00:00", "2026-11-09 18:00:00",
|
||||
SITE_NAME, "跨天活动", "100.00")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("不能跨自然日")));
|
||||
|
||||
// 结束早于开始:同一自然日但时间倒挂
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + FLOW), reporter, organizationId, SUBMIT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body("倒挂单位", "ORG", "2026-11-08 18:00:00", "2026-11-08 09:00:00",
|
||||
SITE_NAME, "倒挂活动", "100.00")))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("必须晚于使用开始时间")));
|
||||
|
||||
// 起止相同也算不晚于
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + FLOW), reporter, organizationId, SUBMIT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body("同刻单位", "ORG", "2026-11-08 09:00:00", "2026-11-08 09:00:00",
|
||||
SITE_NAME, "同刻活动", "100.00")))
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("必须晚于使用开始时间")));
|
||||
|
||||
assertThat(data.countMaster("SELECT COUNT(*) FROM approval_venue_form "
|
||||
+ "WHERE applicant_name IN ('跨天单位', '倒挂单位', '同刻单位')")).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void validatesVenueFields() throws Exception {
|
||||
expectSaveFailure(body("", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "100.00"), "申请单位(人)不能为空");
|
||||
expectSaveFailure(body("单位", null, "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "100.00"), "申请单位(人)类型不能为空");
|
||||
expectSaveFailure(body("单位", "COMPANY", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "100.00"), "申请单位(人)类型只能是单位或个人");
|
||||
expectSaveFailure(body("单位", "ORG", null, "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "100.00"), "使用开始时间不能为空");
|
||||
expectSaveFailure(body("单位", "ORG", "2026-11-08 09:00:00", null,
|
||||
SITE_NAME, "用途", "100.00"), "使用结束时间不能为空");
|
||||
expectSaveFailure(body("单位", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "-1"), "活动费用必须为0到99999999.99之间的两位小数");
|
||||
expectSaveFailure(body("单位", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "100000000"), "活动费用必须为0到99999999.99之间的两位小数");
|
||||
expectSaveFailure(body("单位", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "用途", "1.234"), "活动费用必须为0到99999999.99之间的两位小数");
|
||||
expectSaveFailure(body("单位", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
"", "用途", "100.00"), "场地名称不能为空");
|
||||
expectSaveFailure(body("单位", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
SITE_NAME, "", "100.00"), "用途说明不能为空");
|
||||
|
||||
// 场地 id 必填
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + FLOW), reporter, organizationId, SUBMIT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"applicantName\":\"单位\",\"applicantType\":\"ORG\","
|
||||
+ "\"useStartTime\":\"2026-11-08 09:00:00\",\"useEndTime\":\"2026-11-08 18:00:00\","
|
||||
+ "\"siteName\":\"" + SITE_NAME + "\",\"purpose\":\"用途\",\"activityFee\":100.00}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("请选择场地")));
|
||||
|
||||
// 个人申请合法落库
|
||||
long instanceId = saveVenue("张三", "PERSON", "2026-11-08 09:00:00", "2026-11-08 12:00:00",
|
||||
"个人健身", "0");
|
||||
assertThat(data.queryMaster("SELECT applicant_type FROM approval_venue_form WHERE instance_id = ?",
|
||||
String.class, instanceId)).isEqualTo("PERSON");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rendersApplicantTypeAndEightTermsInDetail() throws Exception {
|
||||
long instanceId = saveVenue("广西某某体育俱乐部", "ORG", "2026-11-08 09:00:00",
|
||||
"2026-11-08 18:00:00", "举办篮球邀请赛", "8888");
|
||||
|
||||
Map<String, String> fields = detailFields(instanceId);
|
||||
|
||||
// 审批人能从详情看出是单位还是个人
|
||||
assertThat(fields).containsEntry("applicantType", "单位");
|
||||
assertThat(fields).containsEntry("applicantName", "广西某某体育俱乐部");
|
||||
assertThat(fields).containsEntry("siteName", SITE_NAME);
|
||||
assertThat(fields).containsEntry("activityFee", "8888.00");
|
||||
|
||||
// 8 条条款逐条输出,第 1 条渲染场地名与活动费用
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
assertThat(fields).as("条款" + i).containsKey("term" + i);
|
||||
assertThat(fields.get("term" + i)).isNotBlank();
|
||||
}
|
||||
assertThat(fields.get("term1")).contains(SITE_NAME).contains("8888.00元");
|
||||
assertThat(fields.get("term2")).contains("费用交付完成");
|
||||
assertThat(fields.get("term8")).contains("空调费");
|
||||
|
||||
// 个人申请在详情显示「个人」
|
||||
long personInstance = saveVenue("李四", "PERSON", "2026-11-08 09:00:00",
|
||||
"2026-11-08 18:00:00", "个人活动", "100");
|
||||
assertThat(detailFields(personInstance)).containsEntry("applicantType", "个人");
|
||||
}
|
||||
|
||||
@Test
|
||||
void listFindsByApplicantNameKeywords() throws Exception {
|
||||
saveVenue("广西甲体育馆运营有限公司", "ORG", "2026-11-08 09:00:00", "2026-11-08 18:00:00",
|
||||
"甲方活动", "100");
|
||||
long target = saveVenue("南宁乙文化传播有限公司", "PERSON", "2026-11-09 09:00:00",
|
||||
"2026-11-09 18:00:00", "乙方活动", "200");
|
||||
|
||||
mockMvc.perform(authed(get("/api/approval/mine/page"), reporter, organizationId, LIST)
|
||||
.param("keywords", "乙文化"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.count").value(1))
|
||||
.andExpect(jsonPath("$.data.list[0].id").value((int) target))
|
||||
.andExpect(jsonPath("$.data.list[0].title").value("南宁乙文化传播有限公司"))
|
||||
.andExpect(jsonPath("$.data.list[0].docTypeName").value("场地使用申请表"));
|
||||
|
||||
mockMvc.perform(authed(get("/api/approval/mine/page"), reporter, organizationId, LIST)
|
||||
.param("keywords", "甲体育馆"))
|
||||
.andExpect(jsonPath("$.data.count").value(1))
|
||||
.andExpect(jsonPath("$.data.list[0].title").value("广西甲体育馆运营有限公司"));
|
||||
|
||||
mockMvc.perform(authed(get("/api/approval/instance/page"), reporter, organizationId, LIST)
|
||||
.param("keywords", "乙文化"))
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.count").value(1))
|
||||
.andExpect(jsonPath("$.data.list[0].id").value((int) target));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsSubmitWithoutAttachment() throws Exception {
|
||||
grantDeptRole("dept_leader_", "部门负责人");
|
||||
grantDeptRole("dept_deputy_", "分管领导");
|
||||
grantRole("approval_general_manager", "总经理");
|
||||
grantRole("approval_archivist", "收文员");
|
||||
|
||||
long instanceId = saveVenue("无附件单位", "ORG", "2026-11-08 09:00:00",
|
||||
"2026-11-08 18:00:00", "无附件活动", "100");
|
||||
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + instanceId + "/submit"), reporter, organizationId, SUBMIT))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("请至少上传一张附件")));
|
||||
|
||||
assertThat(instanceStatus(instanceId)).isEqualTo("DRAFT");
|
||||
assertThat(bizNo(instanceId)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsSubmitWhenDeputyLeaderMissing() throws Exception {
|
||||
grantDeptRole("dept_leader_", "部门负责人");
|
||||
grantRole("approval_archivist", "收文员");
|
||||
long instanceId = saveVenue("缺分管单位", "ORG", "2026-11-08 09:00:00",
|
||||
"2026-11-08 18:00:00", "缺分管活动", "100");
|
||||
uploadAttachment(instanceId);
|
||||
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + instanceId + "/submit"), reporter, organizationId, SUBMIT))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString("报送部门分管领导角色缺配")));
|
||||
|
||||
assertThat(instanceStatus(instanceId)).isEqualTo("DRAFT");
|
||||
}
|
||||
|
||||
// ---------- helpers ----------
|
||||
|
||||
private void expectSaveFailure(String body, String expectedMessage) throws Exception {
|
||||
mockMvc.perform(authed(post("/api/approval/instance/" + FLOW), reporter, organizationId, SUBMIT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(1))
|
||||
.andExpect(jsonPath("$.message").value(org.hamcrest.Matchers.containsString(expectedMessage)));
|
||||
}
|
||||
|
||||
private long saveVenue(String applicantName, String applicantType, String start, String end,
|
||||
String purpose, String activityFee) throws Exception {
|
||||
String response = mockMvc.perform(authed(post("/api/approval/instance/" + FLOW),
|
||||
reporter, organizationId, SUBMIT)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(body(applicantName, applicantType, start, end, SITE_NAME, purpose, activityFee)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
long instanceId = objectMapper.readTree(response).path("data").asLong();
|
||||
data.trackInstance(instanceId);
|
||||
instanceIds.add(instanceId);
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
private void approve(long instanceId, ApprovalTestData.TestUser approver,
|
||||
String expectedNextNodeName, String opinion) throws Exception {
|
||||
long taskId = pendingTaskId(instanceId, approver.userId);
|
||||
mockMvc.perform(authed(post("/api/approval/task/" + taskId + "/approve"), approver, organizationId, APPROVE)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"opinion\":" + quote(opinion) + "}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data.currentNodeName").value(expectedNextNodeName));
|
||||
}
|
||||
|
||||
private Map<String, String> detailFields(long instanceId) throws Exception {
|
||||
String response = mockMvc.perform(authed(get("/api/approval/instance/" + instanceId),
|
||||
reporter, organizationId, LIST))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
JsonNode fields = objectMapper.readTree(response).path("data").path("document").path("fields");
|
||||
Map<String, String> result = new LinkedHashMap<>();
|
||||
for (JsonNode field : fields) {
|
||||
result.put(field.path("key").asText(), field.path("value").asText());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ApprovalTestData.TestUser grantDeptRole(String prefix, String roleName) {
|
||||
String roleCode = prefix + data.organizationCode(organizationId);
|
||||
ApprovalTestData.TestRole role = data.createRole(roleCode, roleName, TENANT);
|
||||
ApprovalTestData.TestUser member = data.createUser(roleName + data.uniqueSuffix(), organizationId, TENANT);
|
||||
data.bindTenant(member.userId, role.roleId, TENANT);
|
||||
return member;
|
||||
}
|
||||
|
||||
private ApprovalTestData.TestUser grantRole(String roleCode, String roleName) {
|
||||
ApprovalTestData.TestRole role = data.createRole(roleCode, roleName, TENANT);
|
||||
ApprovalTestData.TestUser member = data.createUser(roleName + data.uniqueSuffix(), organizationId, TENANT);
|
||||
data.bindTenant(member.userId, role.roleId, TENANT);
|
||||
return member;
|
||||
}
|
||||
|
||||
private void uploadAttachment(long instanceId) throws Exception {
|
||||
MockMultipartFile file = new MockMultipartFile("file", "quote.png", "image/png",
|
||||
new byte[]{(byte) 0x89, 'P', 'N', 'G', 0x0D, 0x0A, 0x1A, 0x0A});
|
||||
mockMvc.perform(multipart("/api/approval/attachment/upload")
|
||||
.file(file)
|
||||
.param("instanceId", String.valueOf(instanceId))
|
||||
.param("category", "OTHER")
|
||||
.header("tenantId", TENANT)
|
||||
.with(authentication(TestAuthentication.user(reporter.userId, reporter.username,
|
||||
organizationId, TENANT, SUBMIT))))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0));
|
||||
}
|
||||
|
||||
private long pendingTaskId(long instanceId, int userId) {
|
||||
Long taskId = data.queryMaster("SELECT id FROM approval_task WHERE instance_id = ? "
|
||||
+ "AND assignee_id = ? AND status = 'PENDING' LIMIT 1", Long.class, instanceId, userId);
|
||||
assertThat(taskId).as("待办任务应存在").isNotNull();
|
||||
return taskId;
|
||||
}
|
||||
|
||||
private MockHttpServletRequestBuilder authed(MockHttpServletRequestBuilder builder,
|
||||
ApprovalTestData.TestUser user, Integer org,
|
||||
String... authorities) {
|
||||
return builder.header("tenantId", TENANT)
|
||||
.with(authentication(TestAuthentication.user(user.userId, user.username, org, TENANT, authorities)));
|
||||
}
|
||||
|
||||
private String body(String applicantName, String applicantType, String start, String end,
|
||||
String siteName, String purpose, String activityFee) {
|
||||
return "{\"applicantName\":" + quote(applicantName)
|
||||
+ ",\"applicantType\":" + quote(applicantType)
|
||||
+ ",\"useStartTime\":" + quote(start)
|
||||
+ ",\"useEndTime\":" + quote(end)
|
||||
+ ",\"siteId\":88001"
|
||||
+ ",\"siteName\":" + quote(siteName)
|
||||
+ ",\"purpose\":" + quote(purpose)
|
||||
+ ",\"activityFee\":" + activityFee
|
||||
+ "}";
|
||||
}
|
||||
|
||||
private String quote(String value) {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
|
||||
}
|
||||
|
||||
private String instanceStatus(long instanceId) {
|
||||
return data.queryMaster("SELECT status FROM approval_instance WHERE id = ?", String.class, instanceId);
|
||||
}
|
||||
|
||||
private String bizNo(long instanceId) {
|
||||
return data.queryMaster("SELECT biz_no FROM approval_instance WHERE id = ?", String.class, instanceId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user