Commit a5c49881aab071a35e56375132af637008ff777d

Authored by YunaiV
1 parent 7a593977

✨ feat(mes): 添加到货通知单和入库单的状态枚举及相关校验

新增 MES 到货通知单和入库单的状态枚举类,提供更清晰的状态管理。
同时在相关服务中添加了对父单据状态的校验,确保只有在草稿状态下才能进行修改和删除操作。

此变更提升了代码的可读性和维护性,减少了硬编码的状态值使用。
Showing 23 changed files with 370 additions and 165 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java
... ... @@ -104,20 +104,16 @@ public class MesWmArrivalNoticeLineController {
104 104 // 1. 获得关联数据
105 105 Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
106 106 convertSet(list, MesWmArrivalNoticeLineDO::getItemId));
  107 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  108 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
107 109 Map<Long, MesQcIqcDO> iqcMap = iqcService.getIqcMap(
108 110 convertSet(list, MesWmArrivalNoticeLineDO::getIqcId));
109 111 // 2. 构建结果
110 112 return BeanUtils.toBean(list, MesWmArrivalNoticeLineRespVO.class, vo -> {
111 113 MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
112 114 vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
113   - // 查询物料的计量单位名称
114   - // TODO @AI:也批量查询,避免逐个;
115   - if (item.getUnitMeasureId() != null) {
116   - MesMdUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasure(item.getUnitMeasureId());
117   - if (unitMeasure != null) {
118   - vo.setUnitMeasureName(unitMeasure.getName());
119   - }
120   - }
  115 + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
  116 + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
121 117 });
122 118 MapUtils.findAndThen(iqcMap, vo.getIqcId(), iqc -> vo.setIqcCode(iqc.getCode()));
123 119 });
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLinePageReqVO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotNull;
5 6 import lombok.Data;
6 7 import lombok.EqualsAndHashCode;
7 8 import lombok.ToString;
... ... @@ -13,6 +14,7 @@ import lombok.ToString;
13 14 public class MesWmArrivalNoticeLinePageReqVO extends PageParam {
14 15  
15 16 @Schema(description = "到货通知单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + @NotNull(message = "到货通知单编号不能为空")
16 18 private Long noticeId;
17 19  
18 20 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/line/MesWmArrivalNoticeLineSaveReqVO.java
... ... @@ -21,7 +21,8 @@ public class MesWmArrivalNoticeLineSaveReqVO {
21 21 @NotNull(message = "物料编号不能为空")
22 22 private Long itemId;
23 23  
24   - @Schema(description = "到货数量", example = "500.00")
  24 + @Schema(description = "到货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00")
  25 + @NotNull(message = "到货数量不能为空")
25 26 private BigDecimal arrivalQuantity;
26 27  
27 28 @Schema(description = "合格数量", example = "500.00")
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptDetailController.java
... ... @@ -114,6 +114,8 @@ public class MesWmItemReceiptDetailController {
114 114 // 1. 获得关联数据
115 115 Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
116 116 convertSet(list, MesWmItemReceiptDetailDO::getItemId));
  117 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  118 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
117 119 Map<Long, MesWmWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
118 120 convertSet(list, MesWmItemReceiptDetailDO::getWarehouseId));
119 121 Map<Long, MesWmWarehouseLocationDO> locationMap = locationService.getWarehouseLocationMap(
... ... @@ -124,13 +126,8 @@ public class MesWmItemReceiptDetailController {
124 126 return BeanUtils.toBean(list, MesWmItemReceiptDetailRespVO.class, vo -> {
125 127 MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
126 128 vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
127   - // TODO @AI:批量查询,避免 N+1 查询
128   - if (item.getUnitMeasureId() != null) {
129   - MesMdUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasure(item.getUnitMeasureId());
130   - if (unitMeasure != null) {
131   - vo.setUnitMeasureName(unitMeasure.getName());
132   - }
133   - }
  129 + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
  130 + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
134 131 });
135 132 MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(),
136 133 warehouse -> vo.setWarehouseName(warehouse.getName()));
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java
... ... @@ -119,6 +119,8 @@ public class MesWmItemReceiptLineController {
119 119 // 1. 获得关联数据
120 120 Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
121 121 convertSet(list, MesWmItemReceiptLineDO::getItemId));
  122 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  123 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
122 124 Map<Long, MesWmWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
123 125 convertSet(list, MesWmItemReceiptLineDO::getWarehouseId));
124 126 Map<Long, MesWmWarehouseLocationDO> locationMap = locationService.getWarehouseLocationMap(
... ... @@ -131,13 +133,8 @@ public class MesWmItemReceiptLineController {
131 133 return BeanUtils.toBean(list, MesWmItemReceiptLineRespVO.class, vo -> {
132 134 MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
133 135 vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification());
134   - // TODO @AI:批量查询,避免 N+1 查询
135   - if (item.getUnitMeasureId() != null) {
136   - MesMdUnitMeasureDO unitMeasure = unitMeasureService.getUnitMeasure(item.getUnitMeasureId());
137   - if (unitMeasure != null) {
138   - vo.setUnitMeasureName(unitMeasure.getName());
139   - }
140   - }
  136 + MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(),
  137 + unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName()));
141 138 });
142 139 MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(),
143 140 warehouse -> vo.setWarehouseName(warehouse.getName()));
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailPageReqVO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotNull;
5 6 import lombok.Data;
6 7 import lombok.EqualsAndHashCode;
7 8 import lombok.ToString;
... ... @@ -12,10 +13,12 @@ import lombok.ToString;
12 13 @ToString(callSuper = true)
13 14 public class MesWmItemReceiptDetailPageReqVO extends PageParam {
14 15  
15   - @Schema(description = "入库单编号", example = "1")
  16 + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + @NotNull(message = "入库单编号不能为空")
16 18 private Long receiptId;
17 19  
18   - @Schema(description = "入库单行编号", example = "1")
  20 + @Schema(description = "入库单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  21 + @NotNull(message = "入库单行编号不能为空")
19 22 private Long lineId;
20 23  
21 24 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/detail/MesWmItemReceiptDetailSaveReqVO.java
... ... @@ -25,7 +25,8 @@ public class MesWmItemReceiptDetailSaveReqVO {
25 25 @NotNull(message = "物料编号不能为空")
26 26 private Long itemId;
27 27  
28   - @Schema(description = "上架数量", example = "300.00")
  28 + @Schema(description = "上架数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00")
  29 + @NotNull(message = "上架数量不能为空")
29 30 private BigDecimal quantity;
30 31  
31 32 @Schema(description = "批次编号", example = "1")
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLinePageReqVO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotNull;
5 6 import lombok.Data;
6 7 import lombok.EqualsAndHashCode;
7 8 import lombok.ToString;
... ... @@ -13,6 +14,7 @@ import lombok.ToString;
13 14 public class MesWmItemReceiptLinePageReqVO extends PageParam {
14 15  
15 16 @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  17 + @NotNull(message = "入库单编号不能为空")
16 18 private Long receiptId;
17 19  
18 20 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineSaveReqVO.java
... ... @@ -25,7 +25,8 @@ public class MesWmItemReceiptLineSaveReqVO {
25 25 @NotNull(message = "物料编号不能为空")
26 26 private Long itemId;
27 27  
28   - @Schema(description = "入库数量", example = "500.00")
  28 + @Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "500.00")
  29 + @NotNull(message = "入库数量不能为空")
29 30 private BigDecimal receivedQuantity;
30 31  
31 32 @Schema(description = "批次编号", example = "1")
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
  5 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum;
5 6 import com.baomidou.mybatisplus.annotation.KeySequence;
6 7 import com.baomidou.mybatisplus.annotation.TableId;
7 8 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -57,12 +58,10 @@ public class MesWmArrivalNoticeDO extends BaseDO {
57 58 * 联系电话
58 59 */
59 60 private String contactTelephone;
60   - // TODO @AI:枚举类;需要 @关联
61   - // TODO @AI:字典类;需要 @关联
62 61 /**
63 62 * 状态
64 63 *
65   - * 0=草稿 1=已提交 2=已审批 3=已完成
  64 + * 枚举 {@link MesWmArrivalNoticeStatusEnum}
66 65 */
67 66 private Integer status;
68 67 /**
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 4 import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
  5 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum;
5 6 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO;
6 7 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
7 8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
... ... @@ -84,12 +85,10 @@ public class MesWmItemReceiptDO extends BaseDO {
84 85 * 入库日期
85 86 */
86 87 private LocalDateTime receiptDate;
87   - // TODO @AI:枚举类;需要 @关联
88   - // TODO @AI:字典类;需要 @关联
89 88 /**
90 89 * 状态
91 90 *
92   - * 0=草稿 1=已提交 2=已审批 3=已完成
  91 + * 枚举 {@link MesWmItemReceiptStatusEnum}
93 92 */
94 93 private Integer status;
95 94 /**
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmArrivalNoticeStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.wm;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * MES 到货通知单状态枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum MesWmArrivalNoticeStatusEnum implements ArrayValuable<Integer> {
  17 +
  18 + PREPARE(0, "草稿"),
  19 + SUBMITTED(1, "已提交"),
  20 + APPROVED(2, "已审批"),
  21 + FINISHED(3, "已完成");
  22 +
  23 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmArrivalNoticeStatusEnum::getStatus).toArray(Integer[]::new);
  24 +
  25 + /**
  26 + * 状态值
  27 + */
  28 + private final Integer status;
  29 + /**
  30 + * 状态名
  31 + */
  32 + private final String name;
  33 +
  34 + @Override
  35 + public Integer[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmItemReceiptStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.wm;
  2 +
  3 +import cn.iocoder.yudao.framework.common.core.ArrayValuable;
  4 +import lombok.AllArgsConstructor;
  5 +import lombok.Getter;
  6 +
  7 +import java.util.Arrays;
  8 +
  9 +/**
  10 + * MES 采购入库单状态枚举
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum MesWmItemReceiptStatusEnum implements ArrayValuable<Integer> {
  17 +
  18 + PREPARE(0, "草稿"),
  19 + SUBMITTED(1, "已提交"),
  20 + APPROVED(2, "已审批"),
  21 + FINISHED(3, "已完成");
  22 +
  23 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmItemReceiptStatusEnum::getStatus).toArray(Integer[]::new);
  24 +
  25 + /**
  26 + * 状态值
  27 + */
  28 + private final Integer status;
  29 + /**
  30 + * 状态名
  31 + */
  32 + private final String name;
  33 +
  34 + @Override
  35 + public Integer[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java
... ... @@ -51,7 +51,6 @@ public interface MesWmArrivalNoticeLineService {
51 51 */
52 52 PageResult<MesWmArrivalNoticeLineDO> getArrivalNoticeLinePage(MesWmArrivalNoticeLinePageReqVO pageReqVO);
53 53  
54   - // TODO @AI:不用的接口,就删除掉;
55 54 /**
56 55 * 按通知单编号获得行列表
57 56 *
... ... @@ -60,4 +59,11 @@ public interface MesWmArrivalNoticeLineService {
60 59 */
61 60 List<MesWmArrivalNoticeLineDO> getArrivalNoticeLineListByNoticeId(Long noticeId);
62 61  
  62 + /**
  63 + * 按通知单编号批量删除行
  64 + *
  65 + * @param noticeId 通知单编号
  66 + */
  67 + void deleteArrivalNoticeLineByNoticeId(Long noticeId);
  68 +
63 69 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice;
2 2  
  3 +import cn.hutool.core.util.BooleanUtil;
  4 +import cn.hutool.core.util.ObjUtil;
3 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 7 import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLinePageReqVO;
6 8 import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.MesWmArrivalNoticeLineSaveReqVO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO;
7 10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO;
8 11 import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeLineMapper;
  12 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum;
9 13 import jakarta.annotation.Resource;
  14 +import org.springframework.context.annotation.Lazy;
10 15 import org.springframework.stereotype.Service;
11 16 import org.springframework.validation.annotation.Validated;
12 17  
13 18 import java.util.List;
14 19  
15 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
16   -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS;
  21 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
17 22  
18 23 /**
19 24 * MES 到货通知单行 Service 实现类
... ... @@ -25,15 +30,19 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine
25 30 @Resource
26 31 private MesWmArrivalNoticeLineMapper arrivalNoticeLineMapper;
27 32  
  33 + @Resource
  34 + @Lazy
  35 + private MesWmArrivalNoticeService arrivalNoticeService;
  36 +
28 37 @Override
29 38 public Long createArrivalNoticeLine(MesWmArrivalNoticeLineSaveReqVO createReqVO) {
30   - // TODO @AI:关联表的校验;
  39 + // 校验父单据存在且为草稿状态
  40 + validateNoticeStatusDraft(createReqVO.getNoticeId());
31 41  
32 42 // 插入
33 43 MesWmArrivalNoticeLineDO line = BeanUtils.toBean(createReqVO, MesWmArrivalNoticeLineDO.class);
34 44 // 如果不需要检验,则合格品数量直接等于到货数量
35   - // TODO @AI:isFalase,减少反向判断;
36   - if (!Boolean.TRUE.equals(line.getIqcCheckFlag())) {
  45 + if (BooleanUtil.isFalse(line.getIqcCheckFlag())) {
37 46 line.setQualifiedQuantity(line.getArrivalQuantity());
38 47 }
39 48 arrivalNoticeLineMapper.insert(line);
... ... @@ -43,14 +52,14 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine
43 52 @Override
44 53 public void updateArrivalNoticeLine(MesWmArrivalNoticeLineSaveReqVO updateReqVO) {
45 54 // 校验存在
46   - validateArrivalNoticeLineExists(updateReqVO.getId());
47   - // TODO @AI:关联表的校验;
  55 + MesWmArrivalNoticeLineDO line = validateArrivalNoticeLineExists(updateReqVO.getId());
  56 + // 校验父单据存在且为草稿状态
  57 + validateNoticeStatusDraft(line.getNoticeId());
48 58  
49 59 // 更新
50 60 MesWmArrivalNoticeLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmArrivalNoticeLineDO.class);
51 61 // 如果不需要检验,则合格品数量直接等于到货数量
52   - // TODO @AI:isFalase,减少反向判断;
53   - if (!Boolean.TRUE.equals(updateObj.getIqcCheckFlag())) {
  62 + if (BooleanUtil.isFalse(updateObj.getIqcCheckFlag())) {
54 63 updateObj.setQualifiedQuantity(updateObj.getArrivalQuantity());
55 64 }
56 65 arrivalNoticeLineMapper.updateById(updateObj);
... ... @@ -79,10 +88,30 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine
79 88 return arrivalNoticeLineMapper.selectListByNoticeId(noticeId);
80 89 }
81 90  
82   - private void validateArrivalNoticeLineExists(Long id) {
83   - if (arrivalNoticeLineMapper.selectById(id) == null) {
  91 + @Override
  92 + public void deleteArrivalNoticeLineByNoticeId(Long noticeId) {
  93 + arrivalNoticeLineMapper.deleteByNoticeId(noticeId);
  94 + }
  95 +
  96 + private MesWmArrivalNoticeLineDO validateArrivalNoticeLineExists(Long id) {
  97 + MesWmArrivalNoticeLineDO line = arrivalNoticeLineMapper.selectById(id);
  98 + if (line == null) {
84 99 throw exception(WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS);
85 100 }
  101 + return line;
  102 + }
  103 +
  104 + /**
  105 + * 校验父到货通知单存在且为草稿状态
  106 + */
  107 + private void validateNoticeStatusDraft(Long noticeId) {
  108 + MesWmArrivalNoticeDO notice = arrivalNoticeService.getArrivalNotice(noticeId);
  109 + if (notice == null) {
  110 + throw exception(WM_ARRIVAL_NOTICE_NOT_EXISTS);
  111 + }
  112 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus(), notice.getStatus())) {
  113 + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE);
  114 + }
86 115 }
87 116  
88 117 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java
... ... @@ -55,23 +55,22 @@ public interface MesWmArrivalNoticeService {
55 55 */
56 56 PageResult<MesWmArrivalNoticeDO> getArrivalNoticePage(MesWmArrivalNoticePageReqVO pageReqVO);
57 57  
58   - // TODO @AI:0-》1、1-》2 尽量写状态;不要写这种;
59 58 /**
60   - * 提交到货通知单(0→1)
  59 + * 提交到货通知单(草稿 → 已提交)
61 60 *
62 61 * @param id 编号
63 62 */
64 63 void submitArrivalNotice(Long id);
65 64  
66 65 /**
67   - * 审批到货通知单(1→2)
  66 + * 审批到货通知单(已提交 → 已审批)
68 67 *
69 68 * @param id 编号
70 69 */
71 70 void approveArrivalNotice(Long id);
72 71  
73 72 /**
74   - * 完成到货通知单(→3),内部调用
  73 + * 完成到货通知单(已审批 → 已完成),内部调用
75 74 *
76 75 * @param id 编号
77 76 */
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.wm.arrivalnotice;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
4 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
5 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 8 import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticePageReqVO;
7 9 import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticeSaveReqVO;
8 10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO;
9 11 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO;
10   -import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeLineMapper;
11 12 import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeMapper;
  13 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum;
12 14 import jakarta.annotation.Resource;
13 15 import org.springframework.stereotype.Service;
14 16 import org.springframework.transaction.annotation.Transactional;
... ... @@ -31,36 +33,27 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
31 33 @Resource
32 34 private MesWmArrivalNoticeMapper arrivalNoticeMapper;
33 35  
34   - // TODO @AI:不允许调用对方的,调用 service;
35 36 @Resource
36   - private MesWmArrivalNoticeLineMapper arrivalNoticeLineMapper;
  37 + private MesWmArrivalNoticeLineService arrivalNoticeLineService;
37 38  
38 39 @Override
39 40 public Long createArrivalNotice(MesWmArrivalNoticeSaveReqVO createReqVO) {
40 41 // 校验编码唯一
41 42 validateCodeUnique(null, createReqVO.getCode());
42   - // TODO @AI:关联数据的校验
43 43  
44 44 // 插入
45 45 MesWmArrivalNoticeDO notice = BeanUtils.toBean(createReqVO, MesWmArrivalNoticeDO.class);
46   - // TODO @AI:使用枚举类;
47   - notice.setStatus(0); // 草稿
  46 + notice.setStatus(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus());
48 47 arrivalNoticeMapper.insert(notice);
49 48 return notice.getId();
50 49 }
51 50  
52 51 @Override
53 52 public void updateArrivalNotice(MesWmArrivalNoticeSaveReqVO updateReqVO) {
54   - // 校验存在
55   - MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(updateReqVO.getId());
56   - // 校验状态:只有草稿才允许修改
57   - // TODO @AI:使用枚举类;
58   - if (notice.getStatus() != 0) {
59   - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE);
60   - }
  53 + // 校验存在 + 草稿状态
  54 + validateArrivalNoticeExistsAndDraft(updateReqVO.getId());
61 55 // 校验编码唯一
62 56 validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
63   - // TODO @AI:关联数据的校验
64 57  
65 58 // 更新
66 59 MesWmArrivalNoticeDO updateObj = BeanUtils.toBean(updateReqVO, MesWmArrivalNoticeDO.class);
... ... @@ -70,16 +63,11 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
70 63 @Override
71 64 @Transactional(rollbackFor = Exception.class)
72 65 public void deleteArrivalNotice(Long id) {
73   - // 校验存在
74   - MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
75   - // 校验状态:只有草稿才允许删除 TODO @AI:抽个统一的校验+ 存在 “草稿”的方法,允许修改、删除
76   - // TODO @AI:使用枚举类;
77   - if (notice.getStatus() != 0) {
78   - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE);
79   - }
  66 + // 校验存在 + 草稿状态
  67 + validateArrivalNoticeExistsAndDraft(id);
80 68  
81 69 // 级联删除行
82   - arrivalNoticeLineMapper.deleteByNoticeId(id);
  70 + arrivalNoticeLineService.deleteArrivalNoticeLineByNoticeId(id);
83 71 // 删除
84 72 arrivalNoticeMapper.deleteById(id);
85 73 }
... ... @@ -95,56 +83,63 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
95 83 }
96 84  
97 85 @Override
  86 + @Transactional(rollbackFor = Exception.class)
98 87 public void submitArrivalNotice(Long id) {
99   - // 校验存在
100   - MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
101   - if (notice.getStatus() != 0) { // TODO @AI:抽个统一的校验+ 存在 “草稿”的方法,允许修改、删除
102   - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE);
  88 + // 1.1 校验存在 + 草稿状态
  89 + validateArrivalNoticeExistsAndDraft(id);
  90 + // 1.2 检查是否有行项目
  91 + List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id);
  92 + if (CollUtil.isEmpty(lines)) {
  93 + throw exception(WM_ARRIVAL_NOTICE_NO_LINE);
103 94 }
104 95  
105   - // 检查是否有行项目
106   - // TODO @AI:搞个 count 方法,在对方 service,传递 noticeId + 状态
107   - List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineMapper.selectListByNoticeId(id);
108 96 // 检查所有行的 iqcCheckFlag:如果没有需要检验的行,则直接审批通过
109   - boolean needCheck = lines.stream().anyMatch(line -> Boolean.TRUE.equals(line.getIqcCheckFlag()));
110   - // TODO @AI:计算 status,然后去更新;
  97 + boolean needCheck = CollectionUtils.anyMatch(lines, line -> Boolean.TRUE.equals(line.getIqcCheckFlag()));
111 98 if (!needCheck) {
112 99 // 不需要检验,直接审批通过
113   - arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO().setId(id).setStatus(2));
  100 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
  101 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.APPROVED.getStatus()));
114 102 } else {
115 103 // 需要检验,提交待审批
116   - arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO().setId(id).setStatus(1));
  104 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
  105 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.SUBMITTED.getStatus()));
117 106 }
118 107 }
119 108  
120 109 @Override
  110 + @Transactional(rollbackFor = Exception.class)
121 111 public void approveArrivalNotice(Long id) {
122 112 // 校验存在
123 113 MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
124   - if (notice.getStatus() != 1) {
125   - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE);
  114 + // 校验状态:只有已提交才允许审批
  115 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.SUBMITTED.getStatus(), notice.getStatus())) {
  116 + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_SUBMITTED);
126 117 }
127   - // TODO @AI:校验状态 + 状态;
128 118  
129 119 // 校验所有 iqcCheckFlag=true 的行必须 iqcId 不为空
130   - // TODO @AI:对方 service ;搞个 count 方法,在对方 service,传递 noticeId + 状态;另外,看看能不能和上面的,保持 service 方法,保持统一;
131   - List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineMapper.selectListByNoticeId(id);
132   - boolean hasUnchecked = lines.stream()
133   - .anyMatch(line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null);
  120 + List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id);
  121 + boolean hasUnchecked = CollectionUtils.anyMatch(lines,
  122 + line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null);
134 123 if (hasUnchecked) {
135 124 throw exception(WM_ARRIVAL_NOTICE_IQC_PENDING);
136 125 }
137 126 // 审批通过
138   - arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO().setId(id).setStatus(2));
  127 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
  128 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.APPROVED.getStatus()));
139 129 }
140 130  
141 131 @Override
142 132 public void finishArrivalNotice(Long id) {
143   - validateArrivalNoticeExists(id);
144   - // TODO @AI:校验状态 + 状态;
  133 + // 校验存在
  134 + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
  135 + // 校验状态:只有已审批才允许完成
  136 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.APPROVED.getStatus(), notice.getStatus())) {
  137 + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_APPROVED);
  138 + }
145 139  
146 140 // 完成
147   - arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO().setId(id).setStatus(3));
  141 + arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO()
  142 + .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.FINISHED.getStatus()));
148 143 }
149 144  
150 145 @Override
... ... @@ -163,13 +158,23 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService
163 158 return notice;
164 159 }
165 160  
  161 + /**
  162 + * 校验到货通知单存在且为草稿状态
  163 + */
  164 + private MesWmArrivalNoticeDO validateArrivalNoticeExistsAndDraft(Long id) {
  165 + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id);
  166 + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PREPARE.getStatus(), notice.getStatus())) {
  167 + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PREPARE);
  168 + }
  169 + return notice;
  170 + }
  171 +
166 172 private void validateCodeUnique(Long id, String code) {
167 173 MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectByCode(code);
168 174 if (notice == null) {
169 175 return;
170 176 }
171   - // TODO @AI:notEquals
172   - if (id == null || !id.equals(notice.getId())) {
  177 + if (ObjUtil.notEqual(id, notice.getId())) {
173 178 throw exception(WM_ARRIVAL_NOTICE_CODE_DUPLICATE);
174 179 }
175 180 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailService.java
... ... @@ -52,6 +52,14 @@ public interface MesWmItemReceiptDetailService {
52 52 PageResult<MesWmItemReceiptDetailDO> getItemReceiptDetailPage(MesWmItemReceiptDetailPageReqVO pageReqVO);
53 53  
54 54 /**
  55 + * 按入库单编号获得明细列表
  56 + *
  57 + * @param receiptId 入库单编号
  58 + * @return 明细列表
  59 + */
  60 + List<MesWmItemReceiptDetailDO> getItemReceiptDetailListByReceiptId(Long receiptId);
  61 +
  62 + /**
55 63 * 按入库单行编号获得明细列表
56 64 *
57 65 * @param lineId 行编号
... ... @@ -59,4 +67,18 @@ public interface MesWmItemReceiptDetailService {
59 67 */
60 68 List<MesWmItemReceiptDetailDO> getItemReceiptDetailListByLineId(Long lineId);
61 69  
  70 + /**
  71 + * 按入库单行编号批量删除明细
  72 + *
  73 + * @param lineId 行编号
  74 + */
  75 + void deleteItemReceiptDetailByLineId(Long lineId);
  76 +
  77 + /**
  78 + * 按入库单编号批量删除明细
  79 + *
  80 + * @param receiptId 入库单编号
  81 + */
  82 + void deleteItemReceiptDetailByReceiptId(Long receiptId);
  83 +
62 84 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptDetailServiceImpl.java
... ... @@ -4,16 +4,20 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 5 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailPageReqVO;
6 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.detail.MesWmItemReceiptDetailSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO;
7 8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO;
8 9 import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptDetailMapper;
  10 +import cn.hutool.core.util.ObjUtil;
  11 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum;
9 12 import jakarta.annotation.Resource;
  13 +import org.springframework.context.annotation.Lazy;
10 14 import org.springframework.stereotype.Service;
11 15 import org.springframework.validation.annotation.Validated;
12 16  
13 17 import java.util.List;
14 18  
15 19 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
16   -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS;
  20 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
17 21  
18 22 /**
19 23 * MES 采购入库明细 Service 实现类
... ... @@ -25,9 +29,15 @@ public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetail
25 29 @Resource
26 30 private MesWmItemReceiptDetailMapper itemReceiptDetailMapper;
27 31  
  32 + @Resource
  33 + @Lazy
  34 + private MesWmItemReceiptService itemReceiptService;
  35 +
28 36 @Override
29 37 public Long createItemReceiptDetail(MesWmItemReceiptDetailSaveReqVO createReqVO) {
30   - // TODO @AI:校验关联字段;
  38 + // 校验父单据存在且为草稿状态
  39 + validateReceiptStatusDraft(createReqVO.getReceiptId());
  40 +
31 41 MesWmItemReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmItemReceiptDetailDO.class);
32 42 itemReceiptDetailMapper.insert(detail);
33 43 return detail.getId();
... ... @@ -36,8 +46,9 @@ public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetail
36 46 @Override
37 47 public void updateItemReceiptDetail(MesWmItemReceiptDetailSaveReqVO updateReqVO) {
38 48 // 校验存在
39   - validateItemReceiptDetailExists(updateReqVO.getId());
40   - // TODO @AI:校验关联字段;
  49 + MesWmItemReceiptDetailDO detail = validateItemReceiptDetailExists(updateReqVO.getId());
  50 + // 校验父单据存在且为草稿状态
  51 + validateReceiptStatusDraft(detail.getReceiptId());
41 52  
42 53 // 更新
43 54 MesWmItemReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptDetailDO.class);
... ... @@ -63,14 +74,44 @@ public class MesWmItemReceiptDetailServiceImpl implements MesWmItemReceiptDetail
63 74 }
64 75  
65 76 @Override
  77 + public List<MesWmItemReceiptDetailDO> getItemReceiptDetailListByReceiptId(Long receiptId) {
  78 + return itemReceiptDetailMapper.selectListByReceiptId(receiptId);
  79 + }
  80 +
  81 + @Override
66 82 public List<MesWmItemReceiptDetailDO> getItemReceiptDetailListByLineId(Long lineId) {
67 83 return itemReceiptDetailMapper.selectListByLineId(lineId);
68 84 }
69 85  
70   - private void validateItemReceiptDetailExists(Long id) {
71   - if (itemReceiptDetailMapper.selectById(id) == null) {
  86 + @Override
  87 + public void deleteItemReceiptDetailByLineId(Long lineId) {
  88 + itemReceiptDetailMapper.deleteByLineId(lineId);
  89 + }
  90 +
  91 + @Override
  92 + public void deleteItemReceiptDetailByReceiptId(Long receiptId) {
  93 + itemReceiptDetailMapper.deleteByReceiptId(receiptId);
  94 + }
  95 +
  96 + private MesWmItemReceiptDetailDO validateItemReceiptDetailExists(Long id) {
  97 + MesWmItemReceiptDetailDO detail = itemReceiptDetailMapper.selectById(id);
  98 + if (detail == null) {
72 99 throw exception(WM_ITEM_RECEIPT_DETAIL_NOT_EXISTS);
73 100 }
  101 + return detail;
  102 + }
  103 +
  104 + /**
  105 + * 校验父采购入库单存在且为草稿状态
  106 + */
  107 + private void validateReceiptStatusDraft(Long receiptId) {
  108 + MesWmItemReceiptDO receipt = itemReceiptService.getItemReceipt(receiptId);
  109 + if (receipt == null) {
  110 + throw exception(WM_ITEM_RECEIPT_NOT_EXISTS);
  111 + }
  112 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) {
  113 + throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
  114 + }
74 115 }
75 116  
76 117 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineService.java
... ... @@ -59,4 +59,11 @@ public interface MesWmItemReceiptLineService {
59 59 */
60 60 List<MesWmItemReceiptLineDO> getItemReceiptLineListByReceiptId(Long receiptId);
61 61  
  62 + /**
  63 + * 按入库单编号批量删除行
  64 + *
  65 + * @param receiptId 入库单编号
  66 + */
  67 + void deleteItemReceiptLineByReceiptId(Long receiptId);
  68 +
62 69 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptLineServiceImpl.java
... ... @@ -4,10 +4,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 5 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLinePageReqVO;
6 6 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO;
7 8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO;
8   -import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptDetailMapper;
9 9 import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptLineMapper;
  10 +import cn.hutool.core.util.ObjUtil;
  11 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum;
10 12 import jakarta.annotation.Resource;
  13 +import org.springframework.context.annotation.Lazy;
11 14 import org.springframework.stereotype.Service;
12 15 import org.springframework.transaction.annotation.Transactional;
13 16 import org.springframework.validation.annotation.Validated;
... ... @@ -15,7 +18,7 @@ import org.springframework.validation.annotation.Validated;
15 18 import java.util.List;
16 19  
17 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
18   -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_ITEM_RECEIPT_LINE_NOT_EXISTS;
  21 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
19 22  
20 23 /**
21 24 * MES 采购入库单行 Service 实现类
... ... @@ -28,11 +31,16 @@ public class MesWmItemReceiptLineServiceImpl implements MesWmItemReceiptLineServ
28 31 private MesWmItemReceiptLineMapper itemReceiptLineMapper;
29 32  
30 33 @Resource
31   - private MesWmItemReceiptDetailMapper itemReceiptDetailMapper;
  34 + @Lazy
  35 + private MesWmItemReceiptService itemReceiptService;
  36 +
  37 + @Resource
  38 + private MesWmItemReceiptDetailService itemReceiptDetailService;
32 39  
33 40 @Override
34 41 public Long createItemReceiptLine(MesWmItemReceiptLineSaveReqVO createReqVO) {
35   - // TODO @AI:校验关联字段;
  42 + // 校验父单据存在且为草稿状态
  43 + validateReceiptStatusDraft(createReqVO.getReceiptId());
36 44  
37 45 // 新增
38 46 MesWmItemReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmItemReceiptLineDO.class);
... ... @@ -43,8 +51,9 @@ public class MesWmItemReceiptLineServiceImpl implements MesWmItemReceiptLineServ
43 51 @Override
44 52 public void updateItemReceiptLine(MesWmItemReceiptLineSaveReqVO updateReqVO) {
45 53 // 校验存在
46   - validateItemReceiptLineExists(updateReqVO.getId());
47   - // TODO @AI:校验关联字段;
  54 + MesWmItemReceiptLineDO line = validateItemReceiptLineExists(updateReqVO.getId());
  55 + // 校验父单据存在且为草稿状态
  56 + validateReceiptStatusDraft(line.getReceiptId());
48 57  
49 58 // 更新
50 59 MesWmItemReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmItemReceiptLineDO.class);
... ... @@ -58,7 +67,7 @@ public class MesWmItemReceiptLineServiceImpl implements MesWmItemReceiptLineServ
58 67 validateItemReceiptLineExists(id);
59 68  
60 69 // 级联删除明细
61   - itemReceiptDetailMapper.deleteByLineId(id);
  70 + itemReceiptDetailService.deleteItemReceiptDetailByLineId(id);
62 71 // 删除
63 72 itemReceiptLineMapper.deleteById(id);
64 73 }
... ... @@ -78,10 +87,30 @@ public class MesWmItemReceiptLineServiceImpl implements MesWmItemReceiptLineServ
78 87 return itemReceiptLineMapper.selectListByReceiptId(receiptId);
79 88 }
80 89  
81   - private void validateItemReceiptLineExists(Long id) {
82   - if (itemReceiptLineMapper.selectById(id) == null) {
  90 + @Override
  91 + public void deleteItemReceiptLineByReceiptId(Long receiptId) {
  92 + itemReceiptLineMapper.deleteByReceiptId(receiptId);
  93 + }
  94 +
  95 + private MesWmItemReceiptLineDO validateItemReceiptLineExists(Long id) {
  96 + MesWmItemReceiptLineDO line = itemReceiptLineMapper.selectById(id);
  97 + if (line == null) {
83 98 throw exception(WM_ITEM_RECEIPT_LINE_NOT_EXISTS);
84 99 }
  100 + return line;
  101 + }
  102 +
  103 + /**
  104 + * 校验父采购入库单存在且为草稿状态
  105 + */
  106 + private void validateReceiptStatusDraft(Long receiptId) {
  107 + MesWmItemReceiptDO receipt = itemReceiptService.getItemReceipt(receiptId);
  108 + if (receipt == null) {
  109 + throw exception(WM_ITEM_RECEIPT_NOT_EXISTS);
  110 + }
  111 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) {
  112 + throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
  113 + }
85 114 }
86 115  
87 116 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java
... ... @@ -49,25 +49,22 @@ public interface MesWmItemReceiptService {
49 49 */
50 50 PageResult<MesWmItemReceiptDO> getItemReceiptPage(MesWmItemReceiptPageReqVO pageReqVO);
51 51  
52   - // TODO @AI:0-》1、1-》2 尽量写状态;不要写这种;
53 52 /**
54   - * 提交采购入库单(0→1)
  53 + * 提交采购入库单(草稿 → 已提交)
55 54 *
56 55 * @param id 编号
57 56 */
58 57 void submitItemReceipt(Long id);
59 58  
60   - // TODO @AI:0-》1、1-》2 尽量写状态;不要写这种;
61 59 /**
62   - * 审批采购入库单(1→2)
  60 + * 审批采购入库单(已提交 → 已审批)
63 61 *
64 62 * @param id 编号
65 63 */
66 64 void approveItemReceipt(Long id);
67 65  
68   - // TODO @AI:0-》1、1-》2 尽量写状态;不要写这种;
69 66 /**
70   - * 执行入库(2→3),更新库存台账
  67 + * 执行入库(已审批 → 已完成),更新库存台账
71 68 *
72 69 * @param id 编号
73 70 */
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.wm.itemreceipt;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
3 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 8 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO;
6 9 import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO;
7 10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO;
8 11 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO;
9 12 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO;
10   -import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptDetailMapper;
11   -import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptLineMapper;
12 13 import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper;
  14 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum;
13 15 import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService;
14 16 import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService;
15 17 import jakarta.annotation.Resource;
... ... @@ -35,10 +37,10 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
35 37 private MesWmItemReceiptMapper itemReceiptMapper;
36 38  
37 39 @Resource
38   - private MesWmItemReceiptLineMapper itemReceiptLineMapper;
  40 + private MesWmItemReceiptLineService itemReceiptLineService;
39 41  
40 42 @Resource
41   - private MesWmItemReceiptDetailMapper itemReceiptDetailMapper;
  43 + private MesWmItemReceiptDetailService itemReceiptDetailService;
42 44  
43 45 @Resource
44 46 @Lazy
... ... @@ -51,25 +53,18 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
51 53 public Long createItemReceipt(MesWmItemReceiptSaveReqVO createReqVO) {
52 54 // 校验编码唯一
53 55 validateCodeUnique(null, createReqVO.getCode());
54   - // TODO @AI:校验关联字段;
55 56  
56 57 // 插入
57 58 MesWmItemReceiptDO receipt = BeanUtils.toBean(createReqVO, MesWmItemReceiptDO.class);
58   - receipt.setStatus(0); // 草稿 TODO @AI:使用枚举类
  59 + receipt.setStatus(MesWmItemReceiptStatusEnum.PREPARE.getStatus());
59 60 itemReceiptMapper.insert(receipt);
60 61 return receipt.getId();
61 62 }
62 63  
63 64 @Override
64 65 public void updateItemReceipt(MesWmItemReceiptSaveReqVO updateReqVO) {
65   - // 校验存在
66   - MesWmItemReceiptDO receipt = validateItemReceiptExists(updateReqVO.getId());
67   - // TODO @AI:校验关联字段;
68   - // 校验状态:只有草稿才允许修改
69   - // TODO @AI:校验状态,看看抽个方法,尽量几个方法复用
70   - if (receipt.getStatus() != 0) {
71   - throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
72   - }
  66 + // 校验存在 + 草稿状态
  67 + validateItemReceiptExistsAndDraft(updateReqVO.getId());
73 68 // 校验编码唯一
74 69 validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
75 70  
... ... @@ -81,17 +76,12 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
81 76 @Override
82 77 @Transactional(rollbackFor = Exception.class)
83 78 public void deleteItemReceipt(Long id) {
84   - // 校验存在
85   - MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
86   - // 校验状态:只有草稿才允许删除
87   - // TODO @AI:校验状态,看看抽个方法,尽量几个方法复用
88   - if (receipt.getStatus() != 0) {
89   - throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
90   - }
  79 + // 校验存在 + 草稿状态
  80 + validateItemReceiptExistsAndDraft(id);
91 81  
92 82 // 级联删除明细和行
93   - itemReceiptDetailMapper.deleteByReceiptId(id);
94   - itemReceiptLineMapper.deleteByReceiptId(id);
  83 + itemReceiptDetailService.deleteItemReceiptDetailByReceiptId(id);
  84 + itemReceiptLineService.deleteItemReceiptLineByReceiptId(id);
95 85 // 删除
96 86 itemReceiptMapper.deleteById(id);
97 87 }
... ... @@ -107,47 +97,43 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
107 97 }
108 98  
109 99 @Override
  100 + @Transactional(rollbackFor = Exception.class)
110 101 public void submitItemReceipt(Long id) {
111   - // 校验存在
112   - MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
113   - // TODO @AI:校验状态,看看抽个方法,尽量几个方法复用
114   - if (receipt.getStatus() != 0) {
115   - throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
116   - }
  102 + // 校验存在 + 草稿状态
  103 + validateItemReceiptExistsAndDraft(id);
117 104 // 校验至少有一条行
118   - // TODO @AI:对方抽个计算数量的方法啊;
119   - List<MesWmItemReceiptLineDO> lines = itemReceiptLineMapper.selectListByReceiptId(id);
120   - if (lines.isEmpty()) {
  105 + List<MesWmItemReceiptLineDO> lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(id);
  106 + if (CollUtil.isEmpty(lines)) {
121 107 throw exception(WM_ITEM_RECEIPT_NO_LINE);
122 108 }
123 109  
124 110 // 提交
125   - itemReceiptMapper.updateById(new MesWmItemReceiptDO().setId(id).setStatus(1));
  111 + itemReceiptMapper.updateById(new MesWmItemReceiptDO()
  112 + .setId(id).setStatus(MesWmItemReceiptStatusEnum.SUBMITTED.getStatus()));
126 113 }
127 114  
128 115 @Override
  116 + @Transactional(rollbackFor = Exception.class)
129 117 public void approveItemReceipt(Long id) {
130 118 // 校验存在
131 119 MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
132   - // TODO @AI:抽一些校验的存在+状态方法
133   - if (receipt.getStatus() != 1) {
  120 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.SUBMITTED.getStatus(), receipt.getStatus())) {
134 121 throw exception(WM_ITEM_RECEIPT_STATUS_ERROR);
135 122 }
136 123 // 校验每行的 SUM(detail.quantity) = line.receivedQuantity
137   - // TODO @AI:抽个计算的 count 方法,然后在行和明细都用;不然代码里到处都是计算的逻辑;
138   - List<MesWmItemReceiptLineDO> lines = itemReceiptLineMapper.selectListByReceiptId(id);
  124 + List<MesWmItemReceiptLineDO> lines = itemReceiptLineService.getItemReceiptLineListByReceiptId(id);
139 125 for (MesWmItemReceiptLineDO line : lines) {
140   - List<MesWmItemReceiptDetailDO> details = itemReceiptDetailMapper.selectListByLineId(line.getId());
141   - BigDecimal totalDetailQty = details.stream()
142   - .map(MesWmItemReceiptDetailDO::getQuantity)
143   - .reduce(BigDecimal.ZERO, BigDecimal::add);
  126 + List<MesWmItemReceiptDetailDO> details = itemReceiptDetailService.getItemReceiptDetailListByLineId(line.getId());
  127 + BigDecimal totalDetailQty = CollectionUtils.getSumValue(details,
  128 + MesWmItemReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO);
144 129 if (line.getReceivedQuantity() != null && totalDetailQty.compareTo(line.getReceivedQuantity()) != 0) {
145 130 throw exception(WM_ITEM_RECEIPT_DETAIL_QUANTITY_MISMATCH);
146 131 }
147 132 }
148 133  
149 134 // 审批
150   - itemReceiptMapper.updateById(new MesWmItemReceiptDO().setId(id).setStatus(2));
  135 + itemReceiptMapper.updateById(new MesWmItemReceiptDO()
  136 + .setId(id).setStatus(MesWmItemReceiptStatusEnum.APPROVED.getStatus()));
151 137 }
152 138  
153 139 @Override
... ... @@ -155,14 +141,12 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
155 141 public void executeItemReceipt(Long id) {
156 142 // 校验存在
157 143 MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
158   - // TODO @AI:抽一些校验的存在+状态方法
159   - if (receipt.getStatus() != 2) {
  144 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.APPROVED.getStatus(), receipt.getStatus())) {
160 145 throw exception(WM_ITEM_RECEIPT_STATUS_ERROR);
161 146 }
162 147  
163 148 // 遍历所有明细,更新库存台账
164   - // TODO @AI:select 方法,对方搞个;
165   - List<MesWmItemReceiptDetailDO> details = itemReceiptDetailMapper.selectListByReceiptId(id);
  149 + List<MesWmItemReceiptDetailDO> details = itemReceiptDetailService.getItemReceiptDetailListByReceiptId(id);
166 150 for (MesWmItemReceiptDetailDO detail : details) {
167 151 materialStockService.increaseStock(
168 152 detail.getItemId(), detail.getWarehouseId(), detail.getLocationId(), detail.getAreaId(),
... ... @@ -170,8 +154,8 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
170 154 }
171 155  
172 156 // 更新入库单状态
173   - // TODO @AI:枚举类;
174   - itemReceiptMapper.updateById(new MesWmItemReceiptDO().setId(id).setStatus(3));
  157 + itemReceiptMapper.updateById(new MesWmItemReceiptDO()
  158 + .setId(id).setStatus(MesWmItemReceiptStatusEnum.FINISHED.getStatus()));
175 159 // 更新关联的到货通知单状态
176 160 if (receipt.getNoticeId() != null) {
177 161 arrivalNoticeService.finishArrivalNotice(receipt.getNoticeId());
... ... @@ -186,13 +170,23 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService {
186 170 return receipt;
187 171 }
188 172  
  173 + /**
  174 + * 校验采购入库单存在且为草稿状态
  175 + */
  176 + private MesWmItemReceiptDO validateItemReceiptExistsAndDraft(Long id) {
  177 + MesWmItemReceiptDO receipt = validateItemReceiptExists(id);
  178 + if (ObjUtil.notEqual(MesWmItemReceiptStatusEnum.PREPARE.getStatus(), receipt.getStatus())) {
  179 + throw exception(WM_ITEM_RECEIPT_STATUS_NOT_PREPARE);
  180 + }
  181 + return receipt;
  182 + }
  183 +
189 184 private void validateCodeUnique(Long id, String code) {
190 185 MesWmItemReceiptDO receipt = itemReceiptMapper.selectByCode(code);
191 186 if (receipt == null) {
192 187 return;
193 188 }
194   - // TODO @AI:ObjUtil notEquals
195   - if (id == null || !id.equals(receipt.getId())) {
  189 + if (ObjUtil.notEqual(id, receipt.getId())) {
196 190 throw exception(WM_ITEM_RECEIPT_CODE_DUPLICATE);
197 191 }
198 192 }
... ...