diff --git a/backend/src/main/java/com/xly/erp/modules/usr/controller/UsrUserController.java b/backend/src/main/java/com/xly/erp/modules/usr/controller/UsrUserController.java index 2ac6132..775e7c6 100644 --- a/backend/src/main/java/com/xly/erp/modules/usr/controller/UsrUserController.java +++ b/backend/src/main/java/com/xly/erp/modules/usr/controller/UsrUserController.java @@ -1,14 +1,18 @@ package com.xly.erp.modules.usr.controller; import com.xly.erp.common.exception.BusinessException; +import com.xly.erp.common.response.PageResult; import com.xly.erp.common.response.Result; import com.xly.erp.common.response.ResultCode; import com.xly.erp.common.security.SecurityUtil; import com.xly.erp.modules.usr.dto.CreateUserDTO; import com.xly.erp.modules.usr.dto.UpdateUserDTO; +import com.xly.erp.modules.usr.dto.UserQueryDTO; import com.xly.erp.modules.usr.service.UsrUserService; +import com.xly.erp.modules.usr.vo.UserVO; import jakarta.validation.Valid; import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -58,4 +62,13 @@ public class UsrUserController { Integer updatedId = usrUserService.updateUser(id, dto); return Result.success(Map.of("id", updatedId)); } + + /** + * 查询用户(REQ-USR-003):任意已认证用户可调用(无管理员前置,spec § 8 D5)。 + * query 参数自动绑定到 {@link UserQueryDTO}(非 @RequestBody);仅 @Valid + 委派 Service。 + */ + @GetMapping("/users") + public Result> queryUsers(@Valid UserQueryDTO dto) { + return Result.success(usrUserService.queryUsers(dto)); + } } diff --git a/backend/src/test/java/com/xly/erp/modules/usr/controller/UsrUserControllerTest.java b/backend/src/test/java/com/xly/erp/modules/usr/controller/UsrUserControllerTest.java index 7842577..1e8693d 100644 --- a/backend/src/test/java/com/xly/erp/modules/usr/controller/UsrUserControllerTest.java +++ b/backend/src/test/java/com/xly/erp/modules/usr/controller/UsrUserControllerTest.java @@ -5,6 +5,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.ArgumentMatchers.eq; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -13,11 +14,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import com.fasterxml.jackson.databind.ObjectMapper; import com.xly.erp.common.exception.BusinessException; import com.xly.erp.common.exception.GlobalExceptionHandler; +import com.xly.erp.common.response.PageResult; import com.xly.erp.common.response.ResultCode; import com.xly.erp.common.security.SecurityUtil; import com.xly.erp.modules.usr.dto.CreateUserDTO; import com.xly.erp.modules.usr.dto.UpdateUserDTO; +import com.xly.erp.modules.usr.dto.UserQueryDTO; import com.xly.erp.modules.usr.service.UsrUserService; +import com.xly.erp.modules.usr.vo.UserVO; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -168,4 +173,61 @@ class UsrUserControllerTest { .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(40401)); } + + // ---------------- REQ-USR-003 T5:查询用户 Controller GET /api/usr/users(无管理员前置)---------------- + + private PageResult onePageResult() { + UserVO vo = new UserVO(); + vo.setId(1); + vo.setSUserName("alice"); + vo.setSUserType("普通用户"); + vo.setSLanguage("中文"); + vo.setIIsVoid(0); + return PageResult.of(List.of(vo), 1L, 1L, 10L); + } + + @Test + void queryReturnsCodeZeroWithPageResult() throws Exception { + when(usrUserService.queryUsers(any(UserQueryDTO.class))).thenReturn(onePageResult()); + + mockMvc.perform(get("/api/usr/users").param("pageNum", "1").param("pageSize", "10")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)) + .andExpect(jsonPath("$.data.total").value(1)) + .andExpect(jsonPath("$.data.pageNum").value(1)) + .andExpect(jsonPath("$.data.pageSize").value(10)) + .andExpect(jsonPath("$.data.records[0].sUserName").value("alice")) + .andExpect(jsonPath("$.data.records[0].sPassword").doesNotExist()) + .andExpect(jsonPath("$.data.records[0].password").doesNotExist()); + } + + @Test + void queryAllowsNonAdmin() throws Exception { + // 无管理员前置(spec § 8 D5):普通用户即可调用,Service 被调用。 + securityUtilMock.when(SecurityUtil::currentUserType).thenReturn("普通用户"); + when(usrUserService.queryUsers(any(UserQueryDTO.class))).thenReturn(onePageResult()); + + mockMvc.perform(get("/api/usr/users")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(0)); + verify(usrUserService).queryUsers(any(UserQueryDTO.class)); + } + + @Test + void queryIllegalEnumReturns40001() throws Exception { + mockMvc.perform(get("/api/usr/users").param("queryField", "身份证")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(40001)); + verify(usrUserService, never()).queryUsers(any(UserQueryDTO.class)); + } + + @Test + void queryPageParamInvalidReturns42201() throws Exception { + when(usrUserService.queryUsers(any(UserQueryDTO.class))) + .thenThrow(new BusinessException(ResultCode.PAGE_PARAM_INVALID)); + + mockMvc.perform(get("/api/usr/users").param("pageNum", "0")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(42201)); + } }