Commit e00bb2bd9fdc8fd18cb5da4844831d90c8adf326

Authored by zichun
1 parent 0017a259

feat(mod): POST /api/mod/modules controller REQ-MOD-001

backend/src/main/java/com/xly/erp/module/mod/controller/ModuleController.java 0 → 100644
  1 +package com.xly.erp.module.mod.controller;
  2 +
  3 +import com.xly.erp.common.response.Result;
  4 +import com.xly.erp.module.mod.dto.CreateModuleDTO;
  5 +import com.xly.erp.module.mod.service.ModuleService;
  6 +import jakarta.validation.Valid;
  7 +import org.springframework.web.bind.annotation.PostMapping;
  8 +import org.springframework.web.bind.annotation.RequestBody;
  9 +import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.RestController;
  11 +
  12 +import java.util.Map;
  13 +
  14 +@RestController
  15 +@RequestMapping("/api/mod")
  16 +public class ModuleController {
  17 +
  18 + private final ModuleService moduleService;
  19 +
  20 + public ModuleController(ModuleService moduleService) {
  21 + this.moduleService = moduleService;
  22 + }
  23 +
  24 + @PostMapping("/modules")
  25 + public Result<Map<String, Integer>> create(@Valid @RequestBody CreateModuleDTO dto) {
  26 + Integer id = moduleService.create(dto);
  27 + return Result.ok(Map.of("iIncrement", id));
  28 + }
  29 +}
... ...
backend/src/main/java/com/xly/erp/module/mod/dto/CreateModuleDTO.java
1 1 package com.xly.erp.module.mod.dto;
2 2  
  3 +import com.fasterxml.jackson.annotation.JsonProperty;
3 4 import jakarta.validation.constraints.NotBlank;
4 5 import jakarta.validation.constraints.Size;
5 6  
6 7 public class CreateModuleDTO {
7 8  
  9 + @JsonProperty("sDisplayType")
8 10 @NotBlank
9 11 private String sDisplayType;
10 12  
  13 + @JsonProperty("sProcedureName")
11 14 @NotBlank
12 15 @Size(max = 100)
13 16 private String sProcedureName;
14 17  
  18 + @JsonProperty("sModuleType")
15 19 @NotBlank
16 20 @Size(max = 50)
17 21 private String sModuleType;
18 22  
  23 + @JsonProperty("sManageDeptEn")
19 24 @NotBlank
20 25 @Size(max = 50)
21 26 private String sManageDeptEn;
22 27  
  28 + @JsonProperty("bShowPermission")
23 29 private Boolean bShowPermission;
24 30  
  31 + @JsonProperty("sModuleNameZh")
25 32 @NotBlank
26 33 @Size(max = 100)
27 34 private String sModuleNameZh;
28 35  
  36 + @JsonProperty("iParentId")
29 37 private Integer iParentId;
30 38  
  39 + @JsonProperty("iSortOrder")
31 40 private Integer iSortOrder;
32 41  
33 42 public String getSDisplayType() { return sDisplayType; }
... ...
backend/src/test/java/com/xly/erp/module/mod/controller/ModuleControllerIT.java 0 → 100644
  1 +package com.xly.erp.module.mod.controller;
  2 +
  3 +import com.fasterxml.jackson.databind.JsonNode;
  4 +import com.fasterxml.jackson.databind.ObjectMapper;
  5 +import com.xly.erp.common.security.TestJwtHelper;
  6 +import org.junit.jupiter.api.AfterEach;
  7 +import org.junit.jupiter.api.BeforeEach;
  8 +import org.junit.jupiter.api.Test;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.boot.test.context.SpringBootTest;
  11 +import org.springframework.boot.test.web.client.TestRestTemplate;
  12 +import org.springframework.boot.test.web.server.LocalServerPort;
  13 +import org.springframework.http.HttpEntity;
  14 +import org.springframework.http.HttpHeaders;
  15 +import org.springframework.http.HttpMethod;
  16 +import org.springframework.http.MediaType;
  17 +import org.springframework.http.ResponseEntity;
  18 +import org.springframework.jdbc.core.JdbcTemplate;
  19 +import org.springframework.test.context.ActiveProfiles;
  20 +
  21 +import java.util.HashMap;
  22 +import java.util.Map;
  23 +
  24 +import static org.assertj.core.api.Assertions.assertThat;
  25 +
  26 +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
  27 +@ActiveProfiles("test")
  28 +class ModuleControllerIT {
  29 +
  30 + @Autowired
  31 + private TestRestTemplate rest;
  32 +
  33 + @Autowired
  34 + private TestJwtHelper testJwtHelper;
  35 +
  36 + @Autowired
  37 + private JdbcTemplate jdbcTemplate;
  38 +
  39 + @Autowired
  40 + private ObjectMapper objectMapper;
  41 +
  42 + @LocalServerPort
  43 + private int port;
  44 +
  45 + @BeforeEach
  46 + @AfterEach
  47 + void cleanup() {
  48 + jdbcTemplate.update("DELETE FROM tModule WHERE sProcedureName LIKE 'sp_test_%'");
  49 + }
  50 +
  51 + @Test
  52 + void postValidBody_with_jwt_returns200_andPersists() throws Exception {
  53 + String token = testJwtHelper.signFor("ADMIN001");
  54 + HttpHeaders headers = jsonHeaders();
  55 + headers.set("Authorization", "Bearer " + token);
  56 +
  57 + ResponseEntity<String> resp = rest.exchange(
  58 + "http://localhost:" + port + "/api/mod/modules",
  59 + HttpMethod.POST,
  60 + new HttpEntity<>(validBody("sp_test_ctrl_ok", "正常路径"), headers),
  61 + String.class);
  62 +
  63 + assertThat(resp.getStatusCode().value()).isEqualTo(200);
  64 + JsonNode body = objectMapper.readTree(resp.getBody());
  65 + assertThat(body.get("code").asInt()).isZero();
  66 + int newId = body.get("data").get("iIncrement").asInt();
  67 + assertThat(newId).isPositive();
  68 +
  69 + Map<String, Object> row = jdbcTemplate.queryForMap(
  70 + "SELECT sProcedureName, sBrandsId, sCreatedBy FROM tModule WHERE iIncrement = ?", newId);
  71 + assertThat(row.get("sProcedureName")).isEqualTo("sp_test_ctrl_ok");
  72 + assertThat(row.get("sBrandsId")).isEqualTo("XLY");
  73 + assertThat(row.get("sCreatedBy")).isEqualTo("ADMIN001");
  74 + }
  75 +
  76 + static HttpHeaders jsonHeaders() {
  77 + HttpHeaders h = new HttpHeaders();
  78 + h.setContentType(MediaType.APPLICATION_JSON);
  79 + return h;
  80 + }
  81 +
  82 + static Map<String, Object> validBody(String procedureName, String nameZh) {
  83 + Map<String, Object> m = new HashMap<>();
  84 + m.put("sDisplayType", "手机端");
  85 + m.put("sProcedureName", procedureName);
  86 + m.put("sModuleType", "业务模块");
  87 + m.put("sManageDeptEn", "IT");
  88 + m.put("bShowPermission", false);
  89 + m.put("sModuleNameZh", nameZh);
  90 + return m;
  91 + }
  92 +}
... ...