2 天以前 f7273277023f3497ac071bf98f556a569cb4dd25
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/trace/MesProTracePublicServiceImpl.java
@@ -2,6 +2,7 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchFlowRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO;
@@ -106,7 +107,7 @@
                throw exception(MES_TRACE_CODE_NOT_FOUND);
            }
            // 2. 聚合全程信息
            MesProTracePublicRespVO result = buildRespVO(rawCode, traceCode, entry.sourceType, entry.batchId);
            MesProTracePublicRespVO result = buildRespVO(rawCode, traceCode, entry.sourceType, entry.batchId, entry.bagItemId);
            recordConsumerScan(rawCode, traceCode, entry.sourceType, entry.batchId, true);
            return result;
        } catch (RuntimeException ex) {
@@ -166,24 +167,24 @@
        // ① 袋码
        MesProBagCodeDO bag = bagCodeService.getBagCodeByCode(traceCode);
        if (bag != null) {
            return new TraceEntry("BAG", bag.getBatchId());
            return new TraceEntry("BAG", bag.getBatchId(), bag.getItemId());
        }
        // ② 托盘码
        MesProPalletDO pallet = palletService.getPalletByCode(traceCode);
        if (pallet != null) {
            return new TraceEntry("PALLET", pallet.getBatchId());
            return new TraceEntry("PALLET", pallet.getBatchId(), null);
        }
        // ③ 批次码(含临时批次码,getBatchByCode 内部兼容)
        MesProBatchDO batch = batchService.getBatchByCode(traceCode);
        if (batch != null) {
            return new TraceEntry("BATCH", batch.getId());
            return new TraceEntry("BATCH", batch.getId(), null);
        }
        return new TraceEntry("", null);
        return new TraceEntry("", null, null);
    }
    // ==================== 聚合构建 ====================
    private MesProTracePublicRespVO buildRespVO(String requestCode, String traceCode, String sourceType, Long batchId) {
    private MesProTracePublicRespVO buildRespVO(String requestCode, String traceCode, String sourceType, Long batchId, Long bagItemId) {
        MesProBatchDO batch = batchService.getBatch(batchId);
        if (batch == null) {
            throw exception(MES_TRACE_CODE_NOT_FOUND);
@@ -192,7 +193,7 @@
        resp.setSourceType(sourceType);
        resp.setRequestCode(requestCode);
        // 品种区块
        fillItem(resp, batch);
        fillItem(resp, batch, bagItemId);
        // 批次区块
        resp.setBatchCode(batch.getCode()).setTempCode(batch.getTempCode())
                .setBatchStatus(batch.getStatus()).setBatchStatusName(batchStatusName(batch.getStatus()))
@@ -219,11 +220,20 @@
        return resp;
    }
    private void fillItem(MesProTracePublicRespVO resp, MesProBatchDO batch) {
        if (batch.getItemId() == null) {
    /**
     * 品种已下沉到袋码数据包:优先取扫码袋码品种,历史批次回退批次品种,批次/托盘入口取批内任一袋码品种
     */
    private void fillItem(MesProTracePublicRespVO resp, MesProBatchDO batch, Long bagItemId) {
        Long itemId = bagItemId != null ? bagItemId : batch.getItemId();
        if (itemId == null) {
            List<MesProBagCodeDO> bags = bagCodeService.getBagCodeListByBatchId(batch.getId());
            itemId = bags == null ? null : bags.stream().map(MesProBagCodeDO::getItemId)
                    .filter(id -> id != null).findFirst().orElse(null);
        }
        if (itemId == null) {
            return;
        }
        MesMdmItemDO item = mdmItemService.getItem(batch.getItemId());
        MesMdmItemDO item = mdmItemService.getItem(itemId);
        if (item == null) {
            return;
        }
@@ -333,12 +343,15 @@
            resp.setPurchaseSources(CollUtil.isNotEmpty(purchaseSources) ? purchaseSources : List.of());
            resp.setSalesTargets(CollUtil.isNotEmpty(salesTargets) ? salesTargets : List.of());
            resp.setProcessTraces(CollUtil.isNotEmpty(processTraces) ? processTraces : List.of());
            List<MesWmBatchFlowRespVO> seedFlows = mesWmBatchService.getBatchFlowList(batch.getCode());
            resp.setSeedFlows(CollUtil.isNotEmpty(seedFlows) ? seedFlows : List.of());
        } catch (Exception ex) {
            // 仓库批次体系(采购/销售/流转)未启用时容错,不影响核心追溯
            log.warn("[fillOptionalModules][批次 {} 扩展模块查询失败: {}]", batch.getCode(), ex.getMessage());
            resp.setPurchaseSources(List.of());
            resp.setSalesTargets(List.of());
            resp.setProcessTraces(List.of());
            resp.setSeedFlows(List.of());
        }
    }
@@ -454,7 +467,7 @@
        };
    }
    private record TraceEntry(String sourceType, Long batchId) {
    private record TraceEntry(String sourceType, Long batchId, Long bagItemId) {
    }
}