From ea2706976943b3700b1df81ae5e9356f7aa51608 Mon Sep 17 00:00:00 2001 From: zichun Date: Wed, 13 May 2026 17:58:25 +0800 Subject: [PATCH] feat(usr): UserConverter (MapStruct) + UserCreateVO REQ-USR-001 --- backend/src/main/java/com/xly/test4/module/usr/converter/UserConverter.java | 41 +++++++++++++++++++++++++++++++++++++++++ backend/src/main/java/com/xly/test4/module/usr/vo/UserCreateVO.java | 15 +++++++++++++++ backend/src/test/java/com/xly/test4/module/usr/converter/UserConverterTest.java | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 0 deletions(-) create mode 100644 backend/src/main/java/com/xly/test4/module/usr/converter/UserConverter.java create mode 100644 backend/src/main/java/com/xly/test4/module/usr/vo/UserCreateVO.java create mode 100644 backend/src/test/java/com/xly/test4/module/usr/converter/UserConverterTest.java diff --git a/backend/src/main/java/com/xly/test4/module/usr/converter/UserConverter.java b/backend/src/main/java/com/xly/test4/module/usr/converter/UserConverter.java new file mode 100644 index 0000000..5925a44 --- /dev/null +++ b/backend/src/main/java/com/xly/test4/module/usr/converter/UserConverter.java @@ -0,0 +1,41 @@ +package com.xly.test4.module.usr.converter; + +import com.xly.test4.module.usr.dto.UserCreateDTO; +import com.xly.test4.module.usr.entity.User; +import com.xly.test4.module.usr.vo.UserCreateVO; +import org.mapstruct.Builder; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +/** + * 关掉 MapStruct 自动选 Lombok @Builder,让其走 setter;User 字段如 `iIncrement` 经 JavaBeans + * Introspector 解析为 property `IIncrement`(第二字符大写,保持原 case),@Mapping 用此命名。 + */ +@Mapper(componentModel = "spring", builder = @Builder(disableBuilder = true)) +public interface UserConverter { + + @Mapping(target = "IIncrement", ignore = true) + @Mapping(target = "SId", ignore = true) + @Mapping(target = "SBrandsId", ignore = true) + @Mapping(target = "SSubsidiaryId", ignore = true) + @Mapping(target = "TCreateDate", ignore = true) + @Mapping(target = "TUpdateDate", ignore = true) + @Mapping(target = "TLastLoginDate", ignore = true) + @Mapping(target = "TLockedUntil", ignore = true) + @Mapping(target = "ILoginFailCount", ignore = true) + @Mapping(target = "IIsDisabled", ignore = true) + @Mapping(target = "SCreatedBy", ignore = true) + @Mapping(target = "SPasswordHash", ignore = true) + @Mapping(target = "SUserCode", source = "userCode") + @Mapping(target = "SUserName", source = "userName") + @Mapping(target = "IEmployeeId", source = "employeeId") + @Mapping(target = "SUserType", source = "userType") + @Mapping(target = "SLanguage", source = "language") + @Mapping(target = "ICanEditDoc", + expression = "java(dto.getCanEditDoc() != null && dto.getCanEditDoc() ? 1 : 0)") + User toEntity(UserCreateDTO dto); + + @Mapping(target = "userId", source = "IIncrement") + @Mapping(target = "userCode", source = "SUserCode") + UserCreateVO toVO(User user); +} diff --git a/backend/src/main/java/com/xly/test4/module/usr/vo/UserCreateVO.java b/backend/src/main/java/com/xly/test4/module/usr/vo/UserCreateVO.java new file mode 100644 index 0000000..05591a7 --- /dev/null +++ b/backend/src/main/java/com/xly/test4/module/usr/vo/UserCreateVO.java @@ -0,0 +1,15 @@ +package com.xly.test4.module.usr.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserCreateVO { + private Integer userId; + private String userCode; +} diff --git a/backend/src/test/java/com/xly/test4/module/usr/converter/UserConverterTest.java b/backend/src/test/java/com/xly/test4/module/usr/converter/UserConverterTest.java new file mode 100644 index 0000000..9cfce6d --- /dev/null +++ b/backend/src/test/java/com/xly/test4/module/usr/converter/UserConverterTest.java @@ -0,0 +1,75 @@ +package com.xly.test4.module.usr.converter; + +import com.xly.test4.module.usr.dto.UserCreateDTO; +import com.xly.test4.module.usr.entity.User; +import com.xly.test4.module.usr.vo.UserCreateVO; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +class UserConverterTest { + + private final UserConverter converter = Mappers.getMapper(UserConverter.class); + + private UserCreateDTO dto() { + UserCreateDTO dto = new UserCreateDTO(); + dto.setUserCode("U-100"); + dto.setUserName("bob"); + dto.setEmployeeId(7); + dto.setUserType("NORMAL"); + dto.setLanguage("en"); + dto.setCanEditDoc(true); + dto.setPassword("plain-pass"); + dto.setPermissionIds(List.of(1, 2)); + return dto; + } + + @Test + void toEntity_mapsAllFieldsExceptPasswordAndPermissions() { + User user = converter.toEntity(dto()); + + assertThat(user.getSUserCode()).isEqualTo("U-100"); + assertThat(user.getSUserName()).isEqualTo("bob"); + assertThat(user.getIEmployeeId()).isEqualTo(7); + assertThat(user.getSUserType()).isEqualTo("NORMAL"); + assertThat(user.getSLanguage()).isEqualTo("en"); + // password / 多租户 / sCreatedBy / iIsDisabled 等都不应在 toEntity 阶段填 + assertThat(user.getSPasswordHash()).isNull(); + assertThat(user.getSBrandsId()).isNull(); + assertThat(user.getSSubsidiaryId()).isNull(); + assertThat(user.getSCreatedBy()).isNull(); + assertThat(user.getIIsDisabled()).isNull(); + } + + @Test + void toEntity_canEditDocTrueMapsTo1() { + UserCreateDTO dto = dto(); + dto.setCanEditDoc(true); + + assertThat(converter.toEntity(dto).getICanEditDoc()).isEqualTo(1); + } + + @Test + void toEntity_canEditDocFalseMapsTo0() { + UserCreateDTO dto = dto(); + dto.setCanEditDoc(false); + + assertThat(converter.toEntity(dto).getICanEditDoc()).isZero(); + } + + @Test + void toVO_mapsIncrementToUserIdAndUserCode() { + User user = User.builder() + .iIncrement(42) + .sUserCode("U-100") + .sUserName("bob") + .build(); + + UserCreateVO vo = converter.toVO(user); + assertThat(vo.getUserId()).isEqualTo(42); + assertThat(vo.getUserCode()).isEqualTo("U-100"); + } +} -- libgit2 0.22.2