Commit dfeb3c104d48d1b8844c9850bf55c924f51e37ef

Authored by YunaiV
1 parent b31f78c8

✨ feat(mes): 更新销售出库单状态流转逻辑,添加 OQC 检验支持

优化销售出库单的状态流转逻辑,新增待检测状态以支持 OQC 检验。根据检验结果自动流转状态,提升出库流程的灵活性和准确性。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -533,7 +533,8 @@ public interface ErrorCodeConstants {
533 533 ErrorCode WM_PRODUCT_SALES_CANNOT_SHIPPING = new ErrorCode(1_040_714_006, "当前状态不允许填写运单");
534 534 ErrorCode WM_PRODUCT_SALES_CANNOT_FINISH = new ErrorCode(1_040_714_007, "当前状态不允许执行出库");
535 535 ErrorCode WM_PRODUCT_SALES_CANNOT_CANCEL = new ErrorCode(1_040_714_008, "当前状态不允许取消");
536   - ErrorCode WM_PRODUCT_SALES_DETAILS_EMPTY = new ErrorCode(1_040_714_009, "拣货明细不能为空");
  536 + ErrorCode WM_PRODUCT_SALES_CANNOT_CONFIRM = new ErrorCode(1_040_714_009, "当前状态不允许确认检验通过");
  537 + ErrorCode WM_PRODUCT_SALES_DETAILS_EMPTY = new ErrorCode(1_040_714_020, "拣货明细不能为空");
537 538 ErrorCode WM_PRODUCT_SALES_DETAIL_QUANTITY_MISMATCH = new ErrorCode(1_040_714_010, "拣货数量与出库数量不匹配");
538 539 ErrorCode WM_PRODUCT_SALES_LINE_NOT_EXISTS = new ErrorCode(1_040_714_011, "销售出库单行不存在");
539 540 ErrorCode WM_PRODUCT_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_714_012, "销售出库明细不存在");
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmProductSalesStatusEnum.java
... ... @@ -28,10 +28,18 @@ public enum MesWmProductSalesStatusEnum implements ArrayValuable<Integer> {
28 28 */
29 29 PREPARE(MesOrderStatusConstants.PREPARE, "草稿"),
30 30 /**
31   - * 待拣货
  31 + * 待检测(需要 OQC 检验时),对接 qc 模块的 MesQcOqcDO 后续流程
32 32 *
33 33 * 对应方法:{@link MesWmProductSalesService#submitProductSales(Long)}
34 34 */
  35 + CONFIRMED(MesOrderStatusConstants.CONFIRMED, "待检测"),
  36 + /**
  37 + * 待拣货
  38 + *
  39 + * 对应方法:
  40 + * 1. 不需要 OQC 检验时:{@link MesWmProductSalesService#submitProductSales(Long)}
  41 + * 2. 或 OQC 检验完成时:{@link MesWmProductSalesService#confirmProductSales(Long)}
  42 + */
35 43 APPROVING(MesOrderStatusConstants.APPROVING, "待拣货"),
36 44 /**
37 45 * 待填写运单
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java
... ... @@ -115,19 +115,30 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe
115 115 productSalesLineMapper.updateById(new MesWmProductSalesLineDO()
116 116 .setId(id).setOqcId(oqcId).setQualityStatus(qualityStatus));
117 117  
118   - // 2. 检查同一出库单下所有需要 OQC 检验的行的质检状态,联动更新出库单整体状态
  118 + // 2. 检查同一出库单下所有需要 OQC 检验的行
119 119 MesWmProductSalesLineDO currentLine = productSalesLineMapper.selectById(id);
120 120 if (currentLine == null || currentLine.getSalesId() == null) {
121 121 return;
122 122 }
123 123 Long salesId = currentLine.getSalesId();
124 124 List<MesWmProductSalesLineDO> allLines = productSalesLineMapper.selectListBySalesId(salesId);
  125 +
  126 + // 2.1 检查是否有不合格行 → 取消出库单
125 127 boolean hasNg = CollectionUtils.anyMatch(allLines,
126 128 line -> Boolean.TRUE.equals(line.getOqcCheckFlag())
127 129 && Objects.equals(line.getQualityStatus(), MesWmQualityStatusEnum.FAIL.getStatus()));
128 130 if (hasNg) {
129 131 log.info("[updateProductSalesLineWhenOqcFinish][销售出库单({}) 存在质检不合格行,取消出库单]", salesId);
130 132 productSalesService.cancelProductSales(salesId);
  133 + return;
  134 + }
  135 +
  136 + // 2.2 检查是否所有 OQC 行都已完成,自动流转 CONFIRMED → APPROVING
  137 + boolean hasUnchecked = CollectionUtils.anyMatch(allLines,
  138 + line -> Boolean.TRUE.equals(line.getOqcCheckFlag()) && line.getOqcId() == null);
  139 + if (!hasUnchecked) {
  140 + log.info("[updateProductSalesLineWhenOqcFinish][销售出库单({}) 所有 OQC 行检验完成,流转到待拣货]", salesId);
  141 + productSalesService.confirmProductSales(salesId);
131 142 }
132 143 }
133 144  
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java
... ... @@ -53,7 +53,11 @@ public interface MesWmProductSalesService {
53 53 PageResult<MesWmProductSalesDO> getProductSalesPage(MesWmProductSalesPageReqVO pageReqVO);
54 54  
55 55 /**
56   - * 提交销售出库单(草稿 → 待拣货)
  56 + * 提交销售出库单
  57 + * <ul>
  58 + * <li>有 OQC 检验行:草稿 → 待检测</li>
  59 + * <li>无 OQC 检验行:草稿 → 待拣货</li>
  60 + * </ul>
57 61 *
58 62 * @param id 编号
59 63 */
... ... @@ -95,4 +99,11 @@ public interface MesWmProductSalesService {
95 99 */
96 100 void cancelProductSales(Long id);
97 101  
  102 + /**
  103 + * OQC 检验完成后,自动流转(待检测 → 待拣货)
  104 + *
  105 + * @param id 编号
  106 + */
  107 + void confirmProductSales(Long id);
  108 +
98 109 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java
... ... @@ -117,7 +117,16 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService {
117 117 throw exception(WM_PRODUCT_SALES_LINES_EMPTY);
118 118 }
119 119  
120   - // 提交(草稿 → 待拣货)
  120 + // 检查所有行的 oqcCheckFlag:如果有需要 OQC 检验的行,进入待检测状态
  121 + boolean needOqc = CollectionUtils.anyMatch(lines,
  122 + line -> Boolean.TRUE.equals(line.getOqcCheckFlag()));
  123 + if (needOqc) {
  124 + // 需要检验,进入待检测
  125 + productSalesMapper.updateById(new MesWmProductSalesDO()
  126 + .setId(id).setStatus(MesWmProductSalesStatusEnum.CONFIRMED.getStatus()));
  127 + return;
  128 + }
  129 + // 不需要检验,直接进入待拣货
121 130 productSalesMapper.updateById(new MesWmProductSalesDO()
122 131 .setId(id).setStatus(MesWmProductSalesStatusEnum.APPROVING.getStatus()));
123 132 }
... ... @@ -215,6 +224,18 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService {
215 224 .setId(id).setStatus(MesWmProductSalesStatusEnum.CANCELED.getStatus()));
216 225 }
217 226  
  227 + @Override
  228 + public void confirmProductSales(Long id) {
  229 + // 校验存在 + 待检测状态
  230 + MesWmProductSalesDO sales = validateProductSalesExists(id);
  231 + if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.CONFIRMED.getStatus(), sales.getStatus())) {
  232 + throw exception(WM_PRODUCT_SALES_CANNOT_CONFIRM);
  233 + }
  234 + // OQC 检验完成,流转到待拣货
  235 + productSalesMapper.updateById(new MesWmProductSalesDO()
  236 + .setId(id).setStatus(MesWmProductSalesStatusEnum.APPROVING.getStatus()));
  237 + }
  238 +
218 239 private MesWmProductSalesDO validateProductSalesExists(Long id) {
219 240 MesWmProductSalesDO sales = productSalesMapper.selectById(id);
220 241 if (sales == null) {
... ...
yudao-module-mes/src/main/resources/mapper/qc/pendinginspect/MesQcPendingInspectMapper.xml
... ... @@ -4,12 +4,12 @@
4 4  
5 5 <!--
6 6 待检任务查询(UNION ALL 多来源),已实现的来源:
7   - 1. 到货通知单(IQC):单据状态=待质检(2),行的 iqc_check_flag=1 且 iqc_id 为空
8   - 2. 外协入库单(IQC):单据状态=待检验(1),行的 iqc_check_flag=1 且 iqc_id 为空
9   - 3. 生产报工(IPQC):单据状态=待检验(3)
10   - 4. 销售出库单(OQC):无单据状态要求,行的 oqc_check_flag=1 且 oqc_id 为空
11   - 5. 生产退料单(RQC):单据状态=待检验(1),行的 rqc_check_flag=1 且 rqc_id 为空 且 quality_status=0(待检)
12   - 6. 销售退货单(RQC):单据状态=待检验(1),行的 rqc_check_flag=1 且 rqc_id 为空 且 quality_status=0(待检)
  7 + 1. 到货通知单(IQC):单据状态=PENDING_QC(2),行的 iqc_check_flag=1 且 iqc_id 为空
  8 + 2. 外协入库单(IQC):单据状态=CONFIRMED(1),行的 iqc_check_flag=1 且 iqc_id 为空
  9 + 3. 生产报工(IPQC):单据状态=UNCHECK(3)
  10 + 4. 销售出库单(OQC):单据状态=CONFIRMED(1),行的 oqc_check_flag=1 且 oqc_id 为空
  11 + 5. 生产退料单(RQC):单据状态=CONFIRMED(1),行的 rqc_check_flag=1 且 rqc_id 为空 且 quality_status=0(待检)
  12 + 6. 销售退货单(RQC):单据状态=CONFIRMED(1),行的 rqc_check_flag=1 且 rqc_id 为空 且 quality_status=0(待检)
13 13 -->
14 14 <select id="selectQcPendingPage" resultType="cn.iocoder.yudao.module.mes.controller.admin.qc.pendinginspect.vo.MesQcPendingInspectRespVO">
15 15 SELECT * FROM (
... ... @@ -103,6 +103,7 @@
103 103 JOIN mes_wm_product_sales_line sl ON s.id = sl.sales_id
104 104 WHERE sl.oqc_check_flag = 1
105 105 AND sl.oqc_id IS NULL
  106 + AND s.status = ${@cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum@CONFIRMED.status}
106 107 AND s.deleted = 0
107 108 AND sl.deleted = 0
108 109  
... ...