diff --git a/backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java b/backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java index e84a888..b488a18 100644 --- a/backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java +++ b/backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java @@ -8,15 +8,19 @@ import com.xly.erp.module.mod.dto.CreateModuleDTO; import com.xly.erp.module.mod.entity.Module; import com.xly.erp.module.mod.mapper.ModuleMapper; import com.xly.erp.module.mod.service.ModuleService; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.util.Set; @Service @Transactional(rollbackFor = Exception.class) public class ModuleServiceImpl implements ModuleService { + private static final Set DISPLAY_TYPES = Set.of("手机端", "前端业务", "系统配置", "接口"); + private final ModuleMapper moduleMapper; private final TenantProperties tenant; private final StubSecurityProperties stub; @@ -31,6 +35,9 @@ public class ModuleServiceImpl implements ModuleService { @Override public Integer create(CreateModuleDTO dto) { + if (!DISPLAY_TYPES.contains(dto.getSDisplayType())) { + throw new BizException(40010, "显示类型枚举不合法"); + } if (dto.getIParentId() != null && !moduleMapper.existsActiveById(dto.getIParentId())) { throw new BizException(40021, "父模块不存在或已删除"); } @@ -51,7 +58,11 @@ public class ModuleServiceImpl implements ModuleService { m.setSCreatedBy(authedUserNo != null ? authedUserNo : stub.getStubUserNo()); m.setBDeleted(false); - moduleMapper.insert(m); + try { + moduleMapper.insert(m); + } catch (DuplicateKeyException e) { + throw new BizException(40020, "存储过程名称已存在"); + } return m.getIIncrement(); } } diff --git a/backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java b/backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java index 58c9bb1..fd0c70b 100644 --- a/backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java +++ b/backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java @@ -11,8 +11,12 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; +import java.util.Collections; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; @@ -82,6 +86,52 @@ class ModuleServiceImplTest { verify(moduleMapper, never()).insert(any(Module.class)); } + @Test + void createWithInvalidDisplayType_throws40010() { + CreateModuleDTO dto = baseDto(); + dto.setSDisplayType("未知"); + + assertThatThrownBy(() -> service.create(dto)) + .isInstanceOf(BizException.class) + .hasFieldOrPropertyWithValue("code", 40010); + verify(moduleMapper, never()).insert(any(Module.class)); + } + + @Test + void createWithNullParentId_skipsParentCheck() { + CreateModuleDTO dto = baseDto(); + dto.setIParentId(null); + + service.create(dto); + + verify(moduleMapper, never()).findActiveFlagById(any()); + verify(moduleMapper, times(1)).insert(any(Module.class)); + } + + @Test + void mapperDuplicateKey_throws40020() { + CreateModuleDTO dto = baseDto(); + when(moduleMapper.insert(any(Module.class))) + .thenThrow(new DuplicateKeyException("uk_procedure_name")); + + assertThatThrownBy(() -> service.create(dto)) + .isInstanceOf(BizException.class) + .hasFieldOrPropertyWithValue("code", 40020); + } + + @Test + void usesAuthenticatedUserNoAsCreatedBy() { + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken("ALICE", null, Collections.emptyList())); + CreateModuleDTO dto = baseDto(); + + service.create(dto); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Module.class); + verify(moduleMapper).insert(captor.capture()); + assertThat(captor.getValue().getSCreatedBy()).isEqualTo("ALICE"); + } + private CreateModuleDTO baseDto() { CreateModuleDTO dto = new CreateModuleDTO(); dto.setSDisplayType("手机端");