李林
2023-10-07 658d4927d468c47208fd012d9128b09249c07eff
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
package com.chinaztt.mes.quality.utils;
 
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chinaztt.mes.quality.dto.ApplyDTO;
import com.chinaztt.mes.quality.dto.ApplyPartDTO;
import com.chinaztt.mes.quality.dto.MoTestStandardDTO;
import com.chinaztt.mes.quality.entity.Apply;
import com.chinaztt.mes.quality.entity.QualityTestApplyRule;
import com.chinaztt.mes.quality.mapper.ApplyPartMapper;
import com.chinaztt.mes.quality.mapper.QualityTestApplyRuleMapper;
import com.chinaztt.mes.quality.mapper.TestStandardMapper;
import com.chinaztt.mes.quality.state.standard.constant.InspectionTypeStringValues;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @Description : 检测申请规则工具类
 * @ClassName : TestApplyRuleUtils
 * @Author : sll
 * @Date: 2022-08-22  15:28
 */
@Service
@AllArgsConstructor
public class TestApplyRuleUtils {
    private ApplyPartMapper applyPartMapper;
    private QualityTestApplyRuleMapper qualityTestApplyRuleMapper;
    private TestStandardMapper testStandardMapper;
 
    /**
     * 根据检测申请规则配置数据自动矫正工作台的自动报检
     *
     * @param applyDTO
     * @return
     */
    public ApplyDTO adjustApplyDTO(ApplyDTO applyDTO) {
        if (CollectionUtils.isEmpty(applyDTO.getApplyPartList())) {
            throw new RuntimeException("申请材料明细为空");
        }
 
        // 约束报检类型
        if (StringUtils.isBlank(applyDTO.getApplyType())) {
            throw new RuntimeException("检测申请类型为空 -> 系统无法处理");
        } else {
            switch (applyDTO.getApplyType()) {
                case Apply.FIRST_APPLY: // 首检
                    break;
                case Apply.OUTPUT_APPLY: // 尾检
                    break;
                case Apply.LOCAL_APPLY: // 库存报检
                    throw new RuntimeException("【库存报检】-> 系统该业务路径暂时无法处理");
                case Apply.ERP_APPLY: // ERP报检
                    throw new RuntimeException("【ERP报检】 -> 系统该业务路径暂时无法处理");
                case Apply.ONSITE_APPLY: // 巡检
                    throw new RuntimeException("【巡检】 -> 系统该业务路径暂时无法处理");
                case Apply.BACK_APPLY: // 退货报检
                    throw new RuntimeException("【退货报检】 -> 系统该业务路径暂时无法处理");
                case Apply.PRODUCT_APPLY: // 成品检
                    throw new RuntimeException("【成品检】 -> 为系统自动触发 -> 必须经过过程检测方可触发");
                case Apply.BATCHFIRST_APPLY: // 批次首检
                    throw new RuntimeException("【批次首检】 -> 系统该业务已废弃");
                case Apply.PROCESS_APPLY: // 工序检
                    break;
                default:
                    throw new RuntimeException("检测申请类型 = 【" + applyDTO.getApplyType() + "】非法");
            }
        }
 
        HashSet<String> operationNos = new HashSet<String>();
        for (ApplyPartDTO applyPartDTO : applyDTO.getApplyPartList()) {
            if (null == applyPartDTO.getSystemNo() || applyPartDTO.getSystemNo().equals("")) {
                throw new RuntimeException("产出系统编号 = 【" + applyPartDTO.getSystemNo() + "】异常");
            }
            operationNos.add(applyPartMapper.selectOperationNoBySystemNo(applyPartDTO.getSystemNo()));// 根据产出系统编号获取对应的工序编号
        }
 
        if (null == operationNos || operationNos.size() == 0) {
            throw new RuntimeException("数据异常 -> 根据查出系统编号无法获取工序编号");
        }
        if (operationNos.size() != 1) {
            throw new RuntimeException("系统不支持一个检测申请单据中对应多个不同工序的申请材料");
        }
 
        // 根据工序编号读检测申请规则配置表(这里的长度必定是1)
        List<QualityTestApplyRule> qualityTestApplyRuleList = new ArrayList<>();
        for (String operationNo : operationNos) {
            qualityTestApplyRuleList = qualityTestApplyRuleMapper.selectList(Wrappers.<QualityTestApplyRule>lambdaQuery().eq(QualityTestApplyRule::getOperationNo, operationNo));
        }
 
        if (CollectionUtils.isEmpty(qualityTestApplyRuleList)) {
            applyDTO.setAutoCreateApplyDoor(true);
            return applyDTO;// 没有单独配置,则按原路径走
        } else {
            // 存在配置,则需校验检测申请规则配置是否合规
            applyRuleCheck(qualityTestApplyRuleList);
 
            for (QualityTestApplyRule qualityTestApplyRule : qualityTestApplyRuleList) {
                if (qualityTestApplyRule.getInspectionType().equals(applyDTO.getApplyType())) {
                    applyDTO.setAutoCreateApplyDoor(true);
                    return applyDTO;// 存在与发起类型相同的检测申请配置,则按原路径走
                }
            }
 
            // 如果申请是首检,且不在配置中,则不进行自动矫正(工作台的固定机制是配置自动报检后会自动发送首检和尾检的检测申请)
            if (applyDTO.getApplyType().equals(Apply.FIRST_APPLY)) {
                applyDTO.setAutoCreateApplyDoor(false);
                return applyDTO;
            }
 
            // 存在配置,但是不存在请求的检测申请类型,则进行自动矫正
            // 自动矫正的检测申请类型优先级:首检 > 尾检 > 工序检 > 成品检(目前系统只支持这4种检测类型)
            List<String> rules = qualityTestApplyRuleList.stream().map(o -> o.getInspectionType()).collect(Collectors.toList());
            if (rules.containsAll(Collections.singleton(Apply.FIRST_APPLY))) {
                applyDTO.setAutoCreateApplyDoor(true);
                applyDTO.setApplyType(Apply.FIRST_APPLY);
                return applyDTO;
            } else if (rules.containsAll(Collections.singleton(Apply.OUTPUT_APPLY))) {
                applyDTO.setAutoCreateApplyDoor(true);
                applyDTO.setApplyType(Apply.OUTPUT_APPLY);
                return applyDTO;
            } else if (rules.containsAll(Collections.singleton(Apply.PROCESS_APPLY))) {
                applyDTO.setAutoCreateApplyDoor(true);
                applyDTO.setApplyType(Apply.PROCESS_APPLY);
                return applyDTO;
            } else if (rules.containsAll(Collections.singleton(Apply.PRODUCT_APPLY))) {
                applyDTO.setAutoCreateApplyDoor(true);
                applyDTO.setApplyType(Apply.PRODUCT_APPLY);
                return applyDTO;
            } else {
                applyDTO.setAutoCreateApplyDoor(false);
                return applyDTO;
            }
        }
 
    }
 
    /**
     * 根据检测申请规则配置数据自动矫正工作台的自动报检
     *
     * @param applyDTO
     * @return
     */
    public ApplyDTO adjustApplyDTONew(ApplyDTO applyDTO) {
        if (CollectionUtils.isEmpty(applyDTO.getApplyPartList())) {
            throw new RuntimeException("申请材料明细为空");
        }
 
        // 约束报检类型
        if (StringUtils.isBlank(applyDTO.getApplyType())) {
            throw new RuntimeException("检测申请类型为空 -> 系统无法处理");
        } else {
            switch (applyDTO.getApplyType()) {
                case Apply.FIRST_APPLY: // 首检
                    break;
                case Apply.OUTPUT_APPLY: // 尾检
                    break;
                case Apply.LOCAL_APPLY: // 库存报检
                    throw new RuntimeException("【库存报检】-> 系统该业务路径暂时无法处理");
                case Apply.ERP_APPLY: // ERP报检
                    throw new RuntimeException("【ERP报检】 -> 系统该业务路径暂时无法处理");
                case Apply.ONSITE_APPLY: // 巡检
                    throw new RuntimeException("【巡检】 -> 系统该业务路径暂时无法处理");
                case Apply.BACK_APPLY: // 退货报检
                    throw new RuntimeException("【退货报检】 -> 系统该业务路径暂时无法处理");
                case Apply.PRODUCT_APPLY: // 成品检
                    break;
                case Apply.BATCHFIRST_APPLY: // 批次首检
                    throw new RuntimeException("【批次首检】 -> 系统该业务已废弃");
                case Apply.PROCESS_APPLY: // 工序检
                    break;
                default:
                    throw new RuntimeException("检测申请类型 = 【" + applyDTO.getApplyType() + "】非法");
            }
        }
 
        List<MoTestStandardDTO> totalTestStandardList = new ArrayList<>();
        for (ApplyPartDTO applyPartDTO : applyDTO.getApplyPartList()) {
            if (null == applyPartDTO.getSystemNo() || applyPartDTO.getSystemNo().equals("")) {
                throw new RuntimeException("产出系统编号 = 【" + applyPartDTO.getSystemNo() + "】异常");
            }
            // 找出对应车间订单的检测标准配置
            List<MoTestStandardDTO> testStandardList = testStandardMapper.selectMoTestStandardDTOList(applyPartDTO.getSystemNo());
            if (CollectionUtils.isEmpty(testStandardList)) {
                throw new RuntimeException("数据异常 -> 车间订单未绑定检测标准");
            }
            if (!BooleanUtil.isTrue(testStandardList.get(0).getInspection())) {
                continue;
            }
            if (BooleanUtil.isTrue(testStandardList.get(0).getInspection()) && StringUtils.isBlank(testStandardList.get(0).getInspectionType())){
                throw new RuntimeException("数据异常 -> 检测标准未配置检测类型");
            }
            totalTestStandardList.addAll(testStandardList);
        }
        if (CollectionUtils.isEmpty(totalTestStandardList)) {
            applyDTO.setAutoCreateApplyDoor(false);
            return applyDTO;
        }
        Long check = totalTestStandardList.stream().map(MoTestStandardDTO::getMoRoutingOperationId).distinct().count();
        if (check > 1) {
            throw new RuntimeException("数据异常 -> 一个检测申请单据中对应多个不同工序的申请材料");
        }
        applyRuleCheckNew(totalTestStandardList);
 
        for (MoTestStandardDTO qualityTestApplyRule : totalTestStandardList) {
            if (qualityTestApplyRule.getInspectionType().equals(applyDTO.getApplyType())) {
                applyDTO.setAutoCreateApplyDoor(true);
                return applyDTO;// 存在与发起类型相同的检测申请配置,则按原路径走
            }
        }
        // 如果申请是首检,且不在配置中,则不进行自动矫正(工作台的固定机制是配置自动报检后会自动发送首检和尾检的检测申请)
        if (applyDTO.getApplyType().equals(Apply.FIRST_APPLY)) {
            applyDTO.setAutoCreateApplyDoor(false);
            return applyDTO;
        }
        // 存在配置,但是不存在请求的检测申请类型,则进行自动矫正
        // 自动矫正的检测申请类型优先级:首检 > 尾检 > 工序检 > 成品检(目前系统只支持这4种检测类型)
        List<String> rules = totalTestStandardList.stream().map(o -> o.getInspectionType()).collect(Collectors.toList());
        if (rules.containsAll(Collections.singleton(Apply.FIRST_APPLY))) {
            applyDTO.setAutoCreateApplyDoor(true);
            applyDTO.setApplyType(Apply.FIRST_APPLY);
            return applyDTO;
        } else if (rules.containsAll(Collections.singleton(Apply.OUTPUT_APPLY))) {
            applyDTO.setAutoCreateApplyDoor(true);
            applyDTO.setApplyType(Apply.OUTPUT_APPLY);
            return applyDTO;
        } else if (rules.containsAll(Collections.singleton(Apply.PROCESS_APPLY))) {
            applyDTO.setAutoCreateApplyDoor(true);
            applyDTO.setApplyType(Apply.PROCESS_APPLY);
            return applyDTO;
        } else if (rules.containsAll(Collections.singleton(Apply.PRODUCT_APPLY))) {
            applyDTO.setAutoCreateApplyDoor(true);
            applyDTO.setApplyType(Apply.PRODUCT_APPLY);
            return applyDTO;
        } else {
            applyDTO.setAutoCreateApplyDoor(false);
            return applyDTO;
        }
 
    }
 
    /**
     * 判断检测申请规则是否合规
     *
     * @param totalTestStandardList 规则列表
     */
    private void applyRuleCheckNew(List<MoTestStandardDTO> totalTestStandardList) {
        /**
         * 合规配置如下:
         * 配置1:首检、尾检
         * 配置2:首检、尾检、成品检
         * 配置3:工序检
         * 配置4:工序检、成品检
         * 配置5:成品检
         */
 
        Set<String> rules = new HashSet<>();
        for (MoTestStandardDTO moTestStandardDTO : totalTestStandardList) {
            rules.add(moTestStandardDTO.getInspectionType());
        }
 
        Boolean door = true;
        if (rules.size() == 1) {
            if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_03).containsAll(rules)) {
                if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_05).containsAll(rules)) {
                    door = false;
                }
            }
        } else if (rules.size() == 3) {
            if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_02).containsAll(rules)) {
                door = false;
            }
        } else if (rules.size() == 2) {
            if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_01).containsAll(rules)) {
                if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_04).containsAll(rules)) {
                    door = false;
                }
            }
        } else {
            door = false;
        }
 
        if (!door) {
            throw new RuntimeException("车间订单工序 = 【" + totalTestStandardList.get(0).getOperationName() + "】绑定的检测标准的检测申请规则配置不合规");
        }
    }
 
    /**
     * 判断检测申请规则是否合规
     *
     * @param qualityTestApplyRuleList 规则列表
     */
    public void applyRuleCheck(List<QualityTestApplyRule> qualityTestApplyRuleList) {
        /**
         * 合规配置如下:
         * 配置1:首检、尾检
         * 配置2:首检、尾检、成品检
         * 配置3:工序检
         * 配置4:工序检、成品检
         */
 
        List<String> rules = new ArrayList<>();
        for (QualityTestApplyRule qualityTestApplyRule : qualityTestApplyRuleList) {
            rules.add(qualityTestApplyRule.getInspectionType());
        }
 
        Boolean door = true;
        if (qualityTestApplyRuleList.size() == 1) {
            if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_03).containsAll(rules)) {
                door = false;
            }
        } else if (qualityTestApplyRuleList.size() == 3) {
            if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_02).containsAll(rules)) {
                door = false;
            }
        } else if (qualityTestApplyRuleList.size() == 2) {
            if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_01).containsAll(rules)) {
                if (!Arrays.asList(InspectionTypeStringValues.TEST_RULE_CONFIG_04).containsAll(rules)) {
                    door = false;
                }
            }
        } else {
            door = false;
        }
 
        if (!door) {
            throw new RuntimeException("工序编号 = 【" + qualityTestApplyRuleList.get(0).getOperationNo() + "】检测申请规则配置不合规");
        }
    }
 
    /**
     * 根据工序编号校验检测申请配置规则是否合规
     *
     * @param operationNo 工序编号
     */
    public void applyRulesCheckByOprationNo(String operationNo) {
        if (StringUtils.isBlank(operationNo)) {
            throw new RuntimeException("工序编号 = 【" + operationNo + "】异常");
        }
        List<QualityTestApplyRule> qualityTestApplyRuleList = qualityTestApplyRuleMapper.selectList(Wrappers.<QualityTestApplyRule>lambdaQuery().eq(QualityTestApplyRule::getOperationNo, operationNo));
        applyRuleCheck(qualityTestApplyRuleList);
    }
 
    /**
     * 剔除掉相同批次号相同检测类型已存在的申请材料
     *
     * @param applyType
     * @param applyPartDTOList
     */
    public void removeAlExistObj(String applyType, List<ApplyPartDTO> applyPartDTOList) {
        if (CollectionUtils.isNotEmpty(applyPartDTOList)) {
            Iterator<ApplyPartDTO> iterator = applyPartDTOList.iterator();
            while (iterator.hasNext()) {
                ApplyPartDTO applyPartDTO = iterator.next();
                if (applyPartMapper.isAutoApplyPartExist(applyType, applyPartDTO.getSystemNo()) > 0) {
                    iterator.remove();
                }
            }
        }
/*        if (CollectionUtils.isNotEmpty(applyPartDTOList)) {
            for (int i = applyPartDTOList.size() - 1; i >= 0; i--) {
                // 工作台那边传过来的申请材料只有system_no
                if (applyPartMapper.isAutoApplyPartExist(applyType, applyPartDTOList.get(i).getSystemNo()) > 0) {
                    applyPartDTOList.remove(i);// 剔除
                }
            }
        }*/
    }
 
    /**
     * 根据系统编号获取检测申请类型
     * 应用场景,矫正工作台进行【尾检】业务操作时的检测申请类型
     *
     * @param systemNo 产出系统编号
     * @return 矫正后的检测申请类型
     */
    public String getApplyTypeBySystemNo(String systemNo) {
        if (null == systemNo) {
            throw new RuntimeException("产出系统编号 = 【" + systemNo + "】 --> 传参异常");
        }
        ApplyDTO applyDTO = new ApplyDTO();
        List<ApplyPartDTO> applyPartDTOList = new ArrayList<>();
        ApplyPartDTO applyPartDTO = new ApplyPartDTO();
 
        applyPartDTO.setSystemNo(systemNo);
        applyPartDTOList.add(applyPartDTO);
        applyDTO.setApplyPartList(applyPartDTOList);
        applyDTO.setApplyType(Apply.OUTPUT_APPLY);// 设置成尾检,然后对其进行矫正
        adjustApplyDTONew(applyDTO);
        return applyDTO.getApplyType();
    }
 
    public void applyRulesCheckBySystemNo(String systemNo) {
        if (StringUtils.isBlank(systemNo)) {
            throw new RuntimeException("系统编号 = 【" + systemNo + "】异常");
        }
        List<MoTestStandardDTO> testStandardList = testStandardMapper.selectMoTestStandardDTOList(systemNo);
        applyRuleCheckNew(testStandardList);
    }
}