| | |
| | | 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; |
| | | import cn.iocoder.yudao.module.mes.controller.pub.trace.vo.MesProTracePublicConfigRespVO; |
| | | import cn.iocoder.yudao.module.mes.controller.pub.trace.vo.MesProTracePublicRespVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO; |
| | |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProBatchWorkerTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProPalletStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.trace.MesTraceCodeStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.framework.qrcode.MesProQrLabelBuilder; |
| | | import cn.iocoder.yudao.module.mes.service.mdm.MesMdmItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService; |
| | |
| | | if (entry.batchId == null && entry.bagItemId == null) { |
| | | throw exception(MES_TRACE_CODE_NOT_FOUND); |
| | | } |
| | | // 2. 聚合全程信息 |
| | | MesProTracePublicRespVO result = buildRespVO(rawCode, traceCode, entry.sourceType, entry.batchId, entry.bagItemId); |
| | | // 2. 聚合全程信息(作废码仍正常返回并记录扫码:作废码被扫是重要的防伪信号,不应记为查询失败) |
| | | MesProTracePublicRespVO result = buildRespVO(rawCode, traceCode, entry); |
| | | recordConsumerScan(rawCode, traceCode, entry.sourceType, entry.batchId, true); |
| | | return result; |
| | | } catch (RuntimeException ex) { |
| | |
| | | entry == null ? null : entry.batchId, false); |
| | | throw ex; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public MesProTracePublicConfigRespVO getPublicConfig() { |
| | | MesProTracePublicConfigRespVO respVO = new MesProTracePublicConfigRespVO(); |
| | | respVO.setOperatorName(MesProQrLabelBuilder.resolveOperatorName()); |
| | | respVO.setTraceUrl(MesProQrLabelBuilder.resolveTraceUrl()); |
| | | respVO.setImported(MesProQrLabelBuilder.isImported()); |
| | | return respVO; |
| | | } |
| | | |
| | | /** |
| | |
| | | // ① 袋码 |
| | | MesProBagCodeDO bag = bagCodeService.getBagCodeByCode(traceCode); |
| | | if (bag != null) { |
| | | return new TraceEntry("BAG", bag.getBatchId(), bag.getItemId()); |
| | | // 已作废的袋码(破损替换后作废)必须对外失效:国标要求二维码不得重复使用, |
| | | // 若作废码仍返回有效溯源信息,作废码即可被冒用销售 |
| | | if (MesProBagCodeStatusEnum.CANCELED.getStatus().equals(bag.getStatus())) { |
| | | return new TraceEntry("BAG", bag.getBatchId(), bag.getItemId(), |
| | | MesTraceCodeStatusEnum.CANCELED.getStatus()); |
| | | } |
| | | return TraceEntry.valid("BAG", bag.getBatchId(), bag.getItemId()); |
| | | } |
| | | // ② 托盘码 |
| | | MesProPalletDO pallet = palletService.getPalletByCode(traceCode); |
| | |
| | | // 未录入批次的托盘取托盘内任一袋码品种,保证仍能展示品种信息 |
| | | Long itemId = pallet.getBatchId() == null |
| | | ? firstItemId(bagCodeService.getBagCodeListByPalletId(pallet.getId())) : null; |
| | | return new TraceEntry("PALLET", pallet.getBatchId(), itemId); |
| | | if (MesProPalletStatusEnum.CANCELED.getStatus().equals(pallet.getStatus())) { |
| | | return new TraceEntry("PALLET", pallet.getBatchId(), itemId, |
| | | MesTraceCodeStatusEnum.CANCELED.getStatus()); |
| | | } |
| | | return TraceEntry.valid("PALLET", pallet.getBatchId(), itemId); |
| | | } |
| | | // ③ 批次码(含临时批次码,getBatchByCode 内部兼容) |
| | | MesProBatchDO batch = batchService.getBatchByCode(traceCode); |
| | | if (batch != null) { |
| | | return new TraceEntry("BATCH", batch.getId(), null); |
| | | if (MesProBatchStatusEnum.CANCELED.getStatus().equals(batch.getStatus())) { |
| | | return new TraceEntry("BATCH", batch.getId(), null, |
| | | MesTraceCodeStatusEnum.CANCELED.getStatus()); |
| | | } |
| | | return new TraceEntry("", null, null); |
| | | return TraceEntry.valid("BATCH", batch.getId(), null); |
| | | } |
| | | return new TraceEntry("", null, null, MesTraceCodeStatusEnum.VALID.getStatus()); |
| | | } |
| | | |
| | | // ==================== 聚合构建 ==================== |
| | | |
| | | private MesProTracePublicRespVO buildRespVO(String requestCode, String traceCode, String sourceType, Long batchId, Long bagItemId) { |
| | | private MesProTracePublicRespVO buildRespVO(String requestCode, String traceCode, TraceEntry entry) { |
| | | String sourceType = entry.sourceType(); |
| | | Long batchId = entry.batchId(); |
| | | Long bagItemId = entry.bagItemId(); |
| | | MesProBatchDO batch = batchId == null ? null : batchService.getBatch(batchId); |
| | | if (batchId != null && batch == null) { |
| | | throw exception(MES_TRACE_CODE_NOT_FOUND); |
| | |
| | | MesProTracePublicRespVO resp = new MesProTracePublicRespVO(); |
| | | resp.setSourceType(sourceType); |
| | | resp.setRequestCode(requestCode); |
| | | // 追溯码有效性 + 标签四要素中的生产经营者与追溯网址,保证与标签印刷内容一致 |
| | | resp.setCodeStatus(entry.codeStatus()); |
| | | resp.setOperatorName(MesProQrLabelBuilder.resolveOperatorName()); |
| | | resp.setTraceUrl(MesProQrLabelBuilder.resolveTraceUrl()); |
| | | // 品种区块 |
| | | fillItem(resp, batch, bagItemId); |
| | | if (batch == null) { |
| | |
| | | }; |
| | | } |
| | | |
| | | private record TraceEntry(String sourceType, Long batchId, Long bagItemId) { |
| | | /** |
| | | * 追溯入口解析结果 |
| | | * |
| | | * @param sourceType 入口类型:BAG / PALLET / BATCH,未匹配到时为空串 |
| | | * @param batchId 生产批次编号 |
| | | * @param bagItemId 袋码绑定的品种编号(未录批次时用于展示品种) |
| | | * @param codeStatus 追溯码有效性:{@link MesTraceCodeStatusEnum#VALID} / {@link MesTraceCodeStatusEnum#CANCELED} |
| | | */ |
| | | private record TraceEntry(String sourceType, Long batchId, Long bagItemId, String codeStatus) { |
| | | |
| | | static TraceEntry valid(String sourceType, Long batchId, Long bagItemId) { |
| | | return new TraceEntry(sourceType, batchId, bagItemId, MesTraceCodeStatusEnum.VALID.getStatus()); |
| | | } |
| | | |
| | | } |
| | | |
| | | } |