Commit 6c3fcaba50068584aa482100ffea4785140a67fd

Authored by zichun
1 parent d05911cd

feat(usr): 用户相关实体/Mapper/CreateUserDTO 校验 REQ-USR-001

backend/src/main/java/com/xly/erp/modules/usr/dto/CreateUserDTO.java 0 → 100644
  1 +package com.xly.erp.modules.usr.dto;
  2 +
  3 +import jakarta.validation.constraints.Max;
  4 +import jakarta.validation.constraints.Min;
  5 +import jakarta.validation.constraints.NotBlank;
  6 +import jakarta.validation.constraints.Pattern;
  7 +import jakarta.validation.constraints.Size;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 新增用户入参(docs/05 契约 / spec § 2.1)。
  12 + *
  13 + * <p>REQ-USR-001 T4。Bean Validation 注解校验格式 / 必填 / 枚举;
  14 + * 关联 id 存在性、枚举兜底后越界判定在 Service 处理。</p>
  15 + */
  16 +public class CreateUserDTO {
  17 +
  18 + /** 用户名:必填,3-20 位字母 / 数字 / 下划线,全局唯一。 */
  19 + @NotBlank(message = "用户名不能为空")
  20 + @Pattern(regexp = "^[A-Za-z0-9_]{3,20}$", message = "用户名须为 3-20 位字母、数字或下划线")
  21 + private String sUserName;
  22 +
  23 + /** 用户号:可选。 */
  24 + @Size(max = 50, message = "用户号长度不能超过 50")
  25 + private String sUserNo;
  26 +
  27 + /** 关联职员 ID:可选,存在性在 Service 校验。 */
  28 + private Integer iEmployeeId;
  29 +
  30 + /** 用户类型:可选,为空时 Service 兜底「普通用户」;非空须为合法枚举。 */
  31 + @Pattern(regexp = "^(普通用户|超级管理员)$", message = "用户类型取值非法")
  32 + private String sUserType;
  33 +
  34 + /** 界面语言:必填,取值 ∈ {中文, 英文, 繁体}。 */
  35 + @NotBlank(message = "语言不能为空")
  36 + @Pattern(regexp = "^(中文|英文|繁体)$", message = "语言取值非法")
  37 + private String sLanguage;
  38 +
  39 + /** 单据修改权限:可选,0 / 1,为空时 Service 兜底 0。 */
  40 + @Min(value = 0, message = "单据修改权限取值非法")
  41 + @Max(value = 1, message = "单据修改权限取值非法")
  42 + private Integer iCanModifyBill;
  43 +
  44 + /** 权限组 ID 列表:可选,元素存在性在 Service 校验。 */
  45 + private List<Integer> permissionIds;
  46 +
  47 + /** 初始密码:可选,为空时 Service 兜底 666666。 */
  48 + @Size(max = 100, message = "初始密码长度不能超过 100")
  49 + private String initialPassword;
  50 +
  51 + public String getSUserName() {
  52 + return sUserName;
  53 + }
  54 +
  55 + public void setSUserName(String sUserName) {
  56 + this.sUserName = sUserName;
  57 + }
  58 +
  59 + public String getSUserNo() {
  60 + return sUserNo;
  61 + }
  62 +
  63 + public void setSUserNo(String sUserNo) {
  64 + this.sUserNo = sUserNo;
  65 + }
  66 +
  67 + public Integer getIEmployeeId() {
  68 + return iEmployeeId;
  69 + }
  70 +
  71 + public void setIEmployeeId(Integer iEmployeeId) {
  72 + this.iEmployeeId = iEmployeeId;
  73 + }
  74 +
  75 + public String getSUserType() {
  76 + return sUserType;
  77 + }
  78 +
  79 + public void setSUserType(String sUserType) {
  80 + this.sUserType = sUserType;
  81 + }
  82 +
  83 + public String getSLanguage() {
  84 + return sLanguage;
  85 + }
  86 +
  87 + public void setSLanguage(String sLanguage) {
  88 + this.sLanguage = sLanguage;
  89 + }
  90 +
  91 + public Integer getICanModifyBill() {
  92 + return iCanModifyBill;
  93 + }
  94 +
  95 + public void setICanModifyBill(Integer iCanModifyBill) {
  96 + this.iCanModifyBill = iCanModifyBill;
  97 + }
  98 +
  99 + public List<Integer> getPermissionIds() {
  100 + return permissionIds;
  101 + }
  102 +
  103 + public void setPermissionIds(List<Integer> permissionIds) {
  104 + this.permissionIds = permissionIds;
  105 + }
  106 +
  107 + public String getInitialPassword() {
  108 + return initialPassword;
  109 + }
  110 +
  111 + public void setInitialPassword(String initialPassword) {
  112 + this.initialPassword = initialPassword;
  113 + }
  114 +}
backend/src/main/java/com/xly/erp/modules/usr/entity/UsrEmployee.java 0 → 100644
  1 +package com.xly.erp.modules.usr.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableField;
  4 +import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.xly.erp.common.base.BaseEntity;
  6 +
  7 +/**
  8 + * 职员实体,映射 {@code usr_employee}(docs/03 SSoT)。
  9 + *
  10 + * <p>REQ-USR-001 T4。本 REQ 仅用于校验 iEmployeeId 存在性(读)。</p>
  11 + */
  12 +@TableName("usr_employee")
  13 +public class UsrEmployee extends BaseEntity {
  14 +
  15 + private static final long serialVersionUID = 1L;
  16 +
  17 + /** 职员 / 员工姓名。 */
  18 + @TableField("sEmployeeName")
  19 + private String sEmployeeName;
  20 +
  21 + /** 员工编号。 */
  22 + @TableField("sEmployeeNo")
  23 + private String sEmployeeNo;
  24 +
  25 + /** 所属部门。 */
  26 + @TableField("sDepartment")
  27 + private String sDepartment;
  28 +
  29 + public String getSEmployeeName() {
  30 + return sEmployeeName;
  31 + }
  32 +
  33 + public void setSEmployeeName(String sEmployeeName) {
  34 + this.sEmployeeName = sEmployeeName;
  35 + }
  36 +
  37 + public String getSEmployeeNo() {
  38 + return sEmployeeNo;
  39 + }
  40 +
  41 + public void setSEmployeeNo(String sEmployeeNo) {
  42 + this.sEmployeeNo = sEmployeeNo;
  43 + }
  44 +
  45 + public String getSDepartment() {
  46 + return sDepartment;
  47 + }
  48 +
  49 + public void setSDepartment(String sDepartment) {
  50 + this.sDepartment = sDepartment;
  51 + }
  52 +}
backend/src/main/java/com/xly/erp/modules/usr/entity/UsrPermission.java 0 → 100644
  1 +package com.xly.erp.modules.usr.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableField;
  4 +import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.xly.erp.common.base.BaseEntity;
  6 +
  7 +/**
  8 + * 权限实体,映射 {@code usr_permission}(docs/03 SSoT)。
  9 + *
  10 + * <p>REQ-USR-001 T4。本 REQ 仅用于校验 permissionIds 元素存在性(读)。</p>
  11 + */
  12 +@TableName("usr_permission")
  13 +public class UsrPermission extends BaseEntity {
  14 +
  15 + private static final long serialVersionUID = 1L;
  16 +
  17 + /** 权限名称。 */
  18 + @TableField("sPermissionName")
  19 + private String sPermissionName;
  20 +
  21 + /** 权限编码(系统内唯一)。 */
  22 + @TableField("sPermissionCode")
  23 + private String sPermissionCode;
  24 +
  25 + /** 权限分类。 */
  26 + @TableField("sPermissionCategory")
  27 + private String sPermissionCategory;
  28 +
  29 + public String getSPermissionName() {
  30 + return sPermissionName;
  31 + }
  32 +
  33 + public void setSPermissionName(String sPermissionName) {
  34 + this.sPermissionName = sPermissionName;
  35 + }
  36 +
  37 + public String getSPermissionCode() {
  38 + return sPermissionCode;
  39 + }
  40 +
  41 + public void setSPermissionCode(String sPermissionCode) {
  42 + this.sPermissionCode = sPermissionCode;
  43 + }
  44 +
  45 + public String getSPermissionCategory() {
  46 + return sPermissionCategory;
  47 + }
  48 +
  49 + public void setSPermissionCategory(String sPermissionCategory) {
  50 + this.sPermissionCategory = sPermissionCategory;
  51 + }
  52 +}
backend/src/main/java/com/xly/erp/modules/usr/entity/UsrUser.java 0 → 100644
  1 +package com.xly.erp.modules.usr.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableField;
  4 +import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.fasterxml.jackson.annotation.JsonIgnore;
  6 +import com.xly.erp.common.base.BaseEntity;
  7 +import java.time.LocalDateTime;
  8 +
  9 +/**
  10 + * 用户实体,映射 {@code usr_user}(docs/03 SSoT)。
  11 + *
  12 + * <p>REQ-USR-001 T4。继承 {@link BaseEntity} 复用标准列;密码列 {@code sPassword}
  13 + * 标注 {@link JsonIgnore} 防止序列化输出。</p>
  14 + */
  15 +@TableName("usr_user")
  16 +public class UsrUser extends BaseEntity {
  17 +
  18 + private static final long serialVersionUID = 1L;
  19 +
  20 + /** 用户名,登录账号,全局唯一。 */
  21 + @TableField("sUserName")
  22 + private String sUserName;
  23 +
  24 + /** 用户号。 */
  25 + @TableField("sUserNo")
  26 + private String sUserNo;
  27 +
  28 + /** 登录密码,BCrypt 哈希存储;禁止序列化输出。 */
  29 + @JsonIgnore
  30 + @TableField("sPassword")
  31 + private String sPassword;
  32 +
  33 + /** 关联职员 ID(可选)。 */
  34 + @TableField("iEmployeeId")
  35 + private Integer iEmployeeId;
  36 +
  37 + /** 用户类型:普通用户 / 超级管理员。 */
  38 + @TableField("sUserType")
  39 + private String sUserType;
  40 +
  41 + /** 界面语言:中文 / 英文 / 繁体。 */
  42 + @TableField("sLanguage")
  43 + private String sLanguage;
  44 +
  45 + /** 单据修改权限:0 否 / 1 是。 */
  46 + @TableField("iCanModifyBill")
  47 + private Integer iCanModifyBill;
  48 +
  49 + /** 作废 / 禁用标志:0 正常 / 1 已作废。 */
  50 + @TableField("iIsVoid")
  51 + private Integer iIsVoid;
  52 +
  53 + /** 最后登录时间。 */
  54 + @TableField("tLastLoginDate")
  55 + private LocalDateTime tLastLoginDate;
  56 +
  57 + /** 制单人(创建该用户的操作员用户名)。 */
  58 + @TableField("sCreator")
  59 + private String sCreator;
  60 +
  61 + public String getSUserName() {
  62 + return sUserName;
  63 + }
  64 +
  65 + public void setSUserName(String sUserName) {
  66 + this.sUserName = sUserName;
  67 + }
  68 +
  69 + public String getSUserNo() {
  70 + return sUserNo;
  71 + }
  72 +
  73 + public void setSUserNo(String sUserNo) {
  74 + this.sUserNo = sUserNo;
  75 + }
  76 +
  77 + public String getSPassword() {
  78 + return sPassword;
  79 + }
  80 +
  81 + public void setSPassword(String sPassword) {
  82 + this.sPassword = sPassword;
  83 + }
  84 +
  85 + public Integer getIEmployeeId() {
  86 + return iEmployeeId;
  87 + }
  88 +
  89 + public void setIEmployeeId(Integer iEmployeeId) {
  90 + this.iEmployeeId = iEmployeeId;
  91 + }
  92 +
  93 + public String getSUserType() {
  94 + return sUserType;
  95 + }
  96 +
  97 + public void setSUserType(String sUserType) {
  98 + this.sUserType = sUserType;
  99 + }
  100 +
  101 + public String getSLanguage() {
  102 + return sLanguage;
  103 + }
  104 +
  105 + public void setSLanguage(String sLanguage) {
  106 + this.sLanguage = sLanguage;
  107 + }
  108 +
  109 + public Integer getICanModifyBill() {
  110 + return iCanModifyBill;
  111 + }
  112 +
  113 + public void setICanModifyBill(Integer iCanModifyBill) {
  114 + this.iCanModifyBill = iCanModifyBill;
  115 + }
  116 +
  117 + public Integer getIIsVoid() {
  118 + return iIsVoid;
  119 + }
  120 +
  121 + public void setIIsVoid(Integer iIsVoid) {
  122 + this.iIsVoid = iIsVoid;
  123 + }
  124 +
  125 + public LocalDateTime getTLastLoginDate() {
  126 + return tLastLoginDate;
  127 + }
  128 +
  129 + public void setTLastLoginDate(LocalDateTime tLastLoginDate) {
  130 + this.tLastLoginDate = tLastLoginDate;
  131 + }
  132 +
  133 + public String getSCreator() {
  134 + return sCreator;
  135 + }
  136 +
  137 + public void setSCreator(String sCreator) {
  138 + this.sCreator = sCreator;
  139 + }
  140 +}
backend/src/main/java/com/xly/erp/modules/usr/entity/UsrUserPermission.java 0 → 100644
  1 +package com.xly.erp.modules.usr.entity;
  2 +
  3 +import com.baomidou.mybatisplus.annotation.TableField;
  4 +import com.baomidou.mybatisplus.annotation.TableName;
  5 +import com.xly.erp.common.base.BaseEntity;
  6 +
  7 +/**
  8 + * 用户权限关联实体,映射 {@code usr_user_permission}(docs/03 SSoT)。
  9 + *
  10 + * <p>REQ-USR-001 T4。用户 ↔ 权限多对多授权;唯一索引 {@code uk_usr_user_permission}
  11 + * on (iUserId, iPermissionId)。</p>
  12 + */
  13 +@TableName("usr_user_permission")
  14 +public class UsrUserPermission extends BaseEntity {
  15 +
  16 + private static final long serialVersionUID = 1L;
  17 +
  18 + /** 用户 ID,外键 -> usr_user.iIncrement。 */
  19 + @TableField("iUserId")
  20 + private Integer iUserId;
  21 +
  22 + /** 权限 ID,外键 -> usr_permission.iIncrement。 */
  23 + @TableField("iPermissionId")
  24 + private Integer iPermissionId;
  25 +
  26 + public UsrUserPermission() {
  27 + }
  28 +
  29 + public UsrUserPermission(Integer iUserId, Integer iPermissionId) {
  30 + this.iUserId = iUserId;
  31 + this.iPermissionId = iPermissionId;
  32 + }
  33 +
  34 + public Integer getIUserId() {
  35 + return iUserId;
  36 + }
  37 +
  38 + public void setIUserId(Integer iUserId) {
  39 + this.iUserId = iUserId;
  40 + }
  41 +
  42 + public Integer getIPermissionId() {
  43 + return iPermissionId;
  44 + }
  45 +
  46 + public void setIPermissionId(Integer iPermissionId) {
  47 + this.iPermissionId = iPermissionId;
  48 + }
  49 +}
backend/src/main/java/com/xly/erp/modules/usr/mapper/UsrEmployeeMapper.java 0 → 100644
  1 +package com.xly.erp.modules.usr.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.xly.erp.modules.usr.entity.UsrEmployee;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * 职员 Mapper(MyBatis-Plus),本 REQ 用于存在性校验。REQ-USR-001 T4。
  9 + */
  10 +@Mapper
  11 +public interface UsrEmployeeMapper extends BaseMapper<UsrEmployee> {
  12 +}
backend/src/main/java/com/xly/erp/modules/usr/mapper/UsrPermissionMapper.java 0 → 100644
  1 +package com.xly.erp.modules.usr.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.xly.erp.modules.usr.entity.UsrPermission;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * 权限 Mapper(MyBatis-Plus),本 REQ 用于存在性校验。REQ-USR-001 T4。
  9 + */
  10 +@Mapper
  11 +public interface UsrPermissionMapper extends BaseMapper<UsrPermission> {
  12 +}
backend/src/main/java/com/xly/erp/modules/usr/mapper/UsrUserMapper.java 0 → 100644
  1 +package com.xly.erp.modules.usr.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.xly.erp.modules.usr.entity.UsrUser;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * 用户 Mapper(MyBatis-Plus)。REQ-USR-001 T4。
  9 + */
  10 +@Mapper
  11 +public interface UsrUserMapper extends BaseMapper<UsrUser> {
  12 +}
backend/src/main/java/com/xly/erp/modules/usr/mapper/UsrUserPermissionMapper.java 0 → 100644
  1 +package com.xly.erp.modules.usr.mapper;
  2 +
  3 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.xly.erp.modules.usr.entity.UsrUserPermission;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * 用户权限关联 Mapper(MyBatis-Plus)。REQ-USR-001 T4。
  9 + */
  10 +@Mapper
  11 +public interface UsrUserPermissionMapper extends BaseMapper<UsrUserPermission> {
  12 +}
backend/src/test/java/com/xly/erp/modules/usr/dto/CreateUserDTOValidationTest.java 0 → 100644
  1 +package com.xly.erp.modules.usr.dto;
  2 +
  3 +import static org.assertj.core.api.Assertions.assertThat;
  4 +
  5 +import jakarta.validation.Validation;
  6 +import jakarta.validation.Validator;
  7 +import jakarta.validation.ValidatorFactory;
  8 +import java.util.Set;
  9 +import jakarta.validation.ConstraintViolation;
  10 +import org.junit.jupiter.api.AfterAll;
  11 +import org.junit.jupiter.api.BeforeAll;
  12 +import org.junit.jupiter.api.Test;
  13 +
  14 +/**
  15 + * REQ-USR-001 T4:CreateUserDTO Bean Validation 校验。
  16 + */
  17 +class CreateUserDTOValidationTest {
  18 +
  19 + private static ValidatorFactory factory;
  20 + private static Validator validator;
  21 +
  22 + @BeforeAll
  23 + static void setUp() {
  24 + factory = Validation.buildDefaultValidatorFactory();
  25 + validator = factory.getValidator();
  26 + }
  27 +
  28 + @AfterAll
  29 + static void tearDown() {
  30 + if (factory != null) {
  31 + factory.close();
  32 + }
  33 + }
  34 +
  35 + @Test
  36 + void rejectsBadUserName() {
  37 + CreateUserDTO dto = new CreateUserDTO();
  38 + dto.setSUserName("ab");
  39 + dto.setSLanguage("中文");
  40 + Set<ConstraintViolation<CreateUserDTO>> violations = validator.validate(dto);
  41 + assertThat(violations)
  42 + .anyMatch(v -> v.getPropertyPath().toString().equals("sUserName"));
  43 + }
  44 +
  45 + @Test
  46 + void rejectsIllegalLanguage() {
  47 + CreateUserDTO dto = new CreateUserDTO();
  48 + dto.setSUserName("good_user");
  49 + dto.setSLanguage("日文");
  50 + Set<ConstraintViolation<CreateUserDTO>> violations = validator.validate(dto);
  51 + assertThat(violations)
  52 + .anyMatch(v -> v.getPropertyPath().toString().equals("sLanguage"));
  53 + }
  54 +
  55 + @Test
  56 + void acceptsMinimalValidBody() {
  57 + CreateUserDTO dto = new CreateUserDTO();
  58 + dto.setSUserName("good_user");
  59 + dto.setSLanguage("中文");
  60 + Set<ConstraintViolation<CreateUserDTO>> violations = validator.validate(dto);
  61 + assertThat(violations).isEmpty();
  62 + }
  63 +}