Commit 8f457010d51da8da60b16453920f5e410bcb8df8

Authored by zichun
1 parent c4b2e2dd

feat(mod): module update dto + service happy path REQ-MOD-002

backend/src/main/java/com/xly/erp/module/mod/dto/UpdateModuleDTO.java 0 → 100644
  1 +package com.xly.erp.module.mod.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonProperty;
  4 +import jakarta.validation.constraints.NotBlank;
  5 +import jakarta.validation.constraints.Size;
  6 +
  7 +public class UpdateModuleDTO {
  8 +
  9 + @JsonProperty("sDisplayType")
  10 + @NotBlank
  11 + private String sDisplayType;
  12 +
  13 + @JsonProperty("sModuleType")
  14 + @NotBlank
  15 + @Size(max = 50)
  16 + private String sModuleType;
  17 +
  18 + @JsonProperty("sManageDeptEn")
  19 + @NotBlank
  20 + @Size(max = 50)
  21 + private String sManageDeptEn;
  22 +
  23 + @JsonProperty("bShowPermission")
  24 + private Boolean bShowPermission;
  25 +
  26 + @JsonProperty("sModuleNameZh")
  27 + @NotBlank
  28 + @Size(max = 100)
  29 + private String sModuleNameZh;
  30 +
  31 + @JsonProperty("iParentId")
  32 + private Integer iParentId;
  33 +
  34 + @JsonProperty("iSortOrder")
  35 + private Integer iSortOrder;
  36 +
  37 + public String getSDisplayType() { return sDisplayType; }
  38 + public void setSDisplayType(String sDisplayType) { this.sDisplayType = sDisplayType; }
  39 + public String getSModuleType() { return sModuleType; }
  40 + public void setSModuleType(String sModuleType) { this.sModuleType = sModuleType; }
  41 + public String getSManageDeptEn() { return sManageDeptEn; }
  42 + public void setSManageDeptEn(String sManageDeptEn) { this.sManageDeptEn = sManageDeptEn; }
  43 + public Boolean getBShowPermission() { return bShowPermission; }
  44 + public void setBShowPermission(Boolean bShowPermission) { this.bShowPermission = bShowPermission; }
  45 + public String getSModuleNameZh() { return sModuleNameZh; }
  46 + public void setSModuleNameZh(String sModuleNameZh) { this.sModuleNameZh = sModuleNameZh; }
  47 + public Integer getIParentId() { return iParentId; }
  48 + public void setIParentId(Integer iParentId) { this.iParentId = iParentId; }
  49 + public Integer getISortOrder() { return iSortOrder; }
  50 + public void setISortOrder(Integer iSortOrder) { this.iSortOrder = iSortOrder; }
  51 +}
backend/src/main/java/com/xly/erp/module/mod/service/ModuleService.java
1 package com.xly.erp.module.mod.service; 1 package com.xly.erp.module.mod.service;
2 2
3 import com.xly.erp.module.mod.dto.CreateModuleDTO; 3 import com.xly.erp.module.mod.dto.CreateModuleDTO;
  4 +import com.xly.erp.module.mod.dto.UpdateModuleDTO;
4 5
5 public interface ModuleService { 6 public interface ModuleService {
6 Integer create(CreateModuleDTO dto); 7 Integer create(CreateModuleDTO dto);
  8 +
  9 + Integer update(Integer id, UpdateModuleDTO dto);
7 } 10 }
backend/src/main/java/com/xly/erp/module/mod/service/impl/ModuleServiceImpl.java
@@ -5,6 +5,7 @@ import com.xly.erp.common.config.TenantProperties; @@ -5,6 +5,7 @@ import com.xly.erp.common.config.TenantProperties;
5 import com.xly.erp.common.exception.BizException; 5 import com.xly.erp.common.exception.BizException;
6 import com.xly.erp.common.security.SecurityContextHelper; 6 import com.xly.erp.common.security.SecurityContextHelper;
7 import com.xly.erp.module.mod.dto.CreateModuleDTO; 7 import com.xly.erp.module.mod.dto.CreateModuleDTO;
  8 +import com.xly.erp.module.mod.dto.UpdateModuleDTO;
8 import com.xly.erp.module.mod.entity.Module; 9 import com.xly.erp.module.mod.entity.Module;
9 import com.xly.erp.module.mod.mapper.ModuleMapper; 10 import com.xly.erp.module.mod.mapper.ModuleMapper;
10 import com.xly.erp.module.mod.service.ModuleService; 11 import com.xly.erp.module.mod.service.ModuleService;
@@ -65,4 +66,28 @@ public class ModuleServiceImpl implements ModuleService { @@ -65,4 +66,28 @@ public class ModuleServiceImpl implements ModuleService {
65 } 66 }
66 return m.getIIncrement(); 67 return m.getIIncrement();
67 } 68 }
  69 +
  70 + @Override
  71 + public Integer update(Integer id, UpdateModuleDTO dto) {
  72 + Module original = moduleMapper.selectById(id);
  73 + if (original == null || Boolean.TRUE.equals(original.getBDeleted())) {
  74 + throw new BizException(40400, "模块不存在或已删除");
  75 + }
  76 + if (!DISPLAY_TYPES.contains(dto.getSDisplayType())) {
  77 + throw new BizException(40010, "显示类型枚举不合法");
  78 + }
  79 +
  80 + Module entity = new Module();
  81 + entity.setIIncrement(id);
  82 + entity.setSDisplayType(dto.getSDisplayType());
  83 + entity.setSModuleType(dto.getSModuleType());
  84 + entity.setSManageDeptEn(dto.getSManageDeptEn());
  85 + entity.setBShowPermission(dto.getBShowPermission() != null ? dto.getBShowPermission() : false);
  86 + entity.setSModuleNameZh(dto.getSModuleNameZh());
  87 + entity.setIParentId(dto.getIParentId());
  88 + entity.setISortOrder(dto.getISortOrder() != null ? dto.getISortOrder() : 0);
  89 +
  90 + moduleMapper.updateById(entity);
  91 + return id;
  92 + }
68 } 93 }
backend/src/test/java/com/xly/erp/module/mod/service/ModuleServiceImplTest.java
@@ -4,6 +4,7 @@ import com.xly.erp.common.config.StubSecurityProperties; @@ -4,6 +4,7 @@ import com.xly.erp.common.config.StubSecurityProperties;
4 import com.xly.erp.common.config.TenantProperties; 4 import com.xly.erp.common.config.TenantProperties;
5 import com.xly.erp.common.exception.BizException; 5 import com.xly.erp.common.exception.BizException;
6 import com.xly.erp.module.mod.dto.CreateModuleDTO; 6 import com.xly.erp.module.mod.dto.CreateModuleDTO;
  7 +import com.xly.erp.module.mod.dto.UpdateModuleDTO;
7 import com.xly.erp.module.mod.entity.Module; 8 import com.xly.erp.module.mod.entity.Module;
8 import com.xly.erp.module.mod.mapper.ModuleMapper; 9 import com.xly.erp.module.mod.mapper.ModuleMapper;
9 import com.xly.erp.module.mod.service.impl.ModuleServiceImpl; 10 import com.xly.erp.module.mod.service.impl.ModuleServiceImpl;
@@ -132,6 +133,76 @@ class ModuleServiceImplTest { @@ -132,6 +133,76 @@ class ModuleServiceImplTest {
132 assertThat(captor.getValue().getSCreatedBy()).isEqualTo("ALICE"); 133 assertThat(captor.getValue().getSCreatedBy()).isEqualTo("ALICE");
133 } 134 }
134 135
  136 + @Test
  137 + void updateWithValidDto_invokesUpdateById_withEditableFieldsOnly() {
  138 + Module original = stubExistingModule(10);
  139 + when(moduleMapper.selectById(10)).thenReturn(original);
  140 + when(moduleMapper.updateById(any(Module.class))).thenReturn(1);
  141 +
  142 + UpdateModuleDTO dto = baseUpdateDto();
  143 + dto.setSModuleNameZh("新名");
  144 +
  145 + Integer result = service.update(10, dto);
  146 + assertThat(result).isEqualTo(10);
  147 +
  148 + ArgumentCaptor<Module> captor = ArgumentCaptor.forClass(Module.class);
  149 + verify(moduleMapper).updateById(captor.capture());
  150 + Module passed = captor.getValue();
  151 + assertThat(passed.getIIncrement()).isEqualTo(10);
  152 + assertThat(passed.getSModuleNameZh()).isEqualTo("新名");
  153 + assertThat(passed.getSDisplayType()).isEqualTo("手机端");
  154 + assertThat(passed.getSProcedureName()).isNull();
  155 + assertThat(passed.getSCreatedBy()).isNull();
  156 + assertThat(passed.getTCreateDate()).isNull();
  157 + assertThat(passed.getSBrandsId()).isNull();
  158 + assertThat(passed.getSSubsidiaryId()).isNull();
  159 + assertThat(passed.getBDeleted()).isNull();
  160 + }
  161 +
  162 + @Test
  163 + void updateWithTargetNotFound_throws40400() {
  164 + when(moduleMapper.selectById(99)).thenReturn(null);
  165 + UpdateModuleDTO dto = baseUpdateDto();
  166 +
  167 + assertThatThrownBy(() -> service.update(99, dto))
  168 + .isInstanceOf(BizException.class)
  169 + .hasFieldOrPropertyWithValue("code", 40400);
  170 + verify(moduleMapper, never()).updateById(any(Module.class));
  171 + }
  172 +
  173 + @Test
  174 + void updateWithBShowPermissionNull_setsFalseInEntity() {
  175 + when(moduleMapper.selectById(10)).thenReturn(stubExistingModule(10));
  176 + when(moduleMapper.updateById(any(Module.class))).thenReturn(1);
  177 + UpdateModuleDTO dto = baseUpdateDto();
  178 + dto.setBShowPermission(null);
  179 +
  180 + service.update(10, dto);
  181 +
  182 + ArgumentCaptor<Module> captor = ArgumentCaptor.forClass(Module.class);
  183 + verify(moduleMapper).updateById(captor.capture());
  184 + assertThat(captor.getValue().getBShowPermission()).isFalse();
  185 + }
  186 +
  187 + private UpdateModuleDTO baseUpdateDto() {
  188 + UpdateModuleDTO dto = new UpdateModuleDTO();
  189 + dto.setSDisplayType("手机端");
  190 + dto.setSModuleType("业务模块");
  191 + dto.setSManageDeptEn("IT");
  192 + dto.setSModuleNameZh("更新后");
  193 + dto.setBShowPermission(false);
  194 + return dto;
  195 + }
  196 +
  197 + private Module stubExistingModule(Integer id) {
  198 + Module m = new Module();
  199 + m.setIIncrement(id);
  200 + m.setSProcedureName("sp_test_existing");
  201 + m.setSCreatedBy("ORIG_USER");
  202 + m.setBDeleted(false);
  203 + return m;
  204 + }
  205 +
135 private CreateModuleDTO baseDto() { 206 private CreateModuleDTO baseDto() {
136 CreateModuleDTO dto = new CreateModuleDTO(); 207 CreateModuleDTO dto = new CreateModuleDTO();
137 dto.setSDisplayType("手机端"); 208 dto.setSDisplayType("手机端");