package cn.iocoder.yudao.module.mes.service.pro.qrexport; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.batch.MesProBatchDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.pallet.MesProPalletDO; import cn.iocoder.yudao.module.mes.enums.pro.MesProPalletStatusEnum; import cn.iocoder.yudao.module.mes.enums.pro.MesProQrExportBizTypeEnum; import cn.iocoder.yudao.module.mes.framework.qrcode.QrLabelInfo; import cn.iocoder.yudao.module.mes.service.pro.bagcode.MesProBagCodeService; import cn.iocoder.yudao.module.mes.service.pro.batch.MesProBatchService; import cn.iocoder.yudao.module.mes.service.pro.pallet.MesProPalletService; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_BATCH_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_PALLET_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_QR_EXPORT_PARAMS_INVALID; /** * 二维码标签数据源工厂 *

* 把「业务类型 + 导出参数」翻译成统一的数据源,使后台导出任务不必关心标签是怎么来的, * 也让同步导出路径与后台路径共用同一套取数与装配口径。 */ @Component public class MesProQrLabelSourceFactory { @Resource private MesProBagCodeService bagCodeService; @Resource private MesProPalletService palletService; @Resource private MesProBatchService batchService; @Resource private MesProQrLabelAssembler assembler; /** * 创建标签数据源;参数不合法时直接抛出业务异常 * * @param bizType 业务类型 * @param uuid 生成组 UUID(袋码类导出可用) * @param batchId 生产批次编号(袋码类可用,其余类型必填) */ public MesProQrLabelSource create(MesProQrExportBizTypeEnum bizType, String uuid, Long batchId) { if (bizType == null) { throw exception(PRO_QR_EXPORT_PARAMS_INVALID); } return switch (bizType) { case BAG_LABEL -> bagSource(uuid, batchId, false); case BAG_BUSINESS -> bagSource(uuid, batchId, true); case PALLET_LABEL -> palletSource(requireBatchId(batchId), false); case PALLET_BUSINESS -> palletSource(requireBatchId(batchId), true); case BATCH_LABEL -> batchSource(requireBatchId(batchId), false); case BATCH_BUSINESS -> batchSource(requireBatchId(batchId), true); }; } /** * 统计标签张数(分流判断用,不装配标签内容) */ public long count(MesProQrExportBizTypeEnum bizType, String uuid, Long batchId) { return create(bizType, uuid, batchId).count(); } private Long requireBatchId(Long batchId) { if (batchId == null) { throw exception(PRO_QR_EXPORT_PARAMS_INVALID); } return batchId; } // ==================== 各业务类型的数据源 ==================== /** * 袋码类数据源(标签 / 业务码) */ private MesProQrLabelSource bagSource(String uuid, Long batchId, boolean business) { if (StrUtil.isBlank(uuid) && batchId == null) { throw exception(PRO_QR_EXPORT_PARAMS_INVALID); } boolean byUuid = StrUtil.isNotBlank(uuid); String zipName = (business ? "袋码业务二维码-" : "袋码二维码-") + (byUuid ? uuid : batchId); return new MesProQrLabelSource() { @Override public long count() { return byUuid ? bagCodeService.getPrintableBagCodeCountByUuid(uuid) : bagCodeService.getPrintableBagCodeCountByBatchId(batchId); } @Override public List fetchPage(int pageNo, int pageSize) { List bags = byUuid ? bagCodeService.getPrintableBagCodePageByUuid(uuid, pageNo, pageSize) : bagCodeService.getPrintableBagCodePageByBatchId(batchId, pageNo, pageSize); return business ? assembler.buildBagBusinessLabels(bags) : assembler.buildBagCodeLabels(bags); } @Override public String zipName() { return zipName; } }; } /** * 托盘类数据源 *

* 一个批次下的托盘数量有上界(受每托袋数约束),故一次性取出后按页切片,无需真分页查询。 */ private MesProQrLabelSource palletSource(Long batchId, boolean business) { List pallets = palletService.getPalletListByBatchId(batchId); if (business) { // 业务码导出需排除已作废托盘,避免作废码被印出 pallets = pallets.stream() .filter(record -> !MesProPalletStatusEnum.CANCELED.getStatus().equals(record.getStatus())) .toList(); } if (pallets.isEmpty()) { throw exception(PRO_PALLET_NOT_EXISTS); } List labels = business ? assembler.buildPalletBusinessLabels(pallets) : assembler.buildPalletLabels(pallets); String zipName = business ? "托盘业务二维码" : "托盘码二维码-" + batchId; return fixedSource(labels, zipName); } /** * 批次类数据源:批次图 + 该批次全部托盘图 */ private MesProQrLabelSource batchSource(Long batchId, boolean business) { MesProBatchDO batch = batchService.getBatch(batchId); if (batch == null) { throw exception(PRO_BATCH_NOT_EXISTS); } List pallets = palletService.getPalletListByBatchId(batchId); if (business) { pallets = pallets.stream() .filter(record -> !MesProPalletStatusEnum.CANCELED.getStatus().equals(record.getStatus())) .toList(); } List labels = business ? assembler.buildBatchBusinessLabels(batch, pallets) : assembler.buildBatchLabels(batch, pallets); String zipName = business ? "批次业务二维码-" + batch.getBusinessCode() : "批次二维码-" + StrUtil.blankToDefault(batch.getCode(), batch.getTempCode()); return fixedSource(labels, zipName); } /** * 由已装配好的标签列表构造数据源(适用于总量有上界的场景) */ private MesProQrLabelSource fixedSource(List labels, String zipName) { return new MesProQrLabelSource() { @Override public long count() { return labels.size(); } @Override public List fetchPage(int pageNo, int pageSize) { int from = (pageNo - 1) * pageSize; if (from >= labels.size()) { return List.of(); } return labels.subList(from, Math.min(from + pageSize, labels.size())); } @Override public String zipName() { return zipName; } }; } }