diff --git a/backend/src/main/java/com/xly/erp/module/usr/dto/UpdateUserReq.java b/backend/src/main/java/com/xly/erp/module/usr/dto/UpdateUserReq.java new file mode 100644 index 0000000..8ca932b --- /dev/null +++ b/backend/src/main/java/com/xly/erp/module/usr/dto/UpdateUserReq.java @@ -0,0 +1,37 @@ +package com.xly.erp.module.usr.dto; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +/** + * PATCH 语义:所有字段都可选;缺省 / 显式 null 视为不变。 + * 特例:employeeId == 0 视为解除关联(DB 写 NULL)。 + */ +@Data +public class UpdateUserReq { + + @Size(max = 50) + @Pattern(regexp = "^\\S+$", message = "userCode 不可为空白") + private String userCode; + + @Pattern(regexp = "NORMAL|SUPER_ADMIN", + message = "userType 必须为 NORMAL 或 SUPER_ADMIN") + private String userType; + + @Pattern(regexp = "zh-CN|en-US|zh-TW", + message = "language 必须为 zh-CN / en-US / zh-TW") + private String language; + + private Boolean canEditDocument; + + @Min(value = 0, message = "employeeId 必须 >= 0;0 表示解除关联") + private Integer employeeId; + + private Boolean isDeleted; + + private List permissionCategoryIds; +} diff --git a/backend/src/main/java/com/xly/erp/module/usr/vo/UserDetailVo.java b/backend/src/main/java/com/xly/erp/module/usr/vo/UserDetailVo.java new file mode 100644 index 0000000..7ebb395 --- /dev/null +++ b/backend/src/main/java/com/xly/erp/module/usr/vo/UserDetailVo.java @@ -0,0 +1,26 @@ +package com.xly.erp.module.usr.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class UserDetailVo { + private Integer userId; + private String username; + private String userCode; + private String userType; + private String language; + private Boolean canEditDocument; + private Boolean isDeleted; + private Integer employeeId; + private String employeeName; + private List permissionCategoryIds; + private String updatedBy; + private LocalDateTime updatedDate; +} diff --git a/backend/src/test/java/com/xly/erp/module/usr/dto/UpdateUserReqValidationTest.java b/backend/src/test/java/com/xly/erp/module/usr/dto/UpdateUserReqValidationTest.java new file mode 100644 index 0000000..8e421f4 --- /dev/null +++ b/backend/src/test/java/com/xly/erp/module/usr/dto/UpdateUserReqValidationTest.java @@ -0,0 +1,77 @@ +package com.xly.erp.module.usr.dto; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.*; + +class UpdateUserReqValidationTest { + + private static final Validator V = + Validation.buildDefaultValidatorFactory().getValidator(); + + @Test + void emptyBody_isValid() { + assertTrue(V.validate(new UpdateUserReq()).isEmpty()); + } + + @Test + void invalidUserType_fails() { + UpdateUserReq r = new UpdateUserReq(); + r.setUserType("ROOT"); + assertFalse(V.validate(r).isEmpty()); + } + + @Test + void invalidLanguage_fails() { + UpdateUserReq r = new UpdateUserReq(); + r.setLanguage("ja-JP"); + assertFalse(V.validate(r).isEmpty()); + } + + @Test + void userCodeTooLong_fails() { + UpdateUserReq r = new UpdateUserReq(); + r.setUserCode("X".repeat(51)); + assertFalse(V.validate(r).isEmpty()); + } + + @Test + void userCodeBlank_fails() { + UpdateUserReq r = new UpdateUserReq(); + r.setUserCode(" "); + assertFalse(V.validate(r).isEmpty()); + } + + @Test + void employeeIdNegative_fails() { + UpdateUserReq r = new UpdateUserReq(); + r.setEmployeeId(-1); + assertFalse(V.validate(r).isEmpty()); + } + + @Test + void employeeIdZero_isValid_meansUnsetRelation() { + UpdateUserReq r = new UpdateUserReq(); + r.setEmployeeId(0); + assertTrue(V.validate(r).isEmpty()); + } + + @Test + void allValidFields_passes() { + UpdateUserReq r = new UpdateUserReq(); + r.setUserCode("U999"); + r.setUserType("NORMAL"); + r.setLanguage("zh-CN"); + r.setCanEditDocument(true); + r.setEmployeeId(7); + r.setIsDeleted(false); + r.setPermissionCategoryIds(java.util.List.of(1, 2)); + Set> v = V.validate(r); + assertTrue(v.isEmpty(), () -> "should be empty but got: " + v); + } +}