liu
2026-10-24 3990ae574c221e3764ce9cbc2e4e3eb71b7b1b52
fix(mes): 修复批次正反向追溯链路
已修改2个文件
71 ■■■■■ 文件已修改
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/resources/mapper/wm/batch/MesWmBatchMapper.xml 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java
@@ -382,7 +382,22 @@
    @Override
    public List<MesWmBatchPurchaseSourceRespVO> getPurchaseSourceList(String code) {
        return batchMapper.selectPurchaseSourceList(code);
        // 成品批次本身通常没有采购入库记录,需要同时汇总所有上游原料批次的采购来源。
        List<String> batchCodes = new ArrayList<>();
        Set<String> visited = new HashSet<>();
        if (StrUtil.isNotBlank(code) && visited.add(code)) {
            batchCodes.add(code);
        }
        for (MesWmBatchDO batch : getBackwardBatchList(code)) {
            if (StrUtil.isNotBlank(batch.getCode()) && visited.add(batch.getCode())) {
                batchCodes.add(batch.getCode());
            }
        }
        List<MesWmBatchPurchaseSourceRespVO> result = new ArrayList<>();
        for (String batchCode : batchCodes) {
            result.addAll(batchMapper.selectPurchaseSourceList(batchCode));
        }
        return result;
    }
    @Override
yudao-module-mes/src/main/resources/mapper/wm/batch/MesWmBatchMapper.xml
@@ -10,37 +10,39 @@
    </resultMap>
    <!--
        向前追溯:从某个原材料批次出发,查找它被哪些工单消耗后,产出了哪些成品批次
        链路:库存事务(消耗 OUT, biz=123, biz_id=消耗单id) → 消耗单 → 报工 → 产出单(feedback_id) → 库存事务(产出 IN, biz=124, biz_id=产出单id) → 批次
        向前追溯:原料消耗明细 → 消耗单 → 产品产出单 → 产品产出行。
        新数据优先按 feedback_id 精确关联;历史/自动生成单据缺少 feedback_id 时,
        退化为同一 work_order_id 关联,保证已有生产数据也能形成批次链路。
    -->
    <select id="selectListByForward" parameterType="String" resultMap="BatchTraceResult">
        SELECT DISTINCT pf.work_order_id, pf.item_id, tx_produce.batch_id, tx_produce.batch_code
        FROM mes_wm_transaction tx_consume
        JOIN mes_wm_item_consume ic ON tx_consume.biz_id = ic.id AND tx_consume.biz_type = 123 AND ic.deleted = 0
        JOIN mes_pro_feedback pf ON pf.id = ic.feedback_id AND pf.deleted = 0
        JOIN mes_wm_product_produce pp ON pp.feedback_id = pf.id AND pp.deleted = 0
        JOIN mes_wm_transaction tx_produce ON tx_produce.biz_id = pp.id AND tx_produce.biz_type = 124 AND tx_produce.deleted = 0
        WHERE tx_consume.batch_code = #{batchCode}
        AND tx_consume.biz_type = 123
        AND tx_consume.deleted = 0
        AND tx_produce.batch_id IS NOT NULL
        SELECT DISTINCT pp.work_order_id, ppl.item_id, ppl.batch_id, ppl.batch_code
        FROM mes_wm_item_consume_detail icd
        JOIN mes_wm_item_consume ic ON ic.id = icd.consume_id AND ic.deleted = 0
        JOIN mes_wm_product_produce pp ON pp.deleted = 0 AND (
            (ic.feedback_id IS NOT NULL AND pp.feedback_id = ic.feedback_id)
            OR ((ic.feedback_id IS NULL OR pp.feedback_id IS NULL)
                AND pp.work_order_id = ic.work_order_id)
        )
        JOIN mes_wm_product_produce_line ppl ON ppl.produce_id = pp.id AND ppl.deleted = 0
        WHERE icd.batch_code = #{batchCode}
          AND icd.deleted = 0
          AND ppl.batch_id IS NOT NULL
    </select>
    <!--
        向后追溯:从某个成品批次出发,查找生产它时消耗了哪些原材料批次
        链路:库存事务(产出 IN, biz=124, biz_id=产出单id) → 产出单 → 报工 → 消耗单(feedback_id) → 库存事务(消耗 OUT, biz=123, biz_id=消耗单id) → 批次
    -->
    <!-- 向后追溯:产品产出行 → 产品产出单 → 消耗单 → 原料消耗明细。关联规则同向前追溯。 -->
    <select id="selectListByBackward" parameterType="String" resultMap="BatchTraceResult">
        SELECT DISTINCT ic.work_order_id, tx_consume.item_id, tx_consume.batch_id, tx_consume.batch_code
        FROM mes_wm_transaction tx_produce
        JOIN mes_wm_product_produce pp ON tx_produce.biz_id = pp.id AND tx_produce.biz_type = 124 AND pp.deleted = 0
        JOIN mes_pro_feedback pf ON pf.id = pp.feedback_id AND pf.deleted = 0
        JOIN mes_wm_item_consume ic ON ic.feedback_id = pf.id AND ic.deleted = 0
        JOIN mes_wm_transaction tx_consume ON tx_consume.biz_id = ic.id AND tx_consume.biz_type = 123 AND tx_consume.deleted = 0
        WHERE tx_produce.batch_code = #{batchCode}
        AND tx_produce.biz_type = 124
        AND tx_produce.deleted = 0
        AND tx_consume.batch_id IS NOT NULL
        SELECT DISTINCT ic.work_order_id, icd.item_id, icd.batch_id, icd.batch_code
        FROM mes_wm_product_produce_line ppl
        JOIN mes_wm_product_produce pp ON pp.id = ppl.produce_id AND pp.deleted = 0
        JOIN mes_wm_item_consume ic ON ic.deleted = 0 AND (
            (pp.feedback_id IS NOT NULL AND ic.feedback_id = pp.feedback_id)
            OR ((pp.feedback_id IS NULL OR ic.feedback_id IS NULL)
                AND ic.work_order_id = pp.work_order_id)
        )
        JOIN mes_wm_item_consume_detail icd ON icd.consume_id = ic.id AND icd.deleted = 0
        WHERE ppl.batch_code = #{batchCode}
          AND ppl.deleted = 0
          AND icd.batch_id IS NOT NULL
    </select>
    <!-- 批次采购来源:批次 → 采购入库行 → 采购入库单 → IQC -->