李林
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
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
package com.chinaztt.mes.quality.service.impl;
 
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.chinaztt.ifs.api.feign.IfsFeignClient;
import com.chinaztt.mes.basic.entity.Part;
import com.chinaztt.mes.basic.mapper.PartMapper;
import com.chinaztt.mes.quality.dto.ApplyPartDTO;
import com.chinaztt.mes.quality.dto.IfsShopOrderDTO;
import com.chinaztt.mes.quality.dto.ReportMDTO;
import com.chinaztt.mes.quality.dto.SubmitReportDTO;
import com.chinaztt.mes.quality.entity.*;
import com.chinaztt.mes.quality.mapper.*;
 
import com.chinaztt.mes.quality.service.ApplyPartService;
import com.chinaztt.mes.quality.service.ReportSampleService;
import com.chinaztt.mes.quality.service.ReportSamplingRecordService;
import com.chinaztt.mes.quality.service.ReportService;
import com.chinaztt.mes.quality.state.result.constant.ResultStateStringValues;
import com.chinaztt.mes.quality.utils.QualityModuleDockIfsUtils;
import com.chinaztt.mes.quality.utils.ReportUtils;
import com.chinaztt.mes.warehouse.dto.StockDTO;
import com.chinaztt.mes.warehouse.mapper.StockMapper;
import com.chinaztt.ztt.common.core.util.R;
import com.chinaztt.ztt.common.security.util.SecurityUtils;
import com.google.gson.Gson;
 
import com.google.gson.internal.LinkedTreeMap;
import lombok.AllArgsConstructor;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * 检测汇报表
 *
 * @author cxf
 * @date 2021-04-06 14:29:39
 */
@Service
@AllArgsConstructor
@Component
@Transactional(rollbackFor = Exception.class)
public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> implements ReportService {
    private static final Long LOCATION_TYPE_QUALIFIED = 4L;//mes产出合格库位码
    private ReportUtils reportUtils;
    private ResultMapper resultMapper;
    private IfsFeignClient ifsFeignClient;
    private PartMapper partMapper;
    private ApplyPartService applyPartService;
    private ApplyPartMapper applyPartMapper;
    private QualityModuleDockIfsUtils qualityModuleDockIfsUtils;
    private ApplyPartFileMapper applyPartFileMapper;
    private ReportSampleMapper reportSampleMapper;
    private ReportSampleService reportSampleService;
    private StockMapper stockMapper;
    private ReportSamplingRecordService reportSamplingRecordService;
    private ReportSamplingRecordMapper reportSamplingRecordMapper;
    private ReportSampleItemMapper reportSampleItemMapper;
    private Environment environment;
 
//    @Autowired
//    public ReportServiceImpl(@Lazy ApplyPartService applyPartService) {
//        this.applyPartService = applyPartService;
//    }
 
 
    @Override
    public boolean save(Report report) {
        reportUtils.checkReportNo(report);//自动生成或校验检测汇报编号(支持手动定义编号)
        return SqlHelper.retBool(baseMapper.insert(report));
    }
 
    @Override
    public boolean updateById(Report report) {
        reportUtils.checkReportNo(report);
        return SqlHelper.retBool(baseMapper.updateById(report));
    }
 
 
    @Override
    public boolean removeById(Long id) {
        Report report = this.baseMapper.selectById(id);
        List<ApplyPart> applyParts = applyPartMapper.selectListByReportId(id);
        if (!applyParts.isEmpty()) {
            // 清空检测结果状态
            List<String> systemNos = applyParts.stream().map(ApplyPart::getSystemNo).collect(Collectors.toList());
            resultMapper.clearCheckStatusBySystemNosAndType(report.getReportType(), systemNos);
        }
 
        // 清空检测申请材料表的汇报id
        applyPartMapper.clearReportId(id);
 
        // 清除抽检记录
        if (report.getSamplingRecordId() != null) {
            reportSamplingRecordService.reduceSamplingRecordNum(report.getSamplingRecordId(), id);
        }
 
 
        // 删除检测汇报
        return SqlHelper.retBool(this.baseMapper.deleteById(id));
    }
 
    @Override
    public R saveFamily(ReportMDTO reportMDTO){
        //校验SN、光标位置码
        if(reportMDTO.getSn() == null || reportMDTO.getSn().length() == 0){
            return R.failed("SN号为空!");
        }else if(!(reportMDTO.getSweepCodeGunCursorLocation().equals("M") || reportMDTO.getSweepCodeGunCursorLocation().equals("D"))){
            return R.failed("扫码枪光标位置码异常!");
        }else{
            switch(reportMDTO.getSweepCodeGunCursorLocation()){
                case "M"://光标在主表表头
                    break;
                case "D"://光标在明细表表头
                    break;
                default:
                    break;
            }
 
            return R.ok("该需求取消,有射频老MES调接口推送");
        }
    }
 
    /**
     * 扫码枪扫码——新增检测汇报
     * @param sn
     * @return 检测汇报记录行id
     */
    private long addReportM(String sn) {
        //根据sn号获取检测汇报类型
        //该SN号有且仅有一条检测申请记录,则支持自动创建检测汇报
        List<String> applyTypeList = baseMapper.getApplyTypeBySN(sn);
        if(applyTypeList == null || applyTypeList.size() == 0){
            throw new RuntimeException("该对象查无检测申请,无法自动创建检测汇报!");
        }else if(applyTypeList.size() > 1){
            throw new RuntimeException("该对象存在多条检测申请,无法自动创建检测汇报!");
        }else{
            //创建检测汇报主表
            Report report = new Report();
            report.setCheckState(Report.CHECK_STATE_UNCHECK);//初始化状态:未检测
            report.setReportType(applyTypeList.get(0));//初始化汇报类型
            reportUtils.checkReportNo(report);//自动生成检测汇报编号
            baseMapper.insert(report);
            return report.getId();//返回自增id
        }
    }
 
    /**
     * 扫码枪扫码——新增检测汇报零件
     * @param reportId 检测汇报主表id
     * @param sn
     * @param reportType 检测汇报类型
     * @return 检测汇报零件记录行id
     */
    private long addReportPart(Long reportId,String sn,String reportType) {
        //根据sn、检测汇报类型获取其对应的检测申请明细(此时sn号对应的检测申请明细只存在唯一一条记录)
        List<ApplyPart> applyPartList = applyPartMapper.selectApplyApertByInspState(sn,reportType);
        if(applyPartList == null || applyPartList.size() != 1){
            throw new RuntimeException("通过SN号及检测汇报类型查无检测申请或检测申请记录数>1");
        }else{
            //将检测汇报id根据sn号更新至检测申请明细中
            baseMapper.updateApplyPartReportId(sn,reportId);
            return applyPartList.get(0).getId();//返回记录行id
        }
    }
 
    @Override
    public R submit(Long id){
        //校验检测汇报是否已提交
        Report report = baseMapper.selectById(id);
 
        if(report.getIsSubmit() != null && report.getIsSubmit()){
            if(report.getIsSubmit()){
                throw new RuntimeException("请勿重复提交检测汇报!");
            }
        }
 
        List<ApplyPart> applyPartList = applyPartMapper.selectListByReportId(id);
        //判断检测汇报中的明细全部已检测是否成立,不成立则拒绝提交报告
        if(CollectionUtils.isNotEmpty(applyPartList)){
            reportUtils.checkOperationNoIsSame(id);//检验汇报零件工序是否一致
            for(int i = 0;i < applyPartList.size();i++){
                if(applyPartList.get(i).getIsQualified() == null){
                    throw new RuntimeException("该检测汇报存在汇报明细未检测,无法提交!");
                }
            }
        }else{
            throw new RuntimeException("检测汇报明细为空!无法提交检测汇报!");
        }
 
        //更新检测汇报主表状态为:已提交
        baseMapper.updateQualityReportSubmitState(id,true);
 
        // ERP 不需要移库
        //对接库存件移库
//        if(report.getReportType().equals(Apply.PRODUCT_APPLY)){
//            //此处的移库是处理成品检中的移库
//            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.MOVE_PART, true);
//        }
 
        // 是否需要成品检处理
        boolean isNeedFinishApply = false;
 
        //首检及批次首检只做检测,不做其他关联业务
        if(!report.getReportType().equals(Apply.FIRST_APPLY)&&!report.getReportType().equals(Apply.BATCHFIRST_APPLY)){
            //ERP 不需要移库
            //移库
//            isNeedFinishApply = applyPartService.moveLibrary(id,ApplyPartServiceImpl.MOVELIBRARY);
 
            if(false){//直接屏蔽,放弃整改
                //ifs移库成功,车间订单接收失败怎么处理?理论上不存在,这两种汇报类型不应该同时存在
                List<ApplyPart> applyPartListFilter_last = filterSynIfsApplyParts(id);
                for(int i = 0;i < applyPartListFilter_last.size();i++){
                    //更新产出明细是否提交ifs为:已提交(根据system_no)
                    if(applyPartMapper.isLastOperationBySystemNo(applyPartListFilter_last.get(i).getSystemNo()) && !report.getReportType().equals(Apply.PRODUCT_APPLY)){
                        continue;//是最后一道工序,且不是成品检,则跳过
                    }
                    baseMapper.updateProductOutIsSynIfs(applyPartListFilter_last.get(i).getSystemNo(),true);
                }
                shopOrderReceive(applyPartListFilter_last,report,"re");//车间订单接收
            }
        }
 
        // 对接ERP产品入口
        List<String> partNos = applyPartList.stream().map(ApplyPart::getPartNo).collect(Collectors.toList());
        List<Part> parts = partMapper.selectList(new LambdaQueryWrapper<Part>().in(Part::getPartNo, partNos));
        Map<String,Object> _Map = new HashMap<>();
        _Map.put("title","成品入库");
        _Map.put("sort",1);// 规定1 成品入库 等ERP确认
//        _Map.put("sort",1);// 规定1 成品入库 等ERP确认
//        SecurityUtils.getUser().getId()
        _Map.put("date3", DateUtil.format(new Date(),"YYYY-MM-dd"));
        List<Map<String,Object>> details = new ArrayList<>();
        _Map.put("details",details);
        for (ApplyPart applyPart:applyPartList) {
            Map<String,Object> pMap = new HashMap<>();
            Part part = parts.stream().filter(e->e.getPartNo().equals(applyPart.getPartNo())).findFirst().get();
            pMap.put("ord",part.getPartFamilyId());
            details.add(pMap);
        }
        _Map.put("details",details);
        inWareHoiuse(_Map);
//        //对接工序报废
//        if(false){
//            //取消对接ifs工序报工,是否自动报工设置为:是
//            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SCRAP_OPERATION, isNeedFinishApply);
//        }
//
//        //对接工序报工
//        if(false){
//            //取消对接ifs工序报废
//            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.REPORT_OPERATION, isNeedFinishApply);
//        }
//
//        //对接车间订单接收
//        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SHOP_ORDER_REC, isNeedFinishApply);
 
        return R.ok("检测汇报单提交成功!");
    }
 
    private void inWareHoiuse(Map<String,Object> map) {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        String inWareHouse = environment.getProperty("inWareHouse");
        HttpPost httpPost = new HttpPost(inWareHouse);
 
        String jsonParams = new Gson().toJson(map);
        // 设置请求体为JSON格式
        StringEntity requestEntity = new StringEntity(jsonParams, ContentType.APPLICATION_JSON);
        httpPost.setEntity(requestEntity);
        String responseString = null;
 
        try {
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            responseString = EntityUtils.toString(entity, "UTF-8");
            R r = new Gson().fromJson(responseString, R.class);
            if (r.getCode()!=0){
                throw new RuntimeException(r.getMsg());
            }
 
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    @Override
    public R submitV2(Long id) {
        synchronized (id.toString().intern()) {
 
            //校验检测汇报是否已提交
            Report report = baseMapper.selectById(id);
 
            if(report.getIsSubmit() != null && report.getIsSubmit()){
                if(report.getIsSubmit()){
                    throw new RuntimeException("请勿重复提交检测汇报!");
                }
            }
 
            List<ApplyPart> applyPartList = applyPartMapper.selectListByReportId(id);
            ApplyPart applyPart = null;
            //判断检测汇报中的明细全部已检测是否成立,不成立则拒绝提交报告
            if(CollectionUtils.isNotEmpty(applyPartList)){
                reportUtils.checkOperationNoIsSame(id);//检验汇报零件工序是否一致
                if (applyPartList.size() > 1) {
                    throw new RuntimeException("检测汇报中仅支持一条待检零件!");
                }
                applyPart = applyPartList.get(0);
                if (applyPart.getIsQualified() == null) {
                    throw new RuntimeException("该检测汇报存在汇报明细未检测,无法提交!");
                }
            }else{
                throw new RuntimeException("检测汇报明细为空!无法提交检测汇报!");
            }
 
            if (report.getSamplingRecordId() == null) {
                reportSamplingRecordService.submitSamplingRecord(applyPart.getSystemNo(), id, report.getReportType());
            }
            // Long samplingReportId = reportSamplingRecordService.addSamplingRecordNum(applyPart.getSystemNo(), id, report.getReportType());
            // if (samplingReportId != null) {
            //     List<ReportSample> reportSamples = reportSampleMapper.selectList(Wrappers.<ReportSample>lambdaQuery().eq(ReportSample::getReportId, id));
            //     for (ReportSample reportSample : reportSamples) {
            //         // 删除旧检测样品记录
            //         reportSampleService.deleteById(reportSample.getId());
            //     }
            //
            //     // 生成新的检测样品记录
            //     // 如果存在抽检规则记录,则将抽检规则记录样品记录复制为当前样品记录
            //     List<ReportSample> reportSampleList = this.reportSampleMapper.selectList(Wrappers.<ReportSample>lambdaQuery().eq(ReportSample::getReportId, samplingReportId));
            //     if (CollectionUtils.isEmpty(reportSampleList)) {
            //         Report samplingReport = this.getById(samplingReportId);
            //         throw new RuntimeException("抽检检测汇报->" + samplingReport.getReportNo() + ",检测汇报不存在样品记录");
            //     }
            //     ReportSample reportSample = new ReportSample();
            //     reportSample.setReportId(applyPart.getReportId());
            //     reportSample.setSystemNo(applyPart.getSystemNo());
            //     reportSample.setTestStandardNo(reportSampleList.get(0).getTestStandardNo());
            //     reportSample.setTestStandardId(reportSampleList.get(0).getTestStandardId());
            //     reportSample.setIsMoTestStandard(reportSampleList.get(0).getIsMoTestStandard());
            //     reportSampleService.insert(reportSample);
            //
            //     // 抽检规则记录样品记录复制为当前样品记录
            //     reportSampleItemMapper.copyReportSampleItem(reportSampleList.get(0).getId(), reportSample.getId());
            // }
 
            //更新检测汇报主表状态为:已提交
            baseMapper.updateQualityReportSubmitState(id,true);
 
            //对接库存件移库
            if(report.getReportType().equals(Apply.PRODUCT_APPLY)){
                // 存在替代零件号,走单独逻辑
                if (applyPart.getReplacePartId() == null) {
                    //此处的移库是处理成品检中的移库
                    qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.MOVE_PART_V2, true);
                }
            }
 
            // 是否需要成品检处理
            boolean isNeedFinishApply = false;
 
            //首检及批次首检只做检测,不做其他关联业务
            if(!report.getReportType().equals(Apply.FIRST_APPLY)&&!report.getReportType().equals(Apply.BATCHFIRST_APPLY)){
                //移库
                isNeedFinishApply = applyPartService.moveLibraryV2(id,ApplyPartServiceImpl.MOVELIBRARY);
 
                //对接车间订单接收
                if (applyPart.getSourceLocationId() != null) {
                    // 存在源库位,走单独逻辑
                    if (applyPart.getReplacePartId() != null) {
                        // 存在替代零件号,走单独逻辑
                        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.MOVE_PART_REPLACE_NO_OUTPUT, isNeedFinishApply);
                    } else {
                        if (applyPart.getScrapArrived() != null && applyPart.getScrapArrived().compareTo(BigDecimal.ZERO) > 0) {
                            // 如果存在报废数量,发放报废数量
                            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SCRAP_ISSUANCE, isNeedFinishApply);
                        }
                        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.MOVE_PART_NO_OUTPUT, isNeedFinishApply);
                    }
                } else if (applyPart.getReplacePartId() != null) {
                    // 存在替代零件号,走单独逻辑
                    qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.MOVE_PART_REPLACE, isNeedFinishApply);
                } else {
                    if (applyPart.getScrapArrived() != null && applyPart.getScrapArrived().compareTo(BigDecimal.ZERO) > 0) {
                        // 如果存在报废数量,发放报废数量
                        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SCRAP_ISSUANCE, isNeedFinishApply);
                    }
                    qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SHOP_ORDER_REC_V2, isNeedFinishApply);
                }
            }
 
            return R.ok("检测汇报单提交成功!");
        }
    }
 
 
    @Override
    public R cancelSubmit(Long id){
        //校验检测汇报是否未提交
        Report report = baseMapper.selectById(id);
 
        if(report.getIsSubmit() == null || !report.getIsSubmit()){
            throw new RuntimeException("检测汇报未提交,无需取消提交!");
        }
 
 
        //更新检测汇报主表状态为:未提交
        baseMapper.updateQualityReportSubmitState(id,false);
 
        //对接库存件移库
        if(report.getReportType().equals(Apply.PRODUCT_APPLY)){
            //此处的移库是处理成品检中的移库
            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_MOVE_PART, true);
        }
 
        // 是否需要成品检处理
        boolean isNeedFinishApply = false;
 
        //首检及批次首检只做检测,不做其他关联业务
        if(!report.getReportType().equals(Apply.FIRST_APPLY)&&!report.getReportType().equals(Apply.BATCHFIRST_APPLY)){
            List<ApplyPart> applyPartListFilter_last = filterSynIfsApplyParts(id);
            isNeedFinishApply = applyPartService.moveLibrary(id,ApplyPartServiceImpl.UNMOVELIBRARY);//取消移库
 
            if(false){//直接屏蔽,放弃整改
                for(int i = 0;i < applyPartListFilter_last.size();i++){
                    //更新产出明细是否提交ifs为:未提交(根据system_no)
                    baseMapper.updateProductOutIsSynIfs(applyPartListFilter_last.get(i).getSystemNo(),false);
                }
 
                shopOrderReceive(applyPartListFilter_last,report,"unre");//车间订单取消接收
            }
 
            //对接取消工序报工
            if(false){
                //取消对接ifs工序报工,是否自动报工设置为:是
                qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_REPORT_OPERATION, isNeedFinishApply);
            }
 
            //对接取消工序报废
            if(false){
                //取消对接ifs工序报废
                qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_SCRAP_OPERATION, isNeedFinishApply);
            }
 
            //对接取消车间订单接收
            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SHOP_ORDER_CANCEL_REC, isNeedFinishApply);
 
        }
 
        return R.ok("检测汇报单取消提交成功!");
    }
 
    @Override
    public R cancelSubmitV2(Long id) {
        synchronized (id.toString().intern()) {
            //校验检测汇报是否未提交
            Report report = baseMapper.selectById(id);
 
            if(report.getIsSubmit() == null || !report.getIsSubmit()){
                throw new RuntimeException("检测汇报未提交,无需取消提交!");
            }
 
            List<ApplyPart> applyPartList = applyPartMapper.selectListByReportId(id);
            ApplyPart applyPart = null;
            if (CollectionUtils.isEmpty(applyPartList) || applyPartList.size() > 1) {
                throw new RuntimeException("不存在检测汇报零件或者检测汇报零件存在多个!");
            } else {
                applyPart = applyPartList.get(0);
            }
 
            //更新检测汇报主表状态为:未提交
            baseMapper.updateQualityReportSubmitState(id,false);
 
            //对接库存件移库
            if(report.getReportType().equals(Apply.PRODUCT_APPLY)){
                // 存在替代零件号,走单独逻辑
                if (applyPart.getReplacePartId() == null) {
                    //此处的移库是处理成品检中的移库
                    qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_MOVE_PART_V2, true);
                }
            }
 
            // 是否需要成品检处理
            boolean isNeedFinishApply = false;
 
            //首检及批次首检只做检测,不做其他关联业务
            if(!report.getReportType().equals(Apply.FIRST_APPLY)&&!report.getReportType().equals(Apply.BATCHFIRST_APPLY)){
                // List<ApplyPart> applyPartListFilter_last = filterSynIfsApplyParts(id);
                isNeedFinishApply = applyPartService.moveLibraryV2(id,ApplyPartServiceImpl.UNMOVELIBRARY);//取消移库
 
                //对接取消车间订单接收
                if (applyPart.getSourceLocationId() != null) {
                    // 存在源库位,走单独逻辑
                    if (applyPart.getReplacePartId() != null) {
                        // 存在替代零件号,走单独逻辑
                        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_MOVE_PART_REPLACE_NO_OUTPUT, isNeedFinishApply);
                    } else {
                        if (applyPart.getScrapArrived() != null) {
                            // 如果存在报废数量,发放报废数量
                            qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_SCRAP_ISSUANCE, isNeedFinishApply);
                        }
                        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_MOVE_PART_NO_OUTPUT, isNeedFinishApply);
                    }
                } else if (applyPart.getReplacePartId() != null) {
                    // 存在替代零件号,走单独逻辑
                    qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_MOVE_PART_REPLACE, isNeedFinishApply);
                } else {
                    // 不存在替代零件号,走正常逻辑
                    if (applyPart.getScrapArrived() != null) {
                        qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.CANCEL_SCRAP_ISSUANCE, isNeedFinishApply);
                    }
                    qualityModuleDockIfsUtils.dockIfsByReportId(id,QualityModuleDockIfsUtils.SHOP_ORDER_CANCEL_REC_V2, isNeedFinishApply);
                }
 
            }
 
            return R.ok("检测汇报单取消提交成功!");
        }
    }
 
    /**
     * 筛选需要对接ifs的检测汇报明细数据
     * @param reportId
     * @return
     */
    public List<ApplyPart> filterSynIfsApplyParts(Long reportId){
        List<ApplyPart> applyPartList = applyPartMapper.selectListByReportId(reportId);
        List<ApplyPart> applyPartListFilter_last = new ArrayList<>();
        //过滤掉非产出报检的
        List<ApplyPart> applyPartListFilter = applyPartList.stream().filter(l -> !l.getIsErp()).collect(Collectors.toList());
        if(CollectionUtils.isNotEmpty(applyPartListFilter)){
            List<Long> applyPartIds = new ArrayList<>();
            for(int i = 0;i < applyPartListFilter.size();i++){
                if(applyPartListFilter.get(i).getIsQualified()){
                    //合格成立
                    Part part = partMapper.selectById(applyPartListFilter.get(i).getPartId());
                    if(part.getPlanningMethod().equals("A") || part.getPlanningMethod().equals("P")){
                        //根据零件id获取零件计划方法=A||P成立
                        //增加一个过滤条件:是否是最后一道工序,若是则对接ifs车间订单接收
                        if(reportUtils.isProdOutLastOperationBySystemNo(applyPartListFilter.get(i).getSystemNo())){
                            applyPartIds.add(applyPartListFilter.get(i).getId());//如果零件计划方法是A或是P,则记录其id
                        }
                    }
                }
            }
 
            //筛选出在id列表中的检测申请(1.过滤掉了非产出报检;2.过滤掉了不合格;3.过滤掉了虚拟件)
            //applyPartListFilter_last = applyPartMapper.selectList(Wrappers.<ApplyPart>lambdaQuery().in(ApplyPart::getId,applyPartIds));//用不到先注释
        }
        return applyPartListFilter_last;
    }
 
    /**
     * 车间订单接收、取消接收
     * @param applyPartListSynIfs
     * @param report
     * @param dir "re":接收;"unre":取消接收
     */
    public void shopOrderReceive(List<ApplyPart> applyPartListSynIfs,Report report,String dir){
        //拼接inAttr
        //对接车间订单接收
        IfsShopOrderDTO ifsShopOrderDTO = new IfsShopOrderDTO();
        ifsShopOrderDTO.setRECORD_ID(report.getReportNo());
        List<IfsShopOrderDTO.DataBean> dataBeanList = new ArrayList<>();//批量标识
 
 
        for(int i = 0;i < applyPartListSynIfs.size();i++){
            if(applyPartMapper.isLastOperationBySystemNo(applyPartListSynIfs.get(i).getSystemNo()) && !report.getReportType().equals(Apply.PRODUCT_APPLY)){
                continue;//是最后一道工序,且不是成品检,则跳过
            }
            SubmitReportDTO submitReportDTO = baseMapper.getManufacturingOrderInfo(applyPartListSynIfs.get(i).getId());
            IfsShopOrderDTO.DataBean batchInfo = new IfsShopOrderDTO.DataBean();
            batchInfo.setORDER_NO(submitReportDTO.getIfsOrderNo());//车间订单号
            batchInfo.setRELEASE_NO(submitReportDTO.getIfsReleaseNo());//下达号
            batchInfo.setSEQUENCE_NO(submitReportDTO.getIfsSequenceNo());//序列号
            batchInfo.setPART_NO(submitReportDTO.getPartNo());//零件号
            batchInfo.setLOT_BATCH_NO(submitReportDTO.getIfsBatchNo());//ifs批次号
            batchInfo.setQUANTITY(submitReportDTO.getQtyArrived());//接收数量
            batchInfo.setSHIFT_DATE(submitReportDTO.getNowDutyDate());//班次日期
            if("早".equals(submitReportDTO.getShiftName().substring(0,1))){
                batchInfo.setSHIFT_TYPE("白");
            }else if("夜".equals(submitReportDTO.getShiftName().substring(0,1))) {
                batchInfo.setSHIFT_TYPE("夜");
            }
            batchInfo.setOUT_SYS_LOT_BAT_NO(submitReportDTO.getOutBatchNo());//SN号
            //batchInfo.setLOCATION_NO(getIfsLocationArrivedByWorkstationId(submitReportDTO.getWorkstationId()));
            batchInfo.setLOCATION_NO(reportUtils.getIfsLocationArrivedBySystemNo(applyPartListSynIfs.get(i).getSystemNo()));
            dataBeanList.add(batchInfo);
        }
        ifsShopOrderDTO.setBATCH_INFO(dataBeanList);
        Gson gson = new Gson();
        String jsonstr = gson.toJson(ifsShopOrderDTO);
        JSONObject jsonObject = JSONObject.parseObject(jsonstr);//解决序列化时自动将大写转小写问题
 
        //JSONObject jsonObject = (JSONObject) JSONObject.toJSON(ifsShopOrderDTO);
 
        R res;
        if(dir.equals("re")){
 
            res = ifsFeignClient.importSoReceiveStd(jsonObject,true);
        }else if(dir.equals("unre")){
            res = ifsFeignClient.importSoUnReceiveStd(jsonObject,true);
        }else{
            throw new RuntimeException("车间订单接收/取消接收方向码错误!");
        }
 
        if(res.getCode() != 0){
            if(dir.equals("re")){
                throw new RuntimeException("ifs车间订单接收失败;erromsg:" + res.getMsg());
            }else{
                throw new RuntimeException("ifs车间订单取消接收失败;erromsg:" + res.getMsg());
            }
        }
    }
 
    /**
     * 根据工作站id获取ifs接收库位
     * @param workstationId
     * @return
     */
    public String getIfsLocationArrivedByWorkstationId(Long workstationId){
        String ifsLocation = baseMapper.getIfsLocationArrivedByWorkstationId(workstationId,LOCATION_TYPE_QUALIFIED);//只有合格的才对接ifs车间订单接收,不合格的ifs无需接收
        if(StringUtils.isBlank(ifsLocation)){
            throw new RuntimeException("通过工作站id:" + workstationId + "无法获取ifs接收库位!");
        }else{
            return ifsLocation;
        }
    }
 
    @Override
    public boolean isApplyReportIsSubmitByReportId(Long id){
        Report report = baseMapper.selectById(id);
        if(report == null){
            throw new RuntimeException("检测汇报状态获取失败!");
        }else{
            if(report.getIsSubmit() == null || !report.getIsSubmit()){
                return false;//检测汇报未提交
            }else{
                return true;//检测汇报已提交
            }
        }
    }
 
    @Override
    public ApplyPartDTO createReport(Long applyPartId, String applyType, String reportPerson) {
        synchronized (applyPartId.toString().intern()) {
            // 校验检测零件是否已绑定检测汇报
            ApplyPart applyPart = this.applyPartMapper.selectById(applyPartId);
            if (applyPart.getReportId() != null && this.getById(applyPart.getReportId()) != null) {
                throw new RuntimeException("检测零件已绑定检测汇报");
            }
 
            Report report = new Report();
            report.setReportType(applyType);
            report.setReportPerson(reportPerson);
            // 创建检测汇报
            this.save(report);
 
            // 生成抽检记录
            Long samplingReportId = this.reportSamplingRecordService.generateSamplingRecord(applyPart.getSystemNo(), report.getId(), applyType);
 
            // 更新检测零件的检测汇报id
            Part part = this.partMapper.selectById(applyPart.getPartId());
            applyPart.setExaminer(part.getExaminer());
            applyPart.setReportId(report.getId());
            this.applyPartMapper.updateById(applyPart);
 
            //2.如果是绑定汇报,把检测结果状态打成检测中
            this.applyPartService.changeStatus(applyPart.getSystemNo(), ResultStateStringValues.TESTING, null, applyType);
            //新增报检后,需要将检测汇报状态改为未检测
            this.applyPartService.changeCheckState(applyPart);
            //如果不存在汇报样品则自动创建一条汇报样品
            if (samplingReportId == null) {
                List<ReportSample> reportSampleList = this.reportSampleMapper.selectList(Wrappers.<ReportSample>lambdaQuery().eq(ReportSample::getReportId,applyPart.getReportId()));
                if(CollectionUtils.isEmpty(reportSampleList)){
                    ReportSample reportSample = new ReportSample();
                    reportSample.setReportId(applyPart.getReportId());
                    reportSample.setSystemNo(applyPart.getSystemNo());
                    reportSample.setTestStandardNo(applyPart.getTestStandardNo());
                    reportSample.setTestStandardId(applyPart.getMoTestStandardId());
                    reportSample.setIsMoTestStandard(true);
                    reportSampleList.add(reportSample);
                    this.reportSampleService.saveBatchList(reportSampleList);
                }
            } else {
                // 生成新的检测样品记录
                // 如果存在抽检规则记录,则将抽检规则记录样品记录复制为当前样品记录
                List<ReportSample> reportSampleList = this.reportSampleMapper.selectList(Wrappers.<ReportSample>lambdaQuery().eq(ReportSample::getReportId, samplingReportId));
                if (CollectionUtils.isEmpty(reportSampleList)) {
                    Report samplingReport = this.getById(samplingReportId);
                    throw new RuntimeException("抽检检测汇报->" + samplingReport.getReportNo() + ",检测汇报不存在样品记录");
                }
                ReportSample reportSample = new ReportSample();
                reportSample.setReportId(applyPart.getReportId());
                reportSample.setSystemNo(applyPart.getSystemNo());
                reportSample.setTestStandardNo(reportSampleList.get(0).getTestStandardNo());
                reportSample.setTestStandardId(reportSampleList.get(0).getTestStandardId());
                reportSample.setIsMoTestStandard(reportSampleList.get(0).getIsMoTestStandard());
                reportSampleService.insert(reportSample);
 
                // 抽检规则记录样品记录复制为当前样品记录
                reportSampleItemMapper.copyReportSampleItem(reportSampleList.get(0).getId(), reportSample.getId());
            }
 
 
            ApplyPartDTO result = this.applyPartMapper.getApplyPartDtoById(applyPartId);
            List<ApplyPartFile> applyPartFiles = this.applyPartFileMapper.selectList(Wrappers.<ApplyPartFile>lambdaQuery().eq(ApplyPartFile::getApplyPartId, applyPartId));
            result.setApplyPartFileList(applyPartFiles);
            List<ReportSample> reportSamples = reportSampleMapper.selectList(Wrappers.<ReportSample>lambdaQuery().eq(ReportSample::getReportId, applyPart.getReportId()));
            result.setReportSampleList(reportSamples);
            // 如果不存在产出时间,标记为非库存报检
            if (result.getProduceTime() == null) {
                result.setIsNotOutCheck(true);
            }
            return result;
        }
    }
}