Commit c6c415dc1341755b804ab2f717849ab818bf3421

Authored by zichun
1 parent acb6b046

feat(usr): user query DTO + list item VO REQ-USR-003

backend/src/main/java/com/xly/erp/module/usr/dto/UserQueryDTO.java 0 → 100644
  1 +package com.xly.erp.module.usr.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonIgnore;
  4 +import jakarta.validation.constraints.Max;
  5 +import jakarta.validation.constraints.Min;
  6 +import jakarta.validation.constraints.Pattern;
  7 +import jakarta.validation.constraints.Size;
  8 +import lombok.Data;
  9 +
  10 +/** REQ-USR-003 用户查询参数 DTO(query string 绑定)。 */
  11 +@Data
  12 +public class UserQueryDTO {
  13 +
  14 + @Min(1)
  15 + private Integer pageNum = 1;
  16 +
  17 + @Min(1)
  18 + @Max(100)
  19 + private Integer pageSize = 20;
  20 +
  21 + /** 可空:缺省视为不过滤;服务层白名单校验后映射到 column 字段 */
  22 + @Pattern(regexp = "^(username|staffname|userno|department|usertype|language|deleted|lastLoginDate|createdBy)?$",
  23 + message = "queryField 非法")
  24 + private String queryField;
  25 +
  26 + /** 可空:默认 contains */
  27 + @Pattern(regexp = "^(contains|notContains|equals)?$", message = "matchType 非法")
  28 + private String matchType;
  29 +
  30 + /** 可空:缺省视为不过滤 */
  31 + @Size(max = 100)
  32 + private String queryValue;
  33 +
  34 + /** 服务层白名单映射后的实际 SQL 列名(如 "u.sUserName")。
  35 + * Jackson 忽略——前端不能也无法直接传入;XML mapper 用 ${query.column} 渲染。 */
  36 + @JsonIgnore
  37 + private String column;
  38 +}
... ...
backend/src/main/java/com/xly/erp/module/usr/vo/UserListItemVO.java 0 → 100644
  1 +package com.xly.erp.module.usr.vo;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.time.LocalDateTime;
  6 +
  7 +/** REQ-USR-003 用户列表行 VO(含 LEFT JOIN tStaff 出来的 sStaffName / sDepartment)。 */
  8 +@Data
  9 +public class UserListItemVO {
  10 + private Integer iIncrement;
  11 + private String sUserName;
  12 + private String sStaffName;
  13 + private String sUserNo;
  14 + private String sDepartment;
  15 + private String sUserType;
  16 + private String sLanguage;
  17 + private Boolean bDeleted;
  18 + private LocalDateTime tLastLoginDate;
  19 + private String sCreatedBy;
  20 + private LocalDateTime tCreateDate;
  21 +}
... ...
backend/src/test/java/com/xly/erp/module/usr/dto/UserQueryDTOValidationTest.java 0 → 100644
  1 +package com.xly.erp.module.usr.dto;
  2 +
  3 +import jakarta.validation.ConstraintViolation;
  4 +import jakarta.validation.Validation;
  5 +import jakarta.validation.Validator;
  6 +import jakarta.validation.ValidatorFactory;
  7 +import org.junit.jupiter.api.Test;
  8 +
  9 +import java.util.Set;
  10 +
  11 +import static org.assertj.core.api.Assertions.assertThat;
  12 +
  13 +class UserQueryDTOValidationTest {
  14 +
  15 + private static final ValidatorFactory FACTORY = Validation.buildDefaultValidatorFactory();
  16 + private final Validator validator = FACTORY.getValidator();
  17 +
  18 + private UserQueryDTO valid() {
  19 + UserQueryDTO d = new UserQueryDTO();
  20 + d.setPageNum(1);
  21 + d.setPageSize(20);
  22 + d.setQueryField("username");
  23 + d.setMatchType("contains");
  24 + d.setQueryValue("alice");
  25 + return d;
  26 + }
  27 +
  28 + @Test
  29 + void allValid_yieldsNoViolations() {
  30 + Set<ConstraintViolation<UserQueryDTO>> v = validator.validate(valid());
  31 + assertThat(v).isEmpty();
  32 + }
  33 +
  34 + @Test
  35 + void pageSizeTooLarge_yieldsViolation() {
  36 + UserQueryDTO d = valid();
  37 + d.setPageSize(101);
  38 + Set<ConstraintViolation<UserQueryDTO>> v = validator.validate(d);
  39 + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()).contains("pageSize");
  40 + }
  41 +
  42 + @Test
  43 + void pageSizeTooSmall_yieldsViolation() {
  44 + UserQueryDTO d = valid();
  45 + d.setPageSize(0);
  46 + Set<ConstraintViolation<UserQueryDTO>> v = validator.validate(d);
  47 + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()).contains("pageSize");
  48 + }
  49 +
  50 + @Test
  51 + void queryFieldInvalidEnum_yieldsViolation() {
  52 + UserQueryDTO d = valid();
  53 + d.setQueryField("invalid_field");
  54 + Set<ConstraintViolation<UserQueryDTO>> v = validator.validate(d);
  55 + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()).contains("queryField");
  56 + }
  57 +
  58 + @Test
  59 + void queryValueOverSized_yieldsViolation() {
  60 + UserQueryDTO d = valid();
  61 + d.setQueryValue("a".repeat(101));
  62 + Set<ConstraintViolation<UserQueryDTO>> v = validator.validate(d);
  63 + assertThat(v).extracting(cv -> cv.getPropertyPath().toString()).contains("queryValue");
  64 + }
  65 +}
... ...