Commit 4080ca5e344aefa7400f1e3914cccc9cfaef4d15

Authored by YunaiV
1 parent 0f77a131

fix(mes): 修复工艺路线模块 TODO,规范代码风格

- DO 类补充 {@link} 外链注解(RouteProcess/Product/ProductBom)
- RouteService 提取 updateRouteStatus 独立接口,启用/禁用逻辑分离
- RouteService 将 mapper 直接调用改为 service 调用,解耦跨表操作
- RouteProcessService 拆分校验方法(sort/process/keyProcess 唯一性)
- RouteProductService 复用 validateRouteProductExists,mapper 改 service
- RouteProductBomService 新增按 routeId/productId 级联删除方法
- Controller 层 buildRespVOList 统一使用 CollUtil/MapUtils/convertSet 模式
- RouteController 新增 /update-status 端点
- 统一使用 ObjUtil.notEqual / CollUtil.isEmpty / BooleanUtil.isFalse
Showing 16 changed files with 242 additions and 176 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteController.java
... ... @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO;
14 14 import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService;
15 15 import io.swagger.v3.oas.annotations.Operation;
16 16 import io.swagger.v3.oas.annotations.Parameter;
  17 +import io.swagger.v3.oas.annotations.Parameters;
17 18 import io.swagger.v3.oas.annotations.tags.Tag;
18 19 import jakarta.annotation.Resource;
19 20 import jakarta.servlet.http.HttpServletResponse;
... ... @@ -53,6 +54,19 @@ public class MesProRouteController {
53 54 return success(true);
54 55 }
55 56  
  57 + @PutMapping("/update-status")
  58 + @Operation(summary = "更新工艺路线状态")
  59 + @Parameters({
  60 + @Parameter(name = "id", description = "编号", required = true),
  61 + @Parameter(name = "status", description = "状态", required = true)
  62 + })
  63 + @PreAuthorize("@ss.hasPermission('mes:pro-route:update')")
  64 + public CommonResult<Boolean> updateRouteStatus(@RequestParam("id") Long id,
  65 + @RequestParam("status") Integer status) {
  66 + routeService.updateRouteStatus(id, status);
  67 + return success(true);
  68 + }
  69 +
56 70 @DeleteMapping("/delete")
57 71 @Operation(summary = "删除工艺路线")
58 72 @Parameter(name = "id", description = "编号", required = true)
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProcessController.java
1 1 package cn.iocoder.yudao.module.mes.controller.admin.pro.route;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
4 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 7 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessRespVO;
6 8 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessSaveReqVO;
... ... @@ -18,11 +20,14 @@ import org.springframework.validation.annotation.Validated;
18 20 import org.springframework.web.bind.annotation.*;
19 21  
20 22 import java.util.ArrayList;
  23 +import java.util.Collections;
21 24 import java.util.List;
22 25 import java.util.Map;
  26 +import java.util.Set;
23 27  
24 28 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
25 29 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
26 31  
27 32 @Tag(name = "管理后台 - MES 工艺路线工序")
28 33 @RestController
... ... @@ -81,42 +86,23 @@ public class MesProRouteProcessController {
81 86 // ==================== 拼接 VO ====================
82 87  
83 88 private List<MesProRouteProcessRespVO> buildRouteProcessRespVOList(List<MesProRouteProcessDO> list) {
84   - // TODO @AI:collutil 去判断空;
85   - if (list.isEmpty()) {
86   - return List.of();
  89 + if (CollUtil.isEmpty(list)) {
  90 + return Collections.emptyList();
87 91 }
88   - // 批量查询工序信息
89   - // TODO @AI:我记得有 CollUtil 可以搞多个的;
90   - List<Long> processIds = new ArrayList<>();
91   - for (MesProRouteProcessDO item : list) {
92   - processIds.add(item.getProcessId());
93   - if (item.getNextProcessId() != null) {
94   - processIds.add(item.getNextProcessId());
95   - }
96   - }
97   - // TODO @AI:processService.getProcessMap 直接返回 Map 就好了;
98   - List<MesProProcessDO> processList = processService.getProcessList(processIds);
99   - Map<Long, MesProProcessDO> processMap = convertMap(processList, MesProProcessDO::getId);
100   - // 拼装
101   - List<MesProRouteProcessRespVO> result = BeanUtils.toBean(list, MesProRouteProcessRespVO.class);
102   - for (MesProRouteProcessRespVO vo : result) {
103   - // TODO @AI:MapUtil findMap
104   - MesProProcessDO process = processMap.get(vo.getProcessId());
105   - if (process != null) {
106   - vo.setProcessCode(process.getCode()).setProcessName(process.getName());
107   - }
108   - // TODO @AI:MapUtil findMap
109   - if (vo.getNextProcessId() != null) {
110   - MesProProcessDO nextProcess = processMap.get(vo.getNextProcessId());
111   - if (nextProcess != null) {
112   - vo.setNextProcessName(nextProcess.getName());
113   - }
114   - }
115   - }
116   - return result;
  92 + // 1. 批量获取关联数据
  93 + Set<Long> processIds = convertSet(list, MesProRouteProcessDO::getProcessId);
  94 + list.forEach(item -> { if (item.getNextProcessId() != null) processIds.add(item.getNextProcessId()); });
  95 + Map<Long, MesProProcessDO> processMap = convertMap(
  96 + processService.getProcessList(new ArrayList<>(processIds)), MesProProcessDO::getId);
  97 + // 2. 拼接 VO
  98 + return BeanUtils.toBean(list, MesProRouteProcessRespVO.class, vo -> {
  99 + MapUtils.findAndThen(processMap, vo.getProcessId(),
  100 + process -> vo.setProcessCode(process.getCode()).setProcessName(process.getName()));
  101 + MapUtils.findAndThen(processMap, vo.getNextProcessId(),
  102 + nextProcess -> vo.setNextProcessName(nextProcess.getName()));
  103 + });
117 104 }
118 105  
119   - // TODO @AI:需要的地方,直接调用 buildRouteProcessRespVOList;
120 106 private MesProRouteProcessRespVO buildRouteProcessRespVO(MesProRouteProcessDO routeProcess) {
121 107 if (routeProcess == null) {
122 108 return null;
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductBomController.java
1 1 package cn.iocoder.yudao.module.mes.controller.admin.pro.route;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
4 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 7 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomRespVO;
6 8 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO;
... ... @@ -20,11 +22,12 @@ import org.springframework.security.access.prepost.PreAuthorize;
20 22 import org.springframework.validation.annotation.Validated;
21 23 import org.springframework.web.bind.annotation.*;
22 24  
  25 +import java.util.Collections;
23 26 import java.util.List;
24 27 import java.util.Map;
25 28  
26 29 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
27   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  30 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
28 31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
29 32  
30 33 @Tag(name = "管理后台 - MES 工艺路线产品 BOM")
... ... @@ -93,35 +96,24 @@ public class MesProRouteProductBomController {
93 96  
94 97 // ==================== 拼接 VO ====================
95 98  
96   - // TODO @AI:参考 /Users/yunai/Java/yudao-all-in-one/ruoyi-vue-pro/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProcessController.java 的 todo;
97   -
98 99 private List<MesProRouteProductBomRespVO> buildRouteProductBomRespVOList(List<MesProRouteProductBomDO> list) {
99   - if (list.isEmpty()) {
100   - return List.of();
101   - }
102   - // 批量查询物料信息
103   - List<Long> itemIds = convertList(list, MesProRouteProductBomDO::getItemId);
104   - List<MesMdItemDO> itemList = itemService.getItemList(itemIds);
105   - Map<Long, MesMdItemDO> itemMap = convertMap(itemList, MesMdItemDO::getId);
106   - // 批量查询单位信息
107   - List<Long> unitMeasureIds = convertList(itemList, MesMdItemDO::getUnitMeasureId);
108   - Map<Long, MesMdUnitMeasureDO> unitMap = convertMap(
109   - unitMeasureService.getUnitMeasureList(unitMeasureIds), MesMdUnitMeasureDO::getId);
110   - // 拼装
111   - List<MesProRouteProductBomRespVO> result = BeanUtils.toBean(list, MesProRouteProductBomRespVO.class);
112   - for (MesProRouteProductBomRespVO vo : result) {
113   - MesMdItemDO item = itemMap.get(vo.getItemId());
114   - if (item != null) {
115   - vo.setItemCode(item.getCode());
116   - vo.setItemName(item.getName());
117   - vo.setSpecification(item.getSpecification());
118   - MesMdUnitMeasureDO unit = unitMap.get(item.getUnitMeasureId());
119   - if (unit != null) {
120   - vo.setUnitName(unit.getName());
121   - }
122   - }
  100 + if (CollUtil.isEmpty(list)) {
  101 + return Collections.emptyList();
123 102 }
124   - return result;
  103 + // 1. 批量获取关联数据
  104 + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
  105 + convertSet(list, MesProRouteProductBomDO::getItemId));
  106 + Map<Long, MesMdUnitMeasureDO> unitMap = unitMeasureService.getUnitMeasureMap(
  107 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
  108 + // 2. 拼接 VO
  109 + return BeanUtils.toBean(list, MesProRouteProductBomRespVO.class, vo -> {
  110 + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
  111 + vo.setItemCode(item.getCode()).setItemName(item.getName())
  112 + .setSpecification(item.getSpecification());
  113 + MapUtils.findAndThen(unitMap, item.getUnitMeasureId(),
  114 + unit -> vo.setUnitName(unit.getName()));
  115 + });
  116 + });
125 117 }
126 118  
127 119 private MesProRouteProductBomRespVO buildRouteProductBomRespVO(MesProRouteProductBomDO routeProductBom) {
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProductController.java
1 1 package cn.iocoder.yudao.module.mes.controller.admin.pro.route;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
4 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 7 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductRespVO;
6 8 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO;
... ... @@ -19,11 +21,12 @@ import org.springframework.security.access.prepost.PreAuthorize;
19 21 import org.springframework.validation.annotation.Validated;
20 22 import org.springframework.web.bind.annotation.*;
21 23  
  24 +import java.util.Collections;
22 25 import java.util.List;
23 26 import java.util.Map;
24 27  
25 28 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
26   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
27 30 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
28 31  
29 32 @Tag(name = "管理后台 - MES 工艺路线产品")
... ... @@ -84,35 +87,25 @@ public class MesProRouteProductController {
84 87 }
85 88  
86 89 // ==================== 拼接 VO ====================
87   - // TODO @AI:参考 /Users/yunai/Java/yudao-all-in-one/ruoyi-vue-pro/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/MesProRouteProcessController.java 的 todo;
88 90  
89 91 private List<MesProRouteProductRespVO> buildRouteProductRespVOList(List<MesProRouteProductDO> list) {
90   - if (list.isEmpty()) {
91   - return List.of();
  92 + if (CollUtil.isEmpty(list)) {
  93 + return Collections.emptyList();
92 94 }
93   - // 批量查询物料信息
94   - List<Long> itemIds = convertList(list, MesProRouteProductDO::getItemId);
95   - List<MesMdItemDO> itemList = itemService.getItemList(itemIds);
96   - Map<Long, MesMdItemDO> itemMap = convertMap(itemList, MesMdItemDO::getId);
97   - // 批量查询单位信息
98   - List<Long> unitMeasureIds = convertList(itemList, MesMdItemDO::getUnitMeasureId);
99   - Map<Long, MesMdUnitMeasureDO> unitMap = convertMap(
100   - unitMeasureService.getUnitMeasureList(unitMeasureIds), MesMdUnitMeasureDO::getId);
101   - // 拼装
102   - List<MesProRouteProductRespVO> result = BeanUtils.toBean(list, MesProRouteProductRespVO.class);
103   - for (MesProRouteProductRespVO vo : result) {
104   - MesMdItemDO item = itemMap.get(vo.getItemId());
105   - if (item != null) {
106   - vo.setItemCode(item.getCode());
107   - vo.setItemName(item.getName());
108   - vo.setSpecification(item.getSpecification());
109   - MesMdUnitMeasureDO unit = unitMap.get(item.getUnitMeasureId());
110   - if (unit != null) {
111   - vo.setUnitName(unit.getName());
112   - }
113   - }
114   - }
115   - return result;
  95 + // 1. 批量获取关联数据
  96 + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
  97 + convertSet(list, MesProRouteProductDO::getItemId));
  98 + Map<Long, MesMdUnitMeasureDO> unitMap = unitMeasureService.getUnitMeasureMap(
  99 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
  100 + // 2. 拼接 VO
  101 + return BeanUtils.toBean(list, MesProRouteProductRespVO.class, vo -> {
  102 + MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
  103 + vo.setItemCode(item.getCode()).setItemName(item.getName())
  104 + .setSpecification(item.getSpecification());
  105 + MapUtils.findAndThen(unitMap, item.getUnitMeasureId(),
  106 + unit -> vo.setUnitName(unit.getName()));
  107 + });
  108 + });
116 109 }
117 110  
118 111 private MesProRouteProductRespVO buildRouteProductRespVO(MesProRouteProductDO routeProduct) {
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProcessDO.java
... ... @@ -26,23 +26,26 @@ public class MesProRouteProcessDO extends BaseDO {
26 26 */
27 27 @TableId
28 28 private Long id;
29   - // TODO @AI:外链 @ 加下,参考别的模块
30 29 /**
31 30 * 工艺路线编号
  31 + *
  32 + * 关联 {@link MesProRouteDO#getId()}
32 33 */
33 34 private Long routeId;
34   - // TODO @AI:外链 @ 加下,参考别的模块
35 35 /**
36 36 * 工序编号
  37 + *
  38 + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.MesProProcessDO#getId()}
37 39 */
38 40 private Long processId;
39 41 /**
40 42 * 序号
41 43 */
42 44 private Integer sort;
43   - // TODO @AI:外链 @ 加下,参考别的模块
44 45 /**
45 46 * 下一道工序编号
  47 + *
  48 + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.MesProProcessDO#getId()}
46 49 */
47 50 private Long nextProcessId;
48 51 /**
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductBomDO.java
... ... @@ -28,24 +28,28 @@ public class MesProRouteProductBomDO extends BaseDO {
28 28 */
29 29 @TableId
30 30 private Long id;
31   - // TODO @AI:外链 @ 加下,参考别的模块
32 31 /**
33 32 * 工艺路线编号
  33 + *
  34 + * 关联 {@link MesProRouteDO#getId()}
34 35 */
35 36 private Long routeId;
36   - // TODO @AI:外链 @ 加下,参考别的模块
37 37 /**
38 38 * 工序编号
  39 + *
  40 + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.pro.MesProProcessDO#getId()}
39 41 */
40 42 private Long processId;
41   - // TODO @AI:外链 @ 加下,参考别的模块
42 43 /**
43 44 * 产品物料编号
  45 + *
  46 + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO#getId()}
44 47 */
45 48 private Long productId;
46   - // TODO @AI:外链 @ 加下,参考别的模块
47 49 /**
48 50 * BOM 物料编号
  51 + *
  52 + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO#getId()}
49 53 */
50 54 private Long itemId;
51 55 /**
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/route/MesProRouteProductDO.java
... ... @@ -28,14 +28,16 @@ public class MesProRouteProductDO extends BaseDO {
28 28 */
29 29 @TableId
30 30 private Long id;
31   - // TODO @AI:外链 @ 加下,参考别的模块
32 31 /**
33 32 * 工艺路线编号
  33 + *
  34 + * 关联 {@link MesProRouteDO#getId()}
34 35 */
35 36 private Long routeId;
36   - // TODO @AI:外链 @ 加下,参考别的模块
37 37 /**
38 38 * 产品物料编号
  39 + *
  40 + * 关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO#getId()}
39 41 */
40 42 private Long itemId;
41 43 /**
... ... @@ -48,8 +50,10 @@ public class MesProRouteProductDO extends BaseDO {
48 50 private BigDecimal productionTime;
49 51 /**
50 52 * 时间单位
  53 + *
  54 + * 字典类型 mes_time_unit_type
51 55 */
52   - // TODO @AI:外链 @ 加下,字典 + 枚举类;
  56 + // TODO @AI:外链 @ 加下,字典 + 枚举类;(需要枚举出来。在 dictconstants 里)
53 57 private String timeUnitType;
54 58 /**
55 59 * 备注
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessService.java
... ... @@ -38,4 +38,11 @@ public interface MesProRouteProcessService {
38 38 */
39 39 List<MesProRouteProcessDO> getRouteProcessListByRouteId(Long routeId);
40 40  
  41 + /**
  42 + * 按工艺路线删除工序(级联删除使用)
  43 + *
  44 + * @param routeId 工艺路线编号
  45 + */
  46 + void deleteRouteProcessByRouteId(Long routeId);
  47 +
41 48 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.pro.route;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 5 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.process.MesProRouteProcessSaveReqVO;
5   -import cn.iocoder.yudao.module.mes.dal.dataobject.pro.MesProProcessDO;
6 6 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
7 7 import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteProcessMapper;
8 8 import cn.iocoder.yudao.module.mes.service.pro.MesProProcessService;
... ... @@ -18,7 +18,6 @@ import java.util.List;
18 18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 19 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
20 20  
21   -// TODO @AI:参考别的模块,需要校验下相关的工艺路线、工序是否存在;(别的 route 也是);最好对方 service 提供校验方法;
22 21 /**
23 22 * MES 工艺路线工序 Service 实现类
24 23 *
... ... @@ -31,16 +30,23 @@ public class MesProRouteProcessServiceImpl implements MesProRouteProcessService
31 30 @Resource
32 31 private MesProRouteProcessMapper routeProcessMapper;
33 32  
34   - // TODO @AI:貌似没用到?是不是应该要用下哈?
35 33 @Resource
36 34 @Lazy
37 35 private MesProProcessService processService;
38 36  
  37 + @Resource
  38 + @Lazy
  39 + private MesProRouteService routeService;
  40 +
39 41 @Override
40 42 @Transactional(rollbackFor = Exception.class)
41 43 public Long createRouteProcess(MesProRouteProcessSaveReqVO createReqVO) {
42   - // 1. 校验
43   - validateRouteProcessCreate(createReqVO);
  44 + // 1.1 校验工艺路线、工序存在
  45 + validateRouteAndProcessExists(createReqVO.getRouteId(), createReqVO.getProcessId());
  46 + // 1.2 校验唯一性
  47 + validateSortUnique(null, createReqVO.getRouteId(), createReqVO.getSort());
  48 + validateProcessUnique(null, createReqVO.getRouteId(), createReqVO.getProcessId());
  49 + validateKeyProcessUnique(null, createReqVO.getRouteId(), createReqVO.getKeyFlag());
44 50  
45 51 // 2. 插入
46 52 MesProRouteProcessDO routeProcess = BeanUtils.toBean(createReqVO, MesProRouteProcessDO.class);
... ... @@ -56,8 +62,12 @@ public class MesProRouteProcessServiceImpl implements MesProRouteProcessService
56 62 public void updateRouteProcess(MesProRouteProcessSaveReqVO updateReqVO) {
57 63 // 1.1 校验存在
58 64 validateRouteProcessExists(updateReqVO.getId());
59   - // 1.2 校验唯一性
60   - validateRouteProcessUpdate(updateReqVO);
  65 + // 1.2 校验工艺路线、工序存在
  66 + validateRouteAndProcessExists(updateReqVO.getRouteId(), updateReqVO.getProcessId());
  67 + // 1.3 校验唯一性
  68 + validateSortUnique(updateReqVO.getId(), updateReqVO.getRouteId(), updateReqVO.getSort());
  69 + validateProcessUnique(updateReqVO.getId(), updateReqVO.getRouteId(), updateReqVO.getProcessId());
  70 + validateKeyProcessUnique(updateReqVO.getId(), updateReqVO.getRouteId(), updateReqVO.getKeyFlag());
61 71  
62 72 // 2. 更新
63 73 MesProRouteProcessDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProcessDO.class);
... ... @@ -88,8 +98,7 @@ public class MesProRouteProcessServiceImpl implements MesProRouteProcessService
88 98 */
89 99 private void rebuildProcessChain(Long routeId) {
90 100 List<MesProRouteProcessDO> list = routeProcessMapper.selectListByRouteId(routeId);
91   - // TODO @AI:CollUtil isEmpty;
92   - if (list.isEmpty()) {
  101 + if (CollUtil.isEmpty(list)) {
93 102 return;
94 103 }
95 104 // 按 sort 排序
... ... @@ -111,45 +120,36 @@ public class MesProRouteProcessServiceImpl implements MesProRouteProcessService
111 120 }
112 121 }
113 122  
114   - // TODO @AI:参考别的模块,拆分为多个模块
115   - private void validateRouteProcessCreate(MesProRouteProcessSaveReqVO reqVO) {
116   - // 序号唯一
117   - MesProRouteProcessDO existing = routeProcessMapper.selectByRouteIdAndSort(reqVO.getRouteId(), reqVO.getSort());
118   - if (existing != null) {
119   - throw exception(PRO_ROUTE_PROCESS_SORT_DUPLICATE);
120   - }
121   - // 工序不重复
122   - existing = routeProcessMapper.selectByRouteIdAndProcessId(reqVO.getRouteId(), reqVO.getProcessId());
123   - if (existing != null) {
124   - throw exception(PRO_ROUTE_PROCESS_DUPLICATE);
  123 + private void validateRouteAndProcessExists(Long routeId, Long processId) {
  124 + if (routeService.getRoute(routeId) == null) {
  125 + throw exception(PRO_ROUTE_NOT_EXISTS);
125 126 }
126   - // 关键工序唯一
127   - if (Boolean.TRUE.equals(reqVO.getKeyFlag())) {
128   - existing = routeProcessMapper.selectKeyProcessByRouteId(reqVO.getRouteId());
129   - if (existing != null) {
130   - throw exception(PRO_ROUTE_PROCESS_KEY_DUPLICATE);
131   - }
  127 + if (processService.getProcess(processId) == null) {
  128 + throw exception(PRO_ROUTE_PROCESS_NOT_EXISTS);
132 129 }
133 130 }
134 131  
135   - // TODO @AI:参考别的模块,拆分为多个模块
136   - private void validateRouteProcessUpdate(MesProRouteProcessSaveReqVO reqVO) {
137   - // 序号唯一(排除自身)
138   - MesProRouteProcessDO existing = routeProcessMapper.selectByRouteIdAndSort(reqVO.getRouteId(), reqVO.getSort());
139   - if (existing != null && !existing.getId().equals(reqVO.getId())) {
  132 + private void validateSortUnique(Long id, Long routeId, Integer sort) {
  133 + MesProRouteProcessDO existing = routeProcessMapper.selectByRouteIdAndSort(routeId, sort);
  134 + if (existing != null && !existing.getId().equals(id)) {
140 135 throw exception(PRO_ROUTE_PROCESS_SORT_DUPLICATE);
141 136 }
142   - // 工序不重复(排除自身)
143   - existing = routeProcessMapper.selectByRouteIdAndProcessId(reqVO.getRouteId(), reqVO.getProcessId());
144   - if (existing != null && !existing.getId().equals(reqVO.getId())) {
  137 + }
  138 +
  139 + private void validateProcessUnique(Long id, Long routeId, Long processId) {
  140 + MesProRouteProcessDO existing = routeProcessMapper.selectByRouteIdAndProcessId(routeId, processId);
  141 + if (existing != null && !existing.getId().equals(id)) {
145 142 throw exception(PRO_ROUTE_PROCESS_DUPLICATE);
146 143 }
147   - // 关键工序唯一(排除自身)
148   - if (Boolean.TRUE.equals(reqVO.getKeyFlag())) {
149   - existing = routeProcessMapper.selectKeyProcessByRouteId(reqVO.getRouteId());
150   - if (existing != null && !existing.getId().equals(reqVO.getId())) {
151   - throw exception(PRO_ROUTE_PROCESS_KEY_DUPLICATE);
152   - }
  144 + }
  145 +
  146 + private void validateKeyProcessUnique(Long id, Long routeId, Boolean keyFlag) {
  147 + if (!Boolean.TRUE.equals(keyFlag)) {
  148 + return;
  149 + }
  150 + MesProRouteProcessDO existing = routeProcessMapper.selectKeyProcessByRouteId(routeId);
  151 + if (existing != null && !existing.getId().equals(id)) {
  152 + throw exception(PRO_ROUTE_PROCESS_KEY_DUPLICATE);
153 153 }
154 154 }
155 155  
... ... @@ -163,4 +163,9 @@ public class MesProRouteProcessServiceImpl implements MesProRouteProcessService
163 163 return routeProcessMapper.selectListByRouteId(routeId);
164 164 }
165 165  
  166 + @Override
  167 + public void deleteRouteProcessByRouteId(Long routeId) {
  168 + routeProcessMapper.deleteByRouteId(routeId);
  169 + }
  170 +
166 171 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomService.java
... ... @@ -38,4 +38,19 @@ public interface MesProRouteProductBomService {
38 38 */
39 39 List<MesProRouteProductBomDO> getRouteProductBomList(Long routeId, Long processId, Long productId);
40 40  
  41 + /**
  42 + * 按工艺路线删除产品 BOM(级联删除使用)
  43 + *
  44 + * @param routeId 工艺路线编号
  45 + */
  46 + void deleteRouteProductBomByRouteId(Long routeId);
  47 +
  48 + /**
  49 + * 按工艺路线和产品删除 BOM(产品删除时级联使用)
  50 + *
  51 + * @param routeId 工艺路线编号
  52 + * @param productId 产品物料编号
  53 + */
  54 + void deleteRouteProductBomByRouteIdAndProductId(Long routeId, Long productId);
  55 +
41 56 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.pro.route;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 5 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO;
5 6 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO;
... ... @@ -65,7 +66,7 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe
65 66 if (existing == null) {
66 67 return;
67 68 }
68   - if (id == null || !existing.getId().equals(id)) {
  69 + if (ObjUtil.notEqual(existing.getId(), id)) {
69 70 throw exception(PRO_ROUTE_PRODUCT_BOM_DUPLICATE);
70 71 }
71 72 }
... ... @@ -80,4 +81,14 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe
80 81 return routeProductBomMapper.selectList(routeId, processId, productId);
81 82 }
82 83  
  84 + @Override
  85 + public void deleteRouteProductBomByRouteId(Long routeId) {
  86 + routeProductBomMapper.deleteByRouteId(routeId);
  87 + }
  88 +
  89 + @Override
  90 + public void deleteRouteProductBomByRouteIdAndProductId(Long routeId, Long productId) {
  91 + routeProductBomMapper.deleteByRouteIdAndProductId(routeId, productId);
  92 + }
  93 +
83 94 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductService.java
... ... @@ -38,4 +38,11 @@ public interface MesProRouteProductService {
38 38 */
39 39 List<MesProRouteProductDO> getRouteProductListByRouteId(Long routeId);
40 40  
  41 + /**
  42 + * 按工艺路线删除产品(级联删除使用)
  43 + *
  44 + * @param routeId 工艺路线编号
  45 + */
  46 + void deleteRouteProductByRouteId(Long routeId);
  47 +
41 48 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.pro.route;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
4 5 import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO;
5 6 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
6   -import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteProductBomMapper;
7 7 import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteProductMapper;
8 8 import jakarta.annotation.Resource;
  9 +import org.springframework.context.annotation.Lazy;
9 10 import org.springframework.stereotype.Service;
10 11 import org.springframework.transaction.annotation.Transactional;
11 12 import org.springframework.validation.annotation.Validated;
... ... @@ -27,9 +28,9 @@ public class MesProRouteProductServiceImpl implements MesProRouteProductService
27 28 @Resource
28 29 private MesProRouteProductMapper routeProductMapper;
29 30  
30   - // TODO @AI:别人模块的操作,需要通过 service;
31 31 @Resource
32   - private MesProRouteProductBomMapper routeProductBomMapper;
  32 + @Lazy
  33 + private MesProRouteProductBomService routeProductBomService;
33 34  
34 35 @Override
35 36 public Long createRouteProduct(MesProRouteProductSaveReqVO createReqVO) {
... ... @@ -58,14 +59,11 @@ public class MesProRouteProductServiceImpl implements MesProRouteProductService
58 59 @Transactional(rollbackFor = Exception.class)
59 60 public void deleteRouteProduct(Long id) {
60 61 // 1. 校验存在
61   - // TODO @AI:复用 validateRouteProductExists 方法;
62 62 MesProRouteProductDO routeProduct = routeProductMapper.selectById(id);
63   - if (routeProduct == null) {
64   - throw exception(PRO_ROUTE_PRODUCT_NOT_EXISTS);
65   - }
  63 + validateRouteProductExists(routeProduct);
66 64  
67 65 // 2.1 级联删除关联的 BOM
68   - routeProductBomMapper.deleteByRouteIdAndProductId(routeProduct.getRouteId(), routeProduct.getItemId());
  66 + routeProductBomService.deleteRouteProductBomByRouteIdAndProductId(routeProduct.getRouteId(), routeProduct.getItemId());
69 67 // 2.2 删除产品关联
70 68 routeProductMapper.deleteById(id);
71 69 }
... ... @@ -76,13 +74,18 @@ public class MesProRouteProductServiceImpl implements MesProRouteProductService
76 74 }
77 75 }
78 76  
  77 + private void validateRouteProductExists(MesProRouteProductDO routeProduct) {
  78 + if (routeProduct == null) {
  79 + throw exception(PRO_ROUTE_PRODUCT_NOT_EXISTS);
  80 + }
  81 + }
  82 +
79 83 private void validateItemUnique(Long id, Long itemId) {
80 84 MesProRouteProductDO existing = routeProductMapper.selectByItemId(itemId);
81 85 if (existing == null) {
82 86 return;
83 87 }
84   - // TODO @AI:notEquals
85   - if (id == null || !existing.getId().equals(id)) {
  88 + if (ObjUtil.notEqual(existing.getId(), id)) {
86 89 throw exception(PRO_ROUTE_PRODUCT_ITEM_DUPLICATE);
87 90 }
88 91 }
... ... @@ -97,4 +100,9 @@ public class MesProRouteProductServiceImpl implements MesProRouteProductService
97 100 return routeProductMapper.selectListByRouteId(routeId);
98 101 }
99 102  
  103 + @Override
  104 + public void deleteRouteProductByRouteId(Long routeId) {
  105 + routeProductMapper.deleteByRouteId(routeId);
  106 + }
  107 +
100 108 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteService.java
... ... @@ -26,6 +26,14 @@ public interface MesProRouteService {
26 26 void updateRoute(@Valid MesProRouteSaveReqVO updateReqVO);
27 27  
28 28 /**
  29 + * 更新工艺路线状态(启用/禁用)
  30 + *
  31 + * @param id 编号
  32 + * @param status 状态
  33 + */
  34 + void updateRouteStatus(Long id, Integer status);
  35 +
  36 + /**
29 37 * 删除工艺路线
30 38 */
31 39 void deleteRoute(Long id);
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.pro.route;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.BooleanUtil;
  5 +import cn.hutool.core.util.ObjUtil;
3 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
... ... @@ -10,10 +13,8 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO
10 13 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO;
11 14 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO;
12 15 import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteMapper;
13   -import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteProcessMapper;
14   -import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteProductBomMapper;
15   -import cn.iocoder.yudao.module.mes.dal.mysql.pro.MesProRouteProductMapper;
16 16 import jakarta.annotation.Resource;
  17 +import org.springframework.context.annotation.Lazy;
17 18 import org.springframework.stereotype.Service;
18 19 import org.springframework.transaction.annotation.Transactional;
19 20 import org.springframework.validation.annotation.Validated;
... ... @@ -35,13 +36,15 @@ public class MesProRouteServiceImpl implements MesProRouteService {
35 36 @Resource
36 37 private MesProRouteMapper routeMapper;
37 38  
38   - // todo @AI:不要直接使用对方模块的 mapper,而是通过 service;
39 39 @Resource
40   - private MesProRouteProcessMapper routeProcessMapper;
  40 + @Lazy
  41 + private MesProRouteProcessService routeProcessService;
41 42 @Resource
42   - private MesProRouteProductMapper routeProductMapper;
  43 + @Lazy
  44 + private MesProRouteProductService routeProductService;
43 45 @Resource
44   - private MesProRouteProductBomMapper routeProductBomMapper;
  46 + @Lazy
  47 + private MesProRouteProductBomService routeProductBomService;
45 48  
46 49 @Override
47 50 public Long createRoute(MesProRouteSaveReqVO createReqVO) {
... ... @@ -59,11 +62,6 @@ public class MesProRouteServiceImpl implements MesProRouteService {
59 62 validateRouteExists(updateReqVO.getId());
60 63 // 1.2 校验编码唯一性
61 64 validateRouteCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
62   - // 1.3 启用时的校验
63   - // TODO @AI:开启禁用,独立接口;保持更新接口的独立;
64   - if (CommonStatusEnum.ENABLE.getStatus().equals(updateReqVO.getStatus())) {
65   - validateRouteEnable(updateReqVO.getId());
66   - }
67 65  
68 66 // 2. 更新
69 67 MesProRouteDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteDO.class);
... ... @@ -71,15 +69,28 @@ public class MesProRouteServiceImpl implements MesProRouteService {
71 69 }
72 70  
73 71 @Override
  72 + public void updateRouteStatus(Long id, Integer status) {
  73 + // 1.1 校验存在
  74 + validateRouteExists(id);
  75 + // 1.2 启用时的校验
  76 + if (CommonStatusEnum.ENABLE.getStatus().equals(status)) {
  77 + validateRouteEnable(id);
  78 + }
  79 +
  80 + // 2. 更新状态
  81 + routeMapper.updateById(new MesProRouteDO().setId(id).setStatus(status));
  82 + }
  83 +
  84 + @Override
74 85 @Transactional(rollbackFor = Exception.class)
75 86 public void deleteRoute(Long id) {
76 87 // 1. 校验存在
77 88 validateRouteExists(id);
78 89  
79 90 // 2.1 级联删除
80   - routeProcessMapper.deleteByRouteId(id);
81   - routeProductMapper.deleteByRouteId(id);
82   - routeProductBomMapper.deleteByRouteId(id);
  91 + routeProcessService.deleteRouteProcessByRouteId(id);
  92 + routeProductService.deleteRouteProductByRouteId(id);
  93 + routeProductBomService.deleteRouteProductBomByRouteId(id);
83 94 // 2.2 删除工艺路线
84 95 routeMapper.deleteById(id);
85 96 }
... ... @@ -95,8 +106,7 @@ public class MesProRouteServiceImpl implements MesProRouteService {
95 106 if (route == null) {
96 107 return;
97 108 }
98   - // TODO @AI:ObjUtil notequals;
99   - if (id == null || !route.getId().equals(id)) {
  109 + if (ObjUtil.notEqual(route.getId(), id)) {
100 110 throw exception(PRO_ROUTE_CODE_DUPLICATE);
101 111 }
102 112 }
... ... @@ -106,23 +116,21 @@ public class MesProRouteServiceImpl implements MesProRouteService {
106 116 */
107 117 private void validateRouteEnable(Long routeId) {
108 118 // 1. 必须有工序
109   - List<MesProRouteProcessDO> processList = routeProcessMapper.selectListByRouteId(routeId);
110   - if (processList.isEmpty()) {
  119 + List<MesProRouteProcessDO> processList = routeProcessService.getRouteProcessListByRouteId(routeId);
  120 + if (CollUtil.isEmpty(processList)) {
111 121 throw exception(PRO_ROUTE_ENABLE_NO_PROCESS);
112 122 }
113 123 // 2. 必须有关键工序
114 124 boolean hasKeyProcess = processList.stream().anyMatch(MesProRouteProcessDO::getKeyFlag);
115   - // TODO @AI:BooleanUtils.isFalue(hasKeyProcess)
116   - if (!hasKeyProcess) {
  125 + if (BooleanUtil.isFalse(hasKeyProcess)) {
117 126 throw exception(PRO_ROUTE_ENABLE_NO_KEY_PROCESS);
118 127 }
119 128 // 3. 所有产品必须配置了 BOM 消耗
120   - List<MesProRouteProductDO> productList = routeProductMapper.selectListByRouteId(routeId);
  129 + List<MesProRouteProductDO> productList = routeProductService.getRouteProductListByRouteId(routeId);
121 130 for (MesProRouteProductDO product : productList) {
122   - List<MesProRouteProductBomDO> bomList = routeProductBomMapper
123   - .selectListByRouteIdAndProductId(routeId, product.getItemId());
124   - // TODO @AI:CollUtil.isEmpty(bomList)
125   - if (bomList.isEmpty()) {
  131 + List<MesProRouteProductBomDO> bomList = routeProductBomService
  132 + .getRouteProductBomList(routeId, null, product.getItemId());
  133 + if (CollUtil.isEmpty(bomList)) {
126 134 throw exception(PRO_ROUTE_ENABLE_PRODUCT_NO_BOM, product.getItemId());
127 135 }
128 136 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/MesQcTemplateServiceImpl.java
... ... @@ -53,7 +53,8 @@ public class MesQcTemplateServiceImpl implements MesQcTemplateService {
53 53 public Long createTemplate(MesQcTemplateSaveReqVO createReqVO) {
54 54 // 校验编码唯一
55 55 validateTemplateCodeUnique(null, createReqVO.getCode());
56   - // 插入(types 由 IntegerListTypeHandler 自动做 List↔逗号字符串转换,enableFlag Boolean↔bit 自动映射)
  56 +
  57 + // 插入
57 58 MesQcTemplateDO template = BeanUtils.toBean(createReqVO, MesQcTemplateDO.class);
58 59 templateMapper.insert(template);
59 60 return template.getId();
... ...