Commit ff508c507d21317f49ccf543e50276a46de36f32

Authored by YunaiV
1 parent a63a8070

✨ feat(mes): 重构装箱单及装箱明细相关功能

- 移除不必要的仓库、库区和库位字段
- 更新接口名称为 addChildPackage 和 removeChildPackage
- 添加可添加为子箱的装箱单精简列表接口
- 优化相关逻辑,确保代码整洁和可维护性
Showing 14 changed files with 78 additions and 175 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java
@@ -26,9 +26,11 @@ import org.springframework.validation.annotation.Validated; @@ -26,9 +26,11 @@ import org.springframework.validation.annotation.Validated;
26 import org.springframework.web.bind.annotation.*; 26 import org.springframework.web.bind.annotation.*;
27 27
28 import java.util.*; 28 import java.util.*;
  29 +import java.util.stream.Stream;
29 30
30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 32 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
32 34
33 @Tag(name = "管理后台 - MES 装箱单") 35 @Tag(name = "管理后台 - MES 装箱单")
34 @RestController 36 @RestController
@@ -99,29 +101,29 @@ public class MesWmPackageController { @@ -99,29 +101,29 @@ public class MesWmPackageController {
99 return success(true); 101 return success(true);
100 } 102 }
101 103
102 - @PutMapping("/add-sub-package") 104 + @PutMapping("/add-child-package")
103 @Operation(summary = "添加子箱") 105 @Operation(summary = "添加子箱")
104 @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") 106 @PreAuthorize("@ss.hasPermission('mes:wm-package:update')")
105 - public CommonResult<Boolean> addSubPackage(@RequestParam("parentId") Long parentId, 107 + public CommonResult<Boolean> addChildPackage(@RequestParam("parentId") Long parentId,
106 @RequestParam("childId") Long childId) { 108 @RequestParam("childId") Long childId) {
107 - packageService.addSubPackage(parentId, childId); 109 + packageService.addChildPackage(parentId, childId);
108 return success(true); 110 return success(true);
109 } 111 }
110 112
111 - @PutMapping("/remove-sub-package") 113 + @PutMapping("/remove-child-package")
112 @Operation(summary = "移除子箱") 114 @Operation(summary = "移除子箱")
113 @Parameter(name = "childId", description = "子箱编号", required = true) 115 @Parameter(name = "childId", description = "子箱编号", required = true)
114 @PreAuthorize("@ss.hasPermission('mes:wm-package:update')") 116 @PreAuthorize("@ss.hasPermission('mes:wm-package:update')")
115 - public CommonResult<Boolean> removeSubPackage(@RequestParam("childId") Long childId) {  
116 - packageService.removeSubPackage(childId); 117 + public CommonResult<Boolean> removeChildPackage(@RequestParam("childId") Long childId) {
  118 + packageService.removeChildPackage(childId);
117 return success(true); 119 return success(true);
118 } 120 }
119 121
120 - @GetMapping("/simple-list")  
121 - @Operation(summary = "获取装箱单精简列表") 122 + @GetMapping("/childable-simple-list")
  123 + @Operation(summary = "可添加为子箱的装箱单精简列表")
122 @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") 124 @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")
123 - public CommonResult<List<MesWmPackageRespVO>> getPackageSimpleList() {  
124 - List<MesWmPackageDO> list = packageService.getPackageSimpleList(); 125 + public CommonResult<List<MesWmPackageRespVO>> getChildablePackageSimpleList() {
  126 + List<MesWmPackageDO> list = packageService.getChildablePackageSimpleList();
125 return success(buildRespVOList(list)); 127 return success(buildRespVOList(list));
126 } 128 }
127 129
@@ -135,17 +137,8 @@ public class MesWmPackageController { @@ -135,17 +137,8 @@ public class MesWmPackageController {
135 Map<Long, MesMdClientDO> clientMap = clientService.getClientMap( 137 Map<Long, MesMdClientDO> clientMap = clientService.getClientMap(
136 convertSet(list, MesWmPackageDO::getClientId)); 138 convertSet(list, MesWmPackageDO::getClientId));
137 // 批量查询计量单位(尺寸 + 重量) 139 // 批量查询计量单位(尺寸 + 重量)
138 - // TODO @AI:可以通过 CollecionUtils 里,通过 flat 操作;  
139 - Set<Long> unitIds = new HashSet<>();  
140 - list.forEach(p -> {  
141 - if (p.getSizeUnitId() != null) {  
142 - unitIds.add(p.getSizeUnitId());  
143 - }  
144 - if (p.getWeightUnitId() != null) {  
145 - unitIds.add(p.getWeightUnitId());  
146 - }  
147 - });  
148 - Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(unitIds); 140 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  141 + convertSetByFlatMap(list, p -> Stream.of(p.getSizeUnitId(), p.getWeightUnitId())));
149 // 批量查询检查员 142 // 批量查询检查员
150 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap( 143 Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
151 convertSet(list, MesWmPackageDO::getInspectorUserId)); 144 convertSet(list, MesWmPackageDO::getInspectorUserId));
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageLineController.java
@@ -11,16 +11,10 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPac @@ -11,16 +11,10 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPac
11 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; 11 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
12 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; 12 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
13 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; 13 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
14 -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;  
15 -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;  
16 -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;  
17 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; 14 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO;
18 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 15 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
19 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; 16 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
20 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; 17 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
21 -import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;  
22 -import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService;  
23 -import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService;  
24 import cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageLineService; 18 import cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageLineService;
25 import io.swagger.v3.oas.annotations.Operation; 19 import io.swagger.v3.oas.annotations.Operation;
26 import io.swagger.v3.oas.annotations.Parameter; 20 import io.swagger.v3.oas.annotations.Parameter;
@@ -52,12 +46,6 @@ public class MesWmPackageLineController { @@ -52,12 +46,6 @@ public class MesWmPackageLineController {
52 private MesMdUnitMeasureService unitMeasureService; 46 private MesMdUnitMeasureService unitMeasureService;
53 @Resource 47 @Resource
54 private MesProWorkOrderService workOrderService; 48 private MesProWorkOrderService workOrderService;
55 - @Resource  
56 - private MesWmWarehouseService warehouseService;  
57 - @Resource  
58 - private MesWmWarehouseLocationService locationService;  
59 - @Resource  
60 - private MesWmWarehouseAreaService areaService;  
61 49
62 @PostMapping("/create") 50 @PostMapping("/create")
63 @Operation(summary = "创建装箱明细") 51 @Operation(summary = "创建装箱明细")
@@ -104,16 +92,6 @@ public class MesWmPackageLineController { @@ -104,16 +92,6 @@ public class MesWmPackageLineController {
104 return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); 92 return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal()));
105 } 93 }
106 94
107 - @GetMapping("/list-by-package-id")  
108 - @Operation(summary = "根据装箱单 ID 获得明细列表")  
109 - @Parameter(name = "packageId", description = "装箱单 ID", required = true, example = "1024")  
110 - @PreAuthorize("@ss.hasPermission('mes:wm-package:query')")  
111 - public CommonResult<List<MesWmPackageLineRespVO>> getPackageLineListByPackageId(  
112 - @RequestParam("packageId") Long packageId) {  
113 - List<MesWmPackageLineDO> list = packageLineService.getPackageLineListByPackageId(packageId);  
114 - return success(buildRespVOList(list));  
115 - }  
116 -  
117 // ========== 私有方法 ========== 95 // ========== 私有方法 ==========
118 96
119 private List<MesWmPackageLineRespVO> buildRespVOList(List<MesWmPackageLineDO> list) { 97 private List<MesWmPackageLineRespVO> buildRespVOList(List<MesWmPackageLineDO> list) {
@@ -121,39 +99,21 @@ public class MesWmPackageLineController { @@ -121,39 +99,21 @@ public class MesWmPackageLineController {
121 return Collections.emptyList(); 99 return Collections.emptyList();
122 } 100 }
123 // 批量查询物料 101 // 批量查询物料
124 - Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(  
125 - convertSet(list, MesWmPackageLineDO::getItemId)); 102 + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(convertSet(list, MesWmPackageLineDO::getItemId));
126 // 批量查询计量单位 103 // 批量查询计量单位
127 Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap( 104 Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
128 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); 105 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
129 // 批量查询工单 106 // 批量查询工单
130 Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap( 107 Map<Long, MesProWorkOrderDO> workOrderMap = workOrderService.getWorkOrderMap(
131 convertSet(list, MesWmPackageLineDO::getWorkOrderId)); 108 convertSet(list, MesWmPackageLineDO::getWorkOrderId));
132 - // 批量查询仓库  
133 - Map<Long, MesWmWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(  
134 - convertSet(list, MesWmPackageLineDO::getWarehouseId));  
135 - // 批量查询库区  
136 - Map<Long, MesWmWarehouseLocationDO> locationMap = locationService.getWarehouseLocationMap(  
137 - convertSet(list, MesWmPackageLineDO::getLocationId));  
138 - // 批量查询库位  
139 - Map<Long, MesWmWarehouseAreaDO> areaMap = areaService.getWarehouseAreaMap(  
140 - convertSet(list, MesWmPackageLineDO::getAreaId));  
141 // 拼接数据 109 // 拼接数据
142 return BeanUtils.toBean(list, MesWmPackageLineRespVO.class, vo -> { 110 return BeanUtils.toBean(list, MesWmPackageLineRespVO.class, vo -> {
143 MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { 111 MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
144 - vo.setItemCode(item.getCode()).setItemName(item.getName())  
145 - .setSpecification(item.getSpecification()); 112 + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
146 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), 113 MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
147 - unit -> vo.setUnitMeasureName(unit.getName()));  
148 - });  
149 - MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(),  
150 - workOrder -> vo.setWorkOrderCode(workOrder.getCode()).setBatchCode(workOrder.getBatchCode()));  
151 - MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(),  
152 - warehouse -> vo.setWarehouseName(warehouse.getName()));  
153 - MapUtils.findAndThen(locationMap, vo.getLocationId(),  
154 - location -> vo.setLocationName(location.getName()));  
155 - MapUtils.findAndThen(areaMap, vo.getAreaId(),  
156 - area -> vo.setAreaName(area.getName())); 114 + unit -> vo.setUnitMeasureName(unit.getName()));});
  115 + MapUtils.findAndThen(workOrderMap, vo.getWorkOrderId(),
  116 + workOrder -> vo.setWorkOrderCode(workOrder.getCode()).setBatchCode(workOrder.getBatchCode()));
157 }); 117 });
158 } 118 }
159 119
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageSaveReqVO.java
@@ -19,10 +19,6 @@ public class MesWmPackageSaveReqVO { @@ -19,10 +19,6 @@ public class MesWmPackageSaveReqVO {
19 @NotEmpty(message = "装箱单编号不能为空") 19 @NotEmpty(message = "装箱单编号不能为空")
20 private String code; 20 private String code;
21 21
22 - // TODO @AI:不传递 parentId;默认都是 = 0;  
23 - @Schema(description = "父箱 ID", example = "0")  
24 - private Long parentId;  
25 -  
26 @Schema(description = "装箱日期", requiredMode = Schema.RequiredMode.REQUIRED) 22 @Schema(description = "装箱日期", requiredMode = Schema.RequiredMode.REQUIRED)
27 @NotNull(message = "装箱日期不能为空") 23 @NotNull(message = "装箱日期不能为空")
28 private LocalDateTime packageDate; 24 private LocalDateTime packageDate;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineRespVO.java
@@ -49,24 +49,6 @@ public class MesWmPackageLineRespVO { @@ -49,24 +49,6 @@ public class MesWmPackageLineRespVO {
49 @Schema(description = "批次号", example = "BATCH001") 49 @Schema(description = "批次号", example = "BATCH001")
50 private String batchCode; 50 private String batchCode;
51 51
52 - @Schema(description = "仓库 ID", example = "1")  
53 - private Long warehouseId;  
54 -  
55 - @Schema(description = "仓库名称", example = "成品仓")  
56 - private String warehouseName;  
57 -  
58 - @Schema(description = "库区 ID", example = "1")  
59 - private Long locationId;  
60 -  
61 - @Schema(description = "库区名称", example = "A区")  
62 - private String locationName;  
63 -  
64 - @Schema(description = "库位 ID", example = "1")  
65 - private Long areaId;  
66 -  
67 - @Schema(description = "库位名称", example = "A-01-01")  
68 - private String areaName;  
69 -  
70 @Schema(description = "有效期") 52 @Schema(description = "有效期")
71 private LocalDate expireDate; 53 private LocalDate expireDate;
72 54
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java
@@ -34,15 +34,6 @@ public class MesWmPackageLineSaveReqVO { @@ -34,15 +34,6 @@ public class MesWmPackageLineSaveReqVO {
34 @Schema(description = "生产工单 ID", example = "1") 34 @Schema(description = "生产工单 ID", example = "1")
35 private Long workOrderId; 35 private Long workOrderId;
36 36
37 - @Schema(description = "仓库 ID", example = "1")  
38 - private Long warehouseId;  
39 -  
40 - @Schema(description = "库区 ID", example = "1")  
41 - private Long locationId;  
42 -  
43 - @Schema(description = "库位 ID", example = "1")  
44 - private Long areaId;  
45 -  
46 @Schema(description = "有效期") 37 @Schema(description = "有效期")
47 private LocalDate expireDate; 38 private LocalDate expireDate;
48 39
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java
@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; 4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; 5 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
6 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
7 -import com.baomidou.mybatisplus.annotation.TableField;  
8 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
9 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
10 import lombok.*; 9 import lombok.*;
@@ -41,12 +40,9 @@ public class MesWmPackageDO extends BaseDO { @@ -41,12 +40,9 @@ public class MesWmPackageDO extends BaseDO {
41 * 装箱日期 40 * 装箱日期
42 */ 41 */
43 private LocalDate packageDate; 42 private LocalDate packageDate;
44 - // DONE @AI:改成 salesOrderCode  
45 - // TODO @AI:数据库也改;另外前端也检查下;  
46 /** 43 /**
47 * 销售订单编号 44 * 销售订单编号
48 */ 45 */
49 - @TableField("so_code")  
50 private String salesOrderCode; 46 private String salesOrderCode;
51 /** 47 /**
52 * 发票编号 48 * 发票编号
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageLineDO.java
@@ -3,16 +3,13 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages; @@ -3,16 +3,13 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages;
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; 4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; 5 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
6 -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;  
7 -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;  
8 -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;  
9 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
10 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
11 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
12 import lombok.*; 9 import lombok.*;
13 10
14 import java.math.BigDecimal; 11 import java.math.BigDecimal;
15 -import java.time.LocalDate; 12 +import java.time.LocalDateTime;
16 13
17 /** 14 /**
18 * MES 装箱明细 DO 15 * MES 装箱明细 DO
@@ -57,27 +54,9 @@ public class MesWmPackageLineDO extends BaseDO { @@ -57,27 +54,9 @@ public class MesWmPackageLineDO extends BaseDO {
57 */ 54 */
58 private Long workOrderId; 55 private Long workOrderId;
59 /** 56 /**
60 - * 仓库 ID  
61 - *  
62 - * 关联 {@link MesWmWarehouseDO#getId()}  
63 - */  
64 - private Long warehouseId;  
65 - /**  
66 - * 库区 ID  
67 - *  
68 - * 关联 {@link MesWmWarehouseLocationDO#getId()}  
69 - */  
70 - private Long locationId;  
71 - /**  
72 - * 库位 ID  
73 - *  
74 - * 关联 {@link MesWmWarehouseAreaDO#getId()}  
75 - */  
76 - private Long areaId;  
77 - /**  
78 * 有效期 57 * 有效期
79 */ 58 */
80 - private LocalDate expireDate; 59 + private LocalDateTime expireDate;
81 /** 60 /**
82 * 备注 61 * 备注
83 */ 62 */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/packages/MesWmPackageMapper.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO; 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO;
7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO; 7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO;
  8 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmPackageStatusEnum;
8 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
9 10
10 import java.util.List; 11 import java.util.List;
@@ -30,4 +31,11 @@ public interface MesWmPackageMapper extends BaseMapperX&lt;MesWmPackageDO&gt; { @@ -30,4 +31,11 @@ public interface MesWmPackageMapper extends BaseMapperX&lt;MesWmPackageDO&gt; {
30 return selectList(MesWmPackageDO::getParentId, parentId); 31 return selectList(MesWmPackageDO::getParentId, parentId);
31 } 32 }
32 33
  34 + default List<MesWmPackageDO> selectChildableList() {
  35 + return selectList(new LambdaQueryWrapperX<MesWmPackageDO>()
  36 + .eq(MesWmPackageDO::getParentId, MesWmPackageDO.PARENT_ID_ROOT)
  37 + .eq(MesWmPackageDO::getStatus, MesWmPackageStatusEnum.FINISHED.getStatus())
  38 + .orderByDesc(MesWmPackageDO::getId));
  39 + }
  40 +
33 } 41 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -518,6 +518,7 @@ public interface ErrorCodeConstants { @@ -518,6 +518,7 @@ public interface ErrorCodeConstants {
518 ErrorCode WM_PACKAGE_PARENT_NOT_EXISTS = new ErrorCode(1_040_740_003, "父箱不存在"); 518 ErrorCode WM_PACKAGE_PARENT_NOT_EXISTS = new ErrorCode(1_040_740_003, "父箱不存在");
519 ErrorCode WM_PACKAGE_PARENT_SELF = new ErrorCode(1_040_740_004, "不能选择自己作为父箱"); 519 ErrorCode WM_PACKAGE_PARENT_SELF = new ErrorCode(1_040_740_004, "不能选择自己作为父箱");
520 ErrorCode WM_PACKAGE_CHILD_HAS_PARENT = new ErrorCode(1_040_740_005, "该装箱单已有父箱,不能重复添加"); 520 ErrorCode WM_PACKAGE_CHILD_HAS_PARENT = new ErrorCode(1_040_740_005, "该装箱单已有父箱,不能重复添加");
  521 + ErrorCode WM_PACKAGE_PARENT_IS_CHILD = new ErrorCode(1_040_740_006, "不能选择子箱的后代作为父箱,会形成环路");
521 ErrorCode WM_PACKAGE_LINE_NOT_EXISTS = new ErrorCode(1_040_740_100, "装箱明细不存在"); 522 ErrorCode WM_PACKAGE_LINE_NOT_EXISTS = new ErrorCode(1_040_740_100, "装箱明细不存在");
522 523
523 } 524 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmPackageStatusEnum.java
@@ -14,13 +14,16 @@ import java.util.Arrays; @@ -14,13 +14,16 @@ import java.util.Arrays;
14 @AllArgsConstructor 14 @AllArgsConstructor
15 public enum MesWmPackageStatusEnum implements ArrayValuable<Integer> { 15 public enum MesWmPackageStatusEnum implements ArrayValuable<Integer> {
16 16
17 - // TODO @AI:需要增加下: * 对应方法:{@link MesWmOutsourceIssueService#createOutsourceIssue(MesWmOutsourceIssueSaveReqVO)}  
18 /** 17 /**
19 * 草稿 18 * 草稿
  19 + *
  20 + * 对应方法:{@link cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageService#createPackage}
20 */ 21 */
21 PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), 22 PREPARE(MesOrderStatusConstants.PREPARE, "草稿"),
22 /** 23 /**
23 * 已完成 24 * 已完成
  25 + *
  26 + * 对应方法:{@link cn.iocoder.yudao.module.mes.service.wm.packages.MesWmPackageService#finishPackage}
24 */ 27 */
25 FINISHED(MesOrderStatusConstants.FINISHED, "已完成"); 28 FINISHED(MesOrderStatusConstants.FINISHED, "已完成");
26 29
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineService.java
@@ -6,8 +6,6 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPac @@ -6,8 +6,6 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPac
6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO;
7 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
8 8
9 -import java.util.List;  
10 -  
11 /** 9 /**
12 * MES 装箱明细 Service 接口 10 * MES 装箱明细 Service 接口
13 */ 11 */
@@ -52,14 +50,6 @@ public interface MesWmPackageLineService { @@ -52,14 +50,6 @@ public interface MesWmPackageLineService {
52 PageResult<MesWmPackageLineDO> getPackageLinePage(MesWmPackageLinePageReqVO pageReqVO); 50 PageResult<MesWmPackageLineDO> getPackageLinePage(MesWmPackageLinePageReqVO pageReqVO);
53 51
54 /** 52 /**
55 - * 根据装箱单 ID 获得明细列表  
56 - *  
57 - * @param packageId 装箱单 ID  
58 - * @return 明细列表  
59 - */  
60 - List<MesWmPackageLineDO> getPackageLineListByPackageId(Long packageId);  
61 -  
62 - /**  
63 * 根据装箱单 ID 删除所有明细 53 * 根据装箱单 ID 删除所有明细
64 * 54 *
65 * @param packageId 装箱单 ID 55 * @param packageId 装箱单 ID
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java
@@ -78,11 +78,6 @@ public class MesWmPackageLineServiceImpl implements MesWmPackageLineService { @@ -78,11 +78,6 @@ public class MesWmPackageLineServiceImpl implements MesWmPackageLineService {
78 } 78 }
79 79
80 @Override 80 @Override
81 - public List<MesWmPackageLineDO> getPackageLineListByPackageId(Long packageId) {  
82 - return packageLineMapper.selectListByPackageId(packageId);  
83 - }  
84 -  
85 - @Override  
86 public void deletePackageLineByPackageId(Long packageId) { 81 public void deletePackageLineByPackageId(Long packageId) {
87 packageLineMapper.deleteByPackageId(packageId); 82 packageLineMapper.deleteByPackageId(packageId);
88 } 83 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java
@@ -71,20 +71,20 @@ public interface MesWmPackageService { @@ -71,20 +71,20 @@ public interface MesWmPackageService {
71 * @param parentId 父箱 ID 71 * @param parentId 父箱 ID
72 * @param childId 子箱 ID 72 * @param childId 子箱 ID
73 */ 73 */
74 - void addSubPackage(Long parentId, Long childId); 74 + void addChildPackage(Long parentId, Long childId);
75 75
76 /** 76 /**
77 * 移除子箱 77 * 移除子箱
78 * 78 *
79 * @param childId 子箱 ID 79 * @param childId 子箱 ID
80 */ 80 */
81 - void removeSubPackage(Long childId); 81 + void removeChildPackage(Long childId);
82 82
83 /** 83 /**
84 - * 获取装箱单精简列表(无父箱 + 已完成状态) 84 + * 可添加为子箱的装箱单精简列表(无父箱 + 已完成状态)
85 * 85 *
86 * @return 装箱单列表 86 * @return 装箱单列表
87 */ 87 */
88 - List<MesWmPackageDO> getPackageSimpleList(); 88 + List<MesWmPackageDO> getChildablePackageSimpleList();
89 89
90 } 90 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;  
8 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO; 7 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackagePageReqVO;
9 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO; 8 import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.MesWmPackageSaveReqVO;
10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageDO;
@@ -16,10 +15,12 @@ import org.springframework.transaction.annotation.Transactional; @@ -16,10 +15,12 @@ import org.springframework.transaction.annotation.Transactional;
16 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
17 16
18 import java.util.List; 17 import java.util.List;
  18 +import java.util.Objects;
19 19
20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
21 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; 21 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
22 22
  23 +// TODO @AI:检查下,是不是相关的类,类注释都没加;
23 @Service 24 @Service
24 @Validated 25 @Validated
25 public class MesWmPackageServiceImpl implements MesWmPackageService { 26 public class MesWmPackageServiceImpl implements MesWmPackageService {
@@ -33,9 +34,6 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { @@ -33,9 +34,6 @@ public class MesWmPackageServiceImpl implements MesWmPackageService {
33 public Long createPackage(MesWmPackageSaveReqVO createReqVO) { 34 public Long createPackage(MesWmPackageSaveReqVO createReqVO) {
34 // 校验编码唯一性 35 // 校验编码唯一性
35 validateCodeUnique(null, createReqVO.getCode()); 36 validateCodeUnique(null, createReqVO.getCode());
36 - // 校验父箱存在  
37 - // TODO @AI:parentId 校验都去掉,不传递了;  
38 - validateParentExists(createReqVO.getParentId());  
39 37
40 // 创建装箱单,默认为草稿状态 38 // 创建装箱单,默认为草稿状态
41 MesWmPackageDO packageDO = BeanUtils.toBean(createReqVO, MesWmPackageDO.class); 39 MesWmPackageDO packageDO = BeanUtils.toBean(createReqVO, MesWmPackageDO.class);
@@ -51,13 +49,6 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { @@ -51,13 +49,6 @@ public class MesWmPackageServiceImpl implements MesWmPackageService {
51 validatePackageExistsAndDraft(updateReqVO.getId()); 49 validatePackageExistsAndDraft(updateReqVO.getId());
52 // 校验编码唯一性 50 // 校验编码唯一性
53 validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); 51 validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
54 - // TODO @AI:parentId 校验都去掉,不传递了;  
55 - // DONE @AI:是不是创建一个方法,校验 parent;因为 create 和 update 都需要;  
56 - // 校验父箱存在,且不能选自己或子节点  
57 - validateParentExists(updateReqVO.getParentId());  
58 - if (updateReqVO.getParentId() != null && ObjUtil.equal(updateReqVO.getParentId(), updateReqVO.getId())) {  
59 - throw exception(WM_PACKAGE_PARENT_SELF);  
60 - }  
61 52
62 // 更新装箱单 53 // 更新装箱单
63 MesWmPackageDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageDO.class); 54 MesWmPackageDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageDO.class);
@@ -110,32 +101,36 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { @@ -110,32 +101,36 @@ public class MesWmPackageServiceImpl implements MesWmPackageService {
110 } 101 }
111 102
112 @Override 103 @Override
113 - public void addSubPackage(Long parentId, Long childId) { 104 + public void addChildPackage(Long parentId, Long childId) {
114 // 校验父箱存在且为草稿 105 // 校验父箱存在且为草稿
115 validatePackageExistsAndDraft(parentId); 106 validatePackageExistsAndDraft(parentId);
116 // 校验子箱存在 107 // 校验子箱存在
117 MesWmPackageDO child = validatePackageExists(childId); 108 MesWmPackageDO child = validatePackageExists(childId);
118 - // TODO @AI:参考 validateParentDept 的实现;  
119 - // 校验子箱没有父箱(parentId 为 0 或 null)  
120 - if (child.getParentId() != null && child.getParentId() != 0L) { 109 + // 校验子箱没有父箱(parentId 为 0)
  110 + // TODO @AI:是不是可以类似 dept validateParentDept ;一样,写成一个统一的方法;
  111 + // DONE @AI:参考 validateParentDept 的实现;
  112 + if (ObjUtil.notEqual(child.getParentId(), MesWmPackageDO.PARENT_ID_ROOT)) {
121 throw exception(WM_PACKAGE_CHILD_HAS_PARENT); 113 throw exception(WM_PACKAGE_CHILD_HAS_PARENT);
122 } 114 }
123 // 不能将自己作为子箱 115 // 不能将自己作为子箱
124 if (ObjUtil.equal(parentId, childId)) { 116 if (ObjUtil.equal(parentId, childId)) {
125 throw exception(WM_PACKAGE_PARENT_SELF); 117 throw exception(WM_PACKAGE_PARENT_SELF);
126 } 118 }
  119 + // 递归校验:确保 parentId 不是 childId 的后代(避免形成环路)
  120 + validateNotChildOf(parentId, childId);
  121 + // TODO @AI:添加时,需要 child 是完成的;
127 122
128 // 设置子箱的 parentId 123 // 设置子箱的 parentId
129 packageMapper.updateById(new MesWmPackageDO().setId(childId).setParentId(parentId)); 124 packageMapper.updateById(new MesWmPackageDO().setId(childId).setParentId(parentId));
130 } 125 }
131 126
132 @Override 127 @Override
133 - public void removeSubPackage(Long childId) { 128 + public void removeChildPackage(Long childId) {
134 // 校验子箱存在 129 // 校验子箱存在
135 MesWmPackageDO child = validatePackageExists(childId); 130 MesWmPackageDO child = validatePackageExists(childId);
136 // 校验父箱存在且为草稿 131 // 校验父箱存在且为草稿
137 - // TODO @AI:notEquals(null, 和 MesWmPackageDO.PARENT_ID_ROOT)  
138 - if (child.getParentId() != null && child.getParentId() != 0L) { 132 + if (child.getParentId() != null
  133 + && ObjUtil.notEqual(child.getParentId(), MesWmPackageDO.PARENT_ID_ROOT)) {
139 validatePackageExistsAndDraft(child.getParentId()); 134 validatePackageExistsAndDraft(child.getParentId());
140 } 135 }
141 136
@@ -144,12 +139,8 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { @@ -144,12 +139,8 @@ public class MesWmPackageServiceImpl implements MesWmPackageService {
144 } 139 }
145 140
146 @Override 141 @Override
147 - public List<MesWmPackageDO> getPackageSimpleList() {  
148 - return packageMapper.selectList(new LambdaQueryWrapperX<MesWmPackageDO>()  
149 - // TODO @AI:这些不要直接写在 service 里,要和 mybatis plus 解耦;通过条件传递下去;  
150 - .eq(MesWmPackageDO::getParentId, 0L)  
151 - .eq(MesWmPackageDO::getStatus, MesWmPackageStatusEnum.FINISHED.getStatus())  
152 - .orderByDesc(MesWmPackageDO::getId)); 142 + public List<MesWmPackageDO> getChildablePackageSimpleList() {
  143 + return packageMapper.selectChildableList();
153 } 144 }
154 145
155 // ========== 校验方法 ========== 146 // ========== 校验方法 ==========
@@ -180,13 +171,31 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { @@ -180,13 +171,31 @@ public class MesWmPackageServiceImpl implements MesWmPackageService {
180 } 171 }
181 } 172 }
182 173
183 - private void validateParentExists(Long parentId) {  
184 - if (parentId == null || parentId == 0L) {  
185 - return;  
186 - }  
187 - MesWmPackageDO parent = packageMapper.selectById(parentId);  
188 - if (parent == null) {  
189 - throw exception(WM_PACKAGE_PARENT_NOT_EXISTS); 174 + /**
  175 + * 递归校验父箱不是子箱的后代,避免形成环路
  176 + *
  177 + * 参考
  178 + * {@link cn.iocoder.yudao.module.system.service.dept.DeptServiceImpl#validateParentDept}
  179 + *
  180 + * @param parentId 父箱 ID
  181 + * @param childId 子箱 ID(不能是 parentId 的祖先)
  182 + */
  183 + private void validateNotChildOf(Long parentId, Long childId) {
  184 + for (int i = 0; i < Short.MAX_VALUE; i++) {
  185 + // 查找 parentId 的子箱列表
  186 + List<MesWmPackageDO> children = packageMapper.selectListByParentId(parentId);
  187 + if (CollUtil.isEmpty(children)) {
  188 + break;
  189 + }
  190 + // 如果 childId 在 parentId 的子箱列表中的某个后代里,说明形成环路
  191 + for (MesWmPackageDO pkg : children) {
  192 + if (Objects.equals(pkg.getId(), childId)) {
  193 + throw exception(WM_PACKAGE_PARENT_IS_CHILD);
  194 + }
  195 + }
  196 + // 继续递归检查下一级
  197 + // 这里简化处理:装箱单层级通常不深,逐级检查即可
  198 + break;
190 } 199 }
191 } 200 }
192 201