Commit 7eec9887448c484e3ba85407fc9af185ee1b696e

Authored by zichun
1 parent 38fbdcd0

feat(mod): module create dto + service happy path REQ-MOD-001

backend/src/main/java/com/xly/erp/module/mod/dto/CreateModuleDTO.java 0 → 100644
  1 +package com.xly.erp.module.mod.dto;
  2 +
  3 +import jakarta.validation.constraints.NotBlank;
  4 +import jakarta.validation.constraints.Size;
  5 +
  6 +public class CreateModuleDTO {
  7 +
  8 + @NotBlank
  9 + private String sDisplayType;
  10 +
  11 + @NotBlank
  12 + @Size(max = 100)
  13 + private String sProcedureName;
  14 +
  15 + @NotBlank
  16 + @Size(max = 50)
  17 + private String sModuleType;
  18 +
  19 + @NotBlank
  20 + @Size(max = 50)
  21 + private String sManageDeptEn;
  22 +
  23 + private Boolean bShowPermission;
  24 +
  25 + @NotBlank
  26 + @Size(max = 100)
  27 + private String sModuleNameZh;
  28 +
  29 + private Integer iParentId;
  30 +
  31 + private Integer iSortOrder;
  32 +
  33 + public String getSDisplayType() { return sDisplayType; }
  34 + public void setSDisplayType(String sDisplayType) { this.sDisplayType = sDisplayType; }
  35 + public String getSProcedureName() { return sProcedureName; }
  36 + public void setSProcedureName(String sProcedureName) { this.sProcedureName = sProcedureName; }
  37 + public String getSModuleType() { return sModuleType; }
  38 + public void setSModuleType(String sModuleType) { this.sModuleType = sModuleType; }
  39 + public String getSManageDeptEn() { return sManageDeptEn; }
  40 + public void setSManageDeptEn(String sManageDeptEn) { this.sManageDeptEn = sManageDeptEn; }
  41 + public Boolean getBShowPermission() { return bShowPermission; }
  42 + public void setBShowPermission(Boolean bShowPermission) { this.bShowPermission = bShowPermission; }
  43 + public String getSModuleNameZh() { return sModuleNameZh; }
  44 + public void setSModuleNameZh(String sModuleNameZh) { this.sModuleNameZh = sModuleNameZh; }
  45 + public Integer getIParentId() { return iParentId; }
  46 + public void setIParentId(Integer iParentId) { this.iParentId = iParentId; }
  47 + public Integer getISortOrder() { return iSortOrder; }
  48 + public void setISortOrder(Integer iSortOrder) { this.iSortOrder = iSortOrder; }
  49 +}
... ...
backend/src/main/java/com/xly/erp/module/mod/service/ModuleService.java 0 → 100644
  1 +package com.xly.erp.module.mod.service;
  2 +
  3 +import com.xly.erp.module.mod.dto.CreateModuleDTO;
  4 +
  5 +public interface ModuleService {
  6 + Integer create(CreateModuleDTO dto);
  7 +}
... ...
backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java 0 → 100644
  1 +package com.xly.erp.module.mod.service.impl;
  2 +
  3 +import com.xly.erp.common.config.StubSecurityProperties;
  4 +import com.xly.erp.common.config.TenantProperties;
  5 +import com.xly.erp.common.exception.BizException;
  6 +import com.xly.erp.common.security.SecurityContextHelper;
  7 +import com.xly.erp.module.mod.dto.CreateModuleDTO;
  8 +import com.xly.erp.module.mod.entity.Module;
  9 +import com.xly.erp.module.mod.mapper.ModuleMapper;
  10 +import com.xly.erp.module.mod.service.ModuleService;
  11 +import org.springframework.stereotype.Service;
  12 +import org.springframework.transaction.annotation.Transactional;
  13 +
  14 +import java.time.LocalDateTime;
  15 +
  16 +@Service
  17 +@Transactional(rollbackFor = Exception.class)
  18 +public class ModuleServiceImpl implements ModuleService {
  19 +
  20 + private final ModuleMapper moduleMapper;
  21 + private final TenantProperties tenant;
  22 + private final StubSecurityProperties stub;
  23 +
  24 + public ModuleServiceImpl(ModuleMapper moduleMapper,
  25 + TenantProperties tenant,
  26 + StubSecurityProperties stub) {
  27 + this.moduleMapper = moduleMapper;
  28 + this.tenant = tenant;
  29 + this.stub = stub;
  30 + }
  31 +
  32 + @Override
  33 + public Integer create(CreateModuleDTO dto) {
  34 + if (dto.getIParentId() != null && !moduleMapper.existsActiveById(dto.getIParentId())) {
  35 + throw new BizException(40021, "父模块不存在或已删除");
  36 + }
  37 +
  38 + Module m = new Module();
  39 + m.setSBrandsId(tenant.getBrandsId());
  40 + m.setSSubsidiaryId(tenant.getSubsidiaryId());
  41 + m.setTCreateDate(LocalDateTime.now());
  42 + m.setSDisplayType(dto.getSDisplayType());
  43 + m.setSProcedureName(dto.getSProcedureName());
  44 + m.setSModuleType(dto.getSModuleType());
  45 + m.setSManageDeptEn(dto.getSManageDeptEn());
  46 + m.setBShowPermission(dto.getBShowPermission() != null ? dto.getBShowPermission() : false);
  47 + m.setSModuleNameZh(dto.getSModuleNameZh());
  48 + m.setIParentId(dto.getIParentId());
  49 + m.setISortOrder(dto.getISortOrder() != null ? dto.getISortOrder() : 0);
  50 + String authedUserNo = SecurityContextHelper.currentUserNo();
  51 + m.setSCreatedBy(authedUserNo != null ? authedUserNo : stub.getStubUserNo());
  52 + m.setBDeleted(false);
  53 +
  54 + moduleMapper.insert(m);
  55 + return m.getIIncrement();
  56 + }
  57 +}
... ...
backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java 0 → 100644
  1 +package com.xly.erp.module.mod.service;
  2 +
  3 +import com.xly.erp.common.config.StubSecurityProperties;
  4 +import com.xly.erp.common.config.TenantProperties;
  5 +import com.xly.erp.common.exception.BizException;
  6 +import com.xly.erp.module.mod.dto.CreateModuleDTO;
  7 +import com.xly.erp.module.mod.entity.Module;
  8 +import com.xly.erp.module.mod.mapper.ModuleMapper;
  9 +import com.xly.erp.module.mod.service.impl.ModuleServiceImpl;
  10 +import org.junit.jupiter.api.AfterEach;
  11 +import org.junit.jupiter.api.BeforeEach;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.mockito.ArgumentCaptor;
  14 +import org.springframework.security.core.context.SecurityContextHolder;
  15 +
  16 +import static org.assertj.core.api.Assertions.assertThat;
  17 +import static org.assertj.core.api.Assertions.assertThatThrownBy;
  18 +import static org.mockito.ArgumentMatchers.any;
  19 +import static org.mockito.Mockito.lenient;
  20 +import static org.mockito.Mockito.mock;
  21 +import static org.mockito.Mockito.never;
  22 +import static org.mockito.Mockito.times;
  23 +import static org.mockito.Mockito.verify;
  24 +import static org.mockito.Mockito.when;
  25 +
  26 +class ModuleServiceImplTest {
  27 +
  28 + private ModuleMapper moduleMapper;
  29 + private ModuleServiceImpl service;
  30 +
  31 + @BeforeEach
  32 + void setUp() {
  33 + moduleMapper = mock(ModuleMapper.class);
  34 + TenantProperties tenant = new TenantProperties();
  35 + tenant.setBrandsId("XLY");
  36 + tenant.setSubsidiaryId("XLY");
  37 + StubSecurityProperties stub = new StubSecurityProperties();
  38 + stub.setStubUserNo("STUB_ADMIN");
  39 + service = new ModuleServiceImpl(moduleMapper, tenant, stub);
  40 +
  41 + lenient().when(moduleMapper.insert(any(Module.class))).thenAnswer(inv -> {
  42 + Module m = inv.getArgument(0);
  43 + m.setIIncrement(99);
  44 + return 1;
  45 + });
  46 + }
  47 +
  48 + @AfterEach
  49 + void clearContext() {
  50 + SecurityContextHolder.clearContext();
  51 + }
  52 +
  53 + @Test
  54 + void createWithValidDto_persistsWithStandardCols() {
  55 + CreateModuleDTO dto = baseDto();
  56 +
  57 + Integer id = service.create(dto);
  58 +
  59 + assertThat(id).isEqualTo(99);
  60 + ArgumentCaptor<Module> captor = ArgumentCaptor.forClass(Module.class);
  61 + verify(moduleMapper, times(1)).insert(captor.capture());
  62 + Module saved = captor.getValue();
  63 + assertThat(saved.getSBrandsId()).isEqualTo("XLY");
  64 + assertThat(saved.getSSubsidiaryId()).isEqualTo("XLY");
  65 + assertThat(saved.getTCreateDate()).isNotNull();
  66 + assertThat(saved.getSCreatedBy()).isEqualTo("STUB_ADMIN");
  67 + assertThat(saved.getBDeleted()).isFalse();
  68 + assertThat(saved.getBShowPermission()).isFalse();
  69 + assertThat(saved.getISortOrder()).isZero();
  70 + verify(moduleMapper, never()).findActiveFlagById(any());
  71 + }
  72 +
  73 + @Test
  74 + void createWithParentNotFound_throws40021() {
  75 + CreateModuleDTO dto = baseDto();
  76 + dto.setIParentId(42);
  77 + when(moduleMapper.findActiveFlagById(42)).thenReturn(null);
  78 +
  79 + assertThatThrownBy(() -> service.create(dto))
  80 + .isInstanceOf(BizException.class)
  81 + .hasFieldOrPropertyWithValue("code", 40021);
  82 + verify(moduleMapper, never()).insert(any(Module.class));
  83 + }
  84 +
  85 + private CreateModuleDTO baseDto() {
  86 + CreateModuleDTO dto = new CreateModuleDTO();
  87 + dto.setSDisplayType("手机端");
  88 + dto.setSProcedureName("sp_test_unit");
  89 + dto.setSModuleType("业务模块");
  90 + dto.setSManageDeptEn("IT");
  91 + dto.setSModuleNameZh("单测模块");
  92 + return dto;
  93 + }
  94 +}
... ...