liu
8 小时以前 6c0fd2cb801554f7999d14e45a94ef0f0d0dfb8d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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;
 
/**
 * 二维码标签数据源工厂
 * <p>
 * 把「业务类型 + 导出参数」翻译成统一的数据源,使后台导出任务不必关心标签是怎么来的,
 * 也让同步导出路径与后台路径共用同一套取数与装配口径。
 */
@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<QrLabelInfo> fetchPage(int pageNo, int pageSize) {
                List<MesProBagCodeDO> 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;
            }
        };
    }
 
    /**
     * 托盘类数据源
     * <p>
     * 一个批次下的托盘数量有上界(受每托袋数约束),故一次性取出后按页切片,无需真分页查询。
     */
    private MesProQrLabelSource palletSource(Long batchId, boolean business) {
        List<MesProPalletDO> 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<QrLabelInfo> 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<MesProPalletDO> pallets = palletService.getPalletListByBatchId(batchId);
        if (business) {
            pallets = pallets.stream()
                    .filter(record -> !MesProPalletStatusEnum.CANCELED.getStatus().equals(record.getStatus()))
                    .toList();
        }
        List<QrLabelInfo> 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<QrLabelInfo> labels, String zipName) {
        return new MesProQrLabelSource() {
 
            @Override
            public long count() {
                return labels.size();
            }
 
            @Override
            public List<QrLabelInfo> 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;
            }
        };
    }
 
}