From 7d2bf8e36bc41427c5e0156a5cf684f72310b8e9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 23 Feb 2026 12:26:19 +0800 Subject: [PATCH] feat(mes): IQC 与到货通知单集成重构 --- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java | 13 +++++-------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java | 13 +++++-------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java | 9 --------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDO.java | 29 +++++++++++++++++------------ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java | 5 +---- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java | 40 ++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java | 37 +++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkorderSourceTypeEnum.java | 37 ------------------------------------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java | 39 +++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java | 9 +++++---- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java | 42 +++++++++++++++++++++++++++++++++++------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java | 10 ++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java | 32 +++++++++++++++++++++++--------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java | 10 +++++++--- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java | 22 ++++++++++++++-------- 15 files changed, 238 insertions(+), 109 deletions(-) create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java delete mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkorderSourceTypeEnum.java create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java index 60c34a2..00559c5 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java @@ -33,11 +33,8 @@ public class MesQcIqcRespVO { @Schema(description = "来源单据 ID", example = "200") private Long sourceDocId; - @Schema(description = "来源单据类型", example = "ARRIVAL") - private String sourceDocType; - - @Schema(description = "来源单据编号", example = "ARV20250101001") - private String sourceDocCode; + @Schema(description = "来源单据类型", example = "100") + private Integer sourceDocType; @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; @@ -87,15 +84,15 @@ public class MesQcIqcRespVO { @Schema(description = "本次检测数量", example = "10") @ExcelProperty("检测数量") - private Integer checkQuantity; + private BigDecimal checkQuantity; @Schema(description = "合格品数量", example = "9") @ExcelProperty("合格品数量") - private Integer qualifiedQuantity; + private BigDecimal qualifiedQuantity; @Schema(description = "不合格品数量", example = "1") @ExcelProperty("不合格品数量") - private Integer unqualifiedQuantity; + private BigDecimal unqualifiedQuantity; // ========== 缺陷统计 ========== diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java index 6050d9f..4cca5b7 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java @@ -32,11 +32,8 @@ public class MesQcIqcSaveReqVO { @Schema(description = "来源单据 ID", example = "200") private Long sourceDocId; - @Schema(description = "来源单据类型", example = "ARRIVAL") - private String sourceDocType; - - @Schema(description = "来源单据编号", example = "ARV20250101001") - private String sourceDocCode; + @Schema(description = "来源单据类型", example = "100") + private Integer sourceDocType; @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; @@ -69,13 +66,13 @@ public class MesQcIqcSaveReqVO { private BigDecimal receivedQuantity; @Schema(description = "本次检测数量", example = "10") - private Integer checkQuantity; + private BigDecimal checkQuantity; @Schema(description = "合格品数量", example = "9") - private Integer qualifiedQuantity; + private BigDecimal qualifiedQuantity; @Schema(description = "不合格品数量", example = "1") - private Integer unqualifiedQuantity; + private BigDecimal unqualifiedQuantity; // ========== 检验 ========== diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java index 059d11c..cece976 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java @@ -112,15 +112,6 @@ public class MesWmArrivalNoticeController { return success(true); } - @PutMapping("/approve") - @Operation(summary = "审批到货通知单") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:update')") - public CommonResult approveArrivalNotice(@RequestParam("id") Long id) { - arrivalNoticeService.approveArrivalNotice(id); - return success(true); - } - @GetMapping("/simple-list") @Operation(summary = "获得到货通知单精简列表") @Parameter(name = "status", description = "状态", example = "2") diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDO.java index a4ceffa..2dd4372 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDO.java @@ -4,6 +4,9 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -47,24 +50,26 @@ public class MesQcIqcDO extends BaseDO { */ private Long templateId; - // ========== 来源单据(TODO @芋艿:WM 模块迁移后接入) ========== + // ========== 来源单据 ========== /** - * 来源单据 ID - */ - private Long sourceDocId; - /** * 来源单据类型 * - * 字典 mes_qc_source_doc_type + * 枚举 {@link MesQcSourceDocTypeEnum} */ - private String sourceDocType; + private Integer sourceDocType; /** - * 来源单据编号 + * 来源单据 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link MesQcSourceDocTypeEnum#ARRIVAL_NOTICE} 时,关联 {@link MesWmArrivalNoticeDO#getId()} */ - private String sourceDocCode; + private Long sourceDocId; /** * 来源单据行 ID + * + * 关联:根据 {@link #sourceDocType} 不同: + * 1. {@link MesQcSourceDocTypeEnum#ARRIVAL_NOTICE} 时,关联 {@link MesWmArrivalNoticeLineDO#getId()} */ private Long sourceLineId; @@ -107,15 +112,15 @@ public class MesQcIqcDO extends BaseDO { /** * 本次检测数量 */ - private Integer checkQuantity; + private BigDecimal checkQuantity; /** * 合格品数量 */ - private Integer qualifiedQuantity; + private BigDecimal qualifiedQuantity; /** * 不合格品数量 */ - private Integer unqualifiedQuantity; + private BigDecimal unqualifiedQuantity; // ========== 缺陷统计 ========== diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java index e4640a0..6b896ff 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java @@ -36,8 +36,6 @@ public class MesWmMaterialStockDO extends BaseDO { */ @TableId private Long id; - // TODO DONE @AI:保留冗余字段。库存台账查询频繁,冗余存储可避免关联 item 表,提升查询性能 - // TODO @AI:还是不记录;因为它没有筛选的诉求;并且,它可以通过 itemId 间接获取;冗余存储反而增加了维护成本; /** * 物料分类编号 * @@ -50,8 +48,6 @@ public class MesWmMaterialStockDO extends BaseDO { * 关联 {@link MesMdItemDO#getId()} */ private Long itemId; - // TODO DONE @AI:保留冗余字段。库存台账查询频繁,冗余存储可避免关联 item 表,提升查询性能 - // TODO @AI:还是不记录;因为它没有筛选的诉求;并且,它可以通过 itemId 间接获取;冗余存储反而增加了维护成本; /** * 计量单位编号 * @@ -88,6 +84,7 @@ public class MesWmMaterialStockDO extends BaseDO { * 关联 {@link MesMdVendorDO#getId()} */ private Long vendorId; + // TODO @AI:这个字段,应该没有的。 /** * 生产工单编号 * diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java new file mode 100644 index 0000000..e249b06 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesBizTypeConstants.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.mes.enums; + +/** + * MES 业务类型常量 + * + * 集中管理业务类型枚举的编号,按业务域分段。 + * 各枚举类引用此处常量,避免硬编码数字。(也避免冲突!!!) + * + * @author 芋道源码 + */ +public final class MesBizTypeConstants { + + private MesBizTypeConstants() {} + + // ========== QC 质检模块 [1, 100) ========== + + public static final int QC_IQC = 1; // 来料检验:MesQcIqcDO + public static final int QC_IPQC = 2; // 过程检验:MesQcIpqcDO + public static final int QC_OQC = 3; // 出货检验:MesQcOqcDO + public static final int QC_RQC = 4; // 退货检验:MesQcRqcDO + + // ========== WM 仓库模块 [100, 200) ========== + + public static final int WM_ARRIVAL_NOTICE = 100; // 到货通知单:MesWmArrivalNoticeDO + // public static final int WM_OUTSOURCE_RECPT = 101; // TODO 外协入库单:未实现,占位 + + // ========== CAL 排班模块 [200, 300) ========== + + // TODO @芋艿【暂时忽略】:MesProWorkOrderTypeEnum + // TODO @芋艿【暂时忽略】:MesProWorkOrderSourceTypeEnum + + // ========== PRO 生产模块 [300, 400) ========== + + // ========== DV 设备模块 [400, 500) ========== + + // ========== TM 工装夹具模块 [500, 600) ========== + + // ========== MD 主数据模块 [600, 700) ========== + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java new file mode 100644 index 0000000..47836b7 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkOrderSourceTypeEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.pro; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 工单来源类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesProWorkOrderSourceTypeEnum implements ArrayValuable { + + ORDER(1, "客户订单"), + STORE(2, "库存备货"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkOrderSourceTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkorderSourceTypeEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkorderSourceTypeEnum.java deleted file mode 100644 index 47836b7..0000000 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProWorkorderSourceTypeEnum.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.mes.enums.pro; - -import cn.iocoder.yudao.framework.common.core.ArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * MES 工单来源类型枚举 - * - * @author 芋道源码 - */ -@Getter -@AllArgsConstructor -public enum MesProWorkOrderSourceTypeEnum implements ArrayValuable { - - ORDER(1, "客户订单"), - STORE(2, "库存备货"); - - public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProWorkOrderSourceTypeEnum::getType).toArray(Integer[]::new); - - /** - * 类型值 - */ - private final Integer type; - /** - * 类型名 - */ - private final String name; - - @Override - public Integer[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java new file mode 100644 index 0000000..db0ece1 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcSourceDocTypeEnum.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.mes.enums.qc; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 质检来源单据类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesQcSourceDocTypeEnum implements ArrayValuable { + + ARRIVAL_NOTICE(MesBizTypeConstants.WM_ARRIVAL_NOTICE, "到货通知单"), + // OUTSOURCE_RECPT(MesBizTypeConstants.WM_OUTSOURCE_RECPT, "外协入库单"), // TODO 未实现,占位 + ; + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcSourceDocTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java index c5af747..c47c1ba 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.enums.qc; import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import lombok.AllArgsConstructor; import lombok.Getter; @@ -15,10 +16,10 @@ import java.util.Arrays; @AllArgsConstructor public enum MesQcTypeEnum implements ArrayValuable { - IQC(1, "来料检验"), - IPQC(2, "过程检验"), - OQC(3, "出货检验"), - RQC(4, "退货检验"); + IQC(MesBizTypeConstants.QC_IQC, "来料检验"), + IPQC(MesBizTypeConstants.QC_IPQC, "过程检验"), + OQC(MesBizTypeConstants.QC_OQC, "出货检验"), + RQC(MesBizTypeConstants.QC_RQC, "退货检验"); public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcTypeEnum::getType).toArray(Integer[]::new); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java index 3244379..b461982 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java @@ -11,11 +11,13 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper; +import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; import cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum; import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateService; +import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -48,6 +50,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { private MesQcIqcLineService iqcLineService; @Resource private MesQcDefectRecordService defectRecordService; + @Resource + private MesWmArrivalNoticeService arrivalNoticeService; @Override @Transactional(rollbackFor = Exception.class) @@ -99,10 +103,10 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { // 1.1 校验存在 + 草稿状态 MesQcIqcDO iqc = validateIqcStatusPrepare(id); // 1.2 校验合格品 + 不合格品 = 检测数量 - if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) { - int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0) - + (iqc.getUnqualifiedQuantity() != null ? iqc.getUnqualifiedQuantity() : 0); - if (total != iqc.getCheckQuantity()) { + if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal total = ObjUtil.defaultIfNull(iqc.getQualifiedQuantity(), BigDecimal.ZERO) + .add(ObjUtil.defaultIfNull(iqc.getUnqualifiedQuantity(), BigDecimal.ZERO)); + if (total.compareTo(iqc.getCheckQuantity()) != 0) { throw exception(QC_IQC_QUANTITY_MISMATCH); } } @@ -112,7 +116,31 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { .setId(id).setStatus(MesQcIqcStatusEnum.FINISHED.getType()); iqcMapper.updateById(updateObj); - // TODO @芋艿:WM 模块迁移后,更新到货通知单行/外协入库单行的检验结果 + // 3. 回写来源单据 + writeBackSourceDoc(iqc); + } + + /** + * 回写来源单据(IQC 完成后) + * + * @param iqc 来料检验单 + */ + private void writeBackSourceDoc(MesQcIqcDO iqc) { + // 校验:sourceDocType 非空时,lineId 和 docId 必须非空,否则为脏数据 + if (iqc.getSourceDocType() == null) { + return; + } + if (iqc.getSourceLineId() == null || iqc.getSourceDocId() == null) { + throw new IllegalArgumentException( + "IQC 单[" + iqc.getId() + "] sourceDocType 非空但 sourceLineId 或 sourceDocId 为空"); + } + + // 根据不同的来源单据类型,回写不同的单据 + if (Objects.equals(iqc.getSourceDocType(), MesBizTypeConstants.WM_ARRIVAL_NOTICE)) { + arrivalNoticeService.approveArrivalNoticeWhenIqcComplete(iqc.getSourceDocId(), iqc.getSourceLineId(), + iqc.getId(), iqc.getQualifiedQuantity()); + } + // TODO 外协入库单:未实现,占位 } @Override @@ -196,8 +224,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { BigDecimal criticalRate = BigDecimal.ZERO; BigDecimal majorRate = BigDecimal.ZERO; BigDecimal minorRate = BigDecimal.ZERO; - if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) { - BigDecimal checkQty = BigDecimal.valueOf(iqc.getCheckQuantity()); + if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + BigDecimal checkQty = iqc.getCheckQuantity(); criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100)) .divide(checkQty, 2, RoundingMode.HALF_UP); majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100)) diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java index f26f8f7..5cec701 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.line.Mes import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.List; /** @@ -66,4 +67,13 @@ public interface MesWmArrivalNoticeLineService { */ void deleteArrivalNoticeLineByNoticeId(Long noticeId); + /** + * IQC 检验完成后回写行数据 + * + * @param lineId 行编号 + * @param iqcId IQC 检验单编号 + * @param qualifiedQuantity 合格数量 + */ + void updateByIqcComplete(Long lineId, Long iqcId, BigDecimal qualifiedQuantity); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java index 5882d3c..aeea130 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java @@ -15,6 +15,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -41,11 +42,7 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine // 插入 MesWmArrivalNoticeLineDO line = BeanUtils.toBean(createReqVO, MesWmArrivalNoticeLineDO.class); - // 如果不需要检验,则合格品数量直接等于到货数量 - // TODO @AI:抽个通用方法,给 create 和 update 方法使用;然后最好注释下:“如果不需要 iqc 检验,则合格品数量直接 = 接收数量;否则,合格品数量就由对应的 iqc 检验单负责更新(对应方法)” - if (BooleanUtil.isFalse(line.getIqcCheckFlag())) { - line.setQualifiedQuantity(line.getArrivalQuantity()); - } + initQualifiedQuantityIfNoIqc(line); arrivalNoticeLineMapper.insert(line); return line.getId(); } @@ -59,13 +56,21 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine // 更新 MesWmArrivalNoticeLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmArrivalNoticeLineDO.class); - // 如果不需要检验,则合格品数量直接等于到货数量 - if (BooleanUtil.isFalse(updateObj.getIqcCheckFlag())) { - updateObj.setQualifiedQuantity(updateObj.getArrivalQuantity()); - } + initQualifiedQuantityIfNoIqc(updateObj); arrivalNoticeLineMapper.updateById(updateObj); } + /** + * 初始化合格品数量: + * 1. 如果不需要 IQC 检验,则合格品数量直接 = 接收数量; + * 2. 否则,合格品数量由对应的 IQC 检验单负责更新(见 {@link #updateByIqcComplete}) + */ + private void initQualifiedQuantityIfNoIqc(MesWmArrivalNoticeLineDO line) { + if (BooleanUtil.isFalse(line.getIqcCheckFlag())) { + line.setQualifiedQuantity(line.getArrivalQuantity()); + } + } + @Override public void deleteArrivalNoticeLine(Long id) { // 校验存在 @@ -94,6 +99,15 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine arrivalNoticeLineMapper.deleteByNoticeId(noticeId); } + @Override + public void updateByIqcComplete(Long lineId, Long iqcId, BigDecimal qualifiedQuantity) { + // 校验行存在 + validateArrivalNoticeLineExists(lineId); + // 更新 + arrivalNoticeLineMapper.updateById(new MesWmArrivalNoticeLineDO() + .setId(lineId).setIqcId(iqcId).setQualifiedQuantity(qualifiedQuantity)); + } + private MesWmArrivalNoticeLineDO validateArrivalNoticeLineExists(Long id) { MesWmArrivalNoticeLineDO line = arrivalNoticeLineMapper.selectById(id); if (line == null) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java index 0d939c3..201dffe 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArr import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; import java.util.Map; @@ -63,11 +64,14 @@ public interface MesWmArrivalNoticeService { void submitArrivalNotice(Long id); /** - * 审批到货通知单(待质检 → 待入库) + * IQC 检验完成后回写到货通知单(更新行 + 尝试推进主表状态) * - * @param id 编号 + * @param id 到货通知单编号 + * @param lineId 到货通知单行编号 + * @param iqcId IQC 检验单编号 + * @param qualifiedQuantity 合格数量 */ - void approveArrivalNotice(Long id); + void approveArrivalNoticeWhenIqcComplete(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity); /** * 完成到货通知单(待入库 → 已完成),内部调用 diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java index 42a4ba0..91a9252 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java @@ -12,10 +12,12 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalN import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -28,6 +30,7 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; */ @Service @Validated +@Slf4j public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService { @Resource @@ -107,25 +110,28 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService } } - // TODO DONE @AI:确认由 IQC 模块在检验完成后调用。前端审批按钮已移除,仅保留 Service 方法供内部调用 @Override @Transactional(rollbackFor = Exception.class) - public void approveArrivalNotice(Long id) { - // 1.1 校验存在 + public void approveArrivalNoticeWhenIqcComplete(Long id, Long lineId, Long iqcId, BigDecimal qualifiedQuantity) { + // 1.1 校验到货通知单存在 MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); - // 1.2 校验状态:只有待质检才允许审批 + // 1.2 校验状态为待质检 if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_QC.getStatus(), notice.getStatus())) { throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_QC); } - // 1.3 校验所有 iqcCheckFlag=true 的行必须 iqcId 不为空 + + // 2. 更新到货通知单行:绑定 iqcId + 合格数量 + arrivalNoticeLineService.updateByIqcComplete(lineId, iqcId, qualifiedQuantity); + + // 3.1 判断是否所有需检行都已完成 List lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); boolean hasUnchecked = CollectionUtils.anyMatch(lines, line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null); if (hasUnchecked) { - throw exception(WM_ARRIVAL_NOTICE_IQC_PENDING); + log.info("[updateWhenIqcComplete][到货通知单({}) 还有未完成检验的行,暂不更新状态]", id); + return; } - - // 2. 审批通过 + // 3.2 所有行检验完成,更新主表状态 PENDING_QC → PENDING_RECEIPT arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() .setId(id).setStatus(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus())); } -- libgit2 0.21.4