李林
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
/*
 *    Copyright (c) 2018-2025, ztt All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: ztt
 */
package com.chinaztt.mes.warehouse.service.impl;
 
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.basic.util.DictUtils;
import com.chinaztt.mes.common.numgen.NumberGenerator;
import com.chinaztt.mes.warehouse.dto.*;
import com.chinaztt.mes.warehouse.entity.*;
import com.chinaztt.mes.warehouse.mapper.*;
import com.chinaztt.mes.warehouse.service.PackagingService;
import com.chinaztt.mes.warehouse.state.constant.LocationTypeStringValues;
import com.chinaztt.mes.warehouse.state.constant.ReportCodeStringValues;
import com.chinaztt.mes.warehouse.state.escort.constant.EscortEvents;
import com.chinaztt.mes.warehouse.state.splittask.constant.SplitTaskStateStringValues;
import com.chinaztt.mes.warehouse.util.StockUtils;
import com.chinaztt.mes.warehouse.util.TransactionType;
import com.chinaztt.mes.warehouse.util.WareHouseUtils;
import com.chinaztt.ztt.admin.api.entity.SysDictItem;
import com.chinaztt.ztt.admin.api.feign.RemoteParamService;
import com.chinaztt.ztt.common.core.constant.SecurityConstants;
import com.chinaztt.ztt.common.core.util.R;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
 
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * 包装主表
 *
 * @author sunxl
 * @date 2021-06-03 13:56:52
 */
@Service
@AllArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class PackagingServiceImpl extends ServiceImpl<PackagingMapper, Packaging> implements PackagingService {
    private NumberGenerator<Packaging> numberGenerator;
    private PackagingItemMapper packagingItemMapper;
    private PartMapper partMapper;
    private PackingBean packingBean;
    private PackagingStaffMapper packagingStaffMapper;
    private DictUtils dictUtils;
    private SplitTaskMapper splitTaskMapper;
    private StockMapper stockMapper;
    private StockUtils stockUtils;
    private WareHouseUtils wareHouseUtils;
    private StockConfigBean stockConfigBean;
    private IfsFeignClient ifsFeignClient;
    private RemoteParamService remoteParamService;
 
    private final static String TX_PACK_WEIGHT_DIFF_LIMIT_VALUE = "TX_PACK_WEIGHT_DIFF_LIMIT_VALUE";
 
    @Override
    public Packaging fullSave(PackagingDTO packagingDTO) {
        Packaging newPackaging = baseMapper.selectOne(Wrappers.<Packaging>lambdaQuery().eq(Packaging::getNo, packagingDTO.getNo()));
        if (newPackaging != null) {
            throw new RuntimeException("包装箱号重复:" + newPackaging.getNo());
        }
 
        if (StringUtils.isBlank(packagingDTO.getNo())) {
            throw new RuntimeException("箱号不可为空!");
        }
 
        //射频包装编号取消自动生成
        //packagingDTO.setNo(numberGenerator.generateNumberWithPrefix(Packaging.DIGIT, Packaging.PREFIX, Packaging::getNo));
        //射频不需要计算这个
        //packagingDTO.setMetre(packagingDTO.getEndMetre().subtract(packagingDTO.getStartMetre()));//根据开始、结束米标自动计算米标
 
//        if (StringUtils.isNotBlank(packagingDTO.getReelType())){
//            //获取字典的数组值
//            List<SysDictItem> dict = dictUtils.getDict("reel_weight");
//            if (CollectionUtil.isNotEmpty(dict)){
//                dict.forEach(a -> {
//                    if (a.getLabel().equals(packagingDTO.getReelType())){
//                        packagingDTO.setRealWeight(new BigDecimal(a.getValue()));
//                    }
//                });
//            }
//        }
        baseMapper.insert(packagingDTO);
 
 
        if (CollectionUtil.isNotEmpty(packagingDTO.getStaffIds())) {
            for (Long id : packagingDTO.getStaffIds()) {
                PackagingStaff packagingStaff = new PackagingStaff();
                packagingStaff.setStaffId(id);
                packagingStaff.setPackagingId(packagingDTO.getId());
                packagingStaffMapper.insert(packagingStaff);
            }
        }
        return packagingDTO;
    }
 
    @Override
    public Packaging addPackagingStock(PackagingDTO packagingDTO) {
        if (wareHouseUtils.isPackConfirm(packagingDTO.getId())) {
            throw new RuntimeException("包装已提交->冻结该操作");
        }
 
        Packaging packaging = baseMapper.selectById(packagingDTO.getId());
        BigDecimal weight = BigDecimal.ZERO;
        //说明请求该接口时,前端已经通过SN号调库存接口获取了零件库存信息
        if (CollectionUtil.isNotEmpty(packagingDTO.getStockList())) {
            BigDecimal number = BigDecimal.ZERO;
            //这边传过来的库存信息为什么是一个list?
            for (Stock stock : packagingDTO.getStockList()) {
                //判断是否已经添加过当前系统号
                int count = packagingItemMapper.selectCount(Wrappers.<PackagingItem>lambdaQuery().eq(PackagingItem::getStockId, stock.getId()));
                if (count > 0) {
                    throw new RuntimeException("该系统号已经经过包装,请选择其它系统号");
                }
                PackagingItem packagingItem = new PackagingItem();
 
                //计算当前实时库存的零件的理论重量
                Part part = partMapper.selectById(stock.getPartId());//根据零件id获取零件对象
                if (part != null) {
                    weight = weight.add(part.getWeight().multiply(stock.getAvailableStockQuantity()));//理论重量=单位重量*可用库存数量 累加
                    packagingItem.setTheoryWeight(part.getWeight().multiply(stock.getAvailableStockQuantity()));//明细行的理论计算重量
                }
 
                packagingItem.setOutBatchNo(stock.getPartBatchNo());//批次号
                packagingItem.setPackageQty(stock.getAvailableStockQuantity());//包装数量=可用库存数量
                packagingItem.setPartId(stock.getPartId());//零件id
                packagingItem.setSystemNo(stock.getSystemNo());//报工产出系统编号
                packagingItem.setPackagingId(packagingDTO.getId());//包装主表id
                packagingItem.setStockId(stock.getId());//实时库存id
                packagingItem.setInLocationId(packagingDTO.getInLocationId());//至库位id
                packagingItem.setLocationId(stock.getLocationId());//库位id
                packagingItem.setIfsBatchNo(stock.getIfsBatchNo());//ifs批次号
                packagingItemMapper.insert(packagingItem);
                number = number.add(stock.getAvailableStockQuantity());//可用数量累加
            }
            //更新包装主表
            //包装净重 = 包装净重 + 明细理论重量
            packaging.setNetWeight(packaging.getNetWeight().add(weight));
            //毛重 = 净重 + 包装重量
            if(null != packaging.getNetWeight() && null != packaging.getPackWeight()){
                packaging.setGrossWeight(packaging.getNetWeight().add(packaging.getPackWeight()));
            }
            //差异重量 = 净重 - 实际重量
            if(null != packaging.getNetWeight() && null != packaging.getRealWeight()){
                packaging.setDifferenceWeight(packaging.getNetWeight().subtract(packaging.getRealWeight()));
            }
            //装箱数量
            packaging.setNumber(packaging.getNumber().add(number));
            //校验理论装箱数量
            if(packaging.getNumber().compareTo(packaging.getTheoreticalNumber()) == 1){
                throw new RuntimeException("实际数量不可以超过理论装箱数量");
            }
            //不在明细新增中更新净重,在保存主表时自动计算净重
            //packaging.setNetWeight(packaging.getGrossWeight().subtract(packaging.getPackWeight()));//净重等于毛重-包装重量
            //差异重量也不在明细新增中更新,在保存主表时自动结算差异重量,明细表新增一个理论计算重量,用于保存理论计算重量
            //packaging.setDifferenceWeight(packaging.getNetWeight().subtract(packaging.getRealWeight()));//差异重量=理论重量-实际重量
            //packaging.setNumber(packaging.getNumber().add(number));//可用数量/包装数量
 
            //判断数量和理论装箱数量,数量不可以超过理论装箱数量(移植跳线的校验)理论装箱数量是怎么来的???,估计这边会跟据包装尺寸获取包装的理论数量,先注释掉
//            if (packaging.getNumber().compareTo(packaging.getTheoreticalNumber())==1){
//                throw new RuntimeException("实际数量不可以超过理论装箱数量");
//            }
 
 
            baseMapper.updateById(packaging);
        } else {
            throw new RuntimeException("查询的实时库存为空");
        }
        return packaging;
    }
 
    @Override
    public Boolean removePackagingById(Long id) {
        if (wareHouseUtils.isPackConfirm(id)) {
            throw new RuntimeException("包装已提交->冻结该操作");
        }
 
        baseMapper.deleteById(id);
        packagingItemMapper.delete(Wrappers.<PackagingItem>lambdaQuery().eq(PackagingItem::getPackagingId, id));
        return true;
    }
 
    @Override
    public IPage<PackagingDTO> getPackagingPage(Page page, QueryWrapper<PackagingDTO> gen) {
        return baseMapper.getPackagingPage(page, gen);
    }
 
    @Override
    public PackagingDTO getPackingById(Long id) {
        return baseMapper.getPackingById(id);
    }
 
    @Override
    public boolean fullUpdate(PackagingDTO packagingDTO) {
        //校验包装编号(箱号)是否重复,射频的包装编号是可以修改的
        //判断逻辑:编号相等且行号不等,存在则重复
        Packaging newPackaging = baseMapper.selectOne(Wrappers.<Packaging>lambdaQuery().eq(Packaging::getNo, packagingDTO.getNo()).ne(Packaging::getId, packagingDTO.getId()));
        if (newPackaging != null) {
            throw new RuntimeException("包装箱号重复:" + newPackaging.getNo());
        }
 
        if (wareHouseUtils.isPackConfirm(packagingDTO.getId())) {
            throw new RuntimeException("包装已提交->冻结该操作");
        }
 
        //射频主表无需计算米标(留着也不报错)
        if(null != packagingDTO.getEndMetre() && null != packagingDTO.getStartMetre()){
            packagingDTO.setMetre(packagingDTO.getEndMetre().subtract(packagingDTO.getStartMetre()));//计算米标
        }
        //射频主表无需盘具重量(留着也不报错)
        //根据盘具类型,获取盘具重量
        if (StringUtils.isNotBlank(packagingDTO.getReelType())) {
            //获取字典的数组值
            List<SysDictItem> dict = dictUtils.getDict("reel_weight");
            if (CollectionUtil.isNotEmpty(dict)) {
                dict.forEach(a -> {
                    if (a.getLabel().equals(packagingDTO.getReelType())) {
                        packagingDTO.setRealWeight(new BigDecimal(a.getValue()));
                    }
                });
            }
        }
        //根据包装尺寸获取包装重量
        //如果存在包装尺寸,则获取包装重量
        if (StringUtils.isNotBlank(packagingDTO.getPackSize())) {
            //获取数据字典
            List<SysDictItem> dictItemList = dictUtils.getDict("pack_size_weight");
            if (CollectionUtil.isNotEmpty(dictItemList)) {
                dictItemList.forEach(a -> {
                    if (a.getLabel().equals(packagingDTO.getPackSize())) {
                        if(StringUtils.isNotBlank(a.getDescription())){
                            packagingDTO.setPackWeight(new BigDecimal(a.getDescription()));//包装重量
                        }
                    }
                });
            }
        }
 
        //如果包装重量&毛重存在,则更新净重
//        if (packagingDTO.getPackWeight() != null && packagingDTO.getGrossWeight() != null) {
//            packagingDTO.setNetWeight(packagingDTO.getGrossWeight().subtract(packagingDTO.getPackWeight()));
//        }
 
        //更新差异重量(差异重量=理论计算重量-净重)
        //根据主表id获取明细行的理论计算重量总和
        Double theoryWeight = packagingItemMapper.getTheoryWeightTotal(packagingDTO.getId());
        //判断不为 null
        if (null != theoryWeight) {
            //包装总净重 = 明细的理论重量和
            packagingDTO.setNetWeight(new BigDecimal(theoryWeight));
 
            //毛重 = 净重 + 包装重量
            if(null != packagingDTO.getPackWeight() && null != packagingDTO.getNetWeight()){
                packagingDTO.setGrossWeight(packagingDTO.getNetWeight().add(packagingDTO.getPackWeight()));
            }
 
            //差异重量 = 理论重量 - 实际净重(该计算方式作废)
            //packagingDTO.setDifferenceWeight(new BigDecimal(theoryWeight).subtract(packagingDTO.getNetWeight()));
            //差异重量 = 净重 - 实际重量
            packagingDTO.setDifferenceWeight(packagingDTO.getNetWeight().subtract(packagingDTO.getRealWeight()));
        }
        baseMapper.updateById(packagingDTO);
 
        //射频不需要用到包装人员,放在这也不会报错
        packagingStaffMapper.delete(Wrappers.<PackagingStaff>lambdaQuery().eq(PackagingStaff::getPackagingId, packagingDTO.getId()));
        if (CollectionUtil.isNotEmpty(packagingDTO.getStaffIds())) {
            for (Long id : packagingDTO.getStaffIds()) {
                PackagingStaff packagingStaff = new PackagingStaff();
                packagingStaff.setStaffId(id);
                packagingStaff.setPackagingId(packagingDTO.getId());
                packagingStaffMapper.insert(packagingStaff);
            }
        }
        //return false;//return 恒等于fasle???
        return true;
    }
 
    @Override
    public boolean batchSave(List<PackagingDTO> packagingDTOList) {
        packagingDTOList.forEach(packagingDTO -> {
 
            SplitTask splitTask = splitTaskMapper.selectById(packagingDTO.getSplitTaskId());
            splitTask.setStatus(SplitTaskStateStringValues.USED);
            splitTaskMapper.updateById(splitTask);
 
            packagingDTO.setNo(numberGenerator.generateNumberWithPrefix(Packaging.DIGIT, Packaging.PREFIX, Packaging::getNo));
            packagingDTO.setStatus(SplitTaskStateStringValues.UNSUBMIT);
            baseMapper.insert(packagingDTO);
        });
        return true;
    }
 
    @Override
    public synchronized boolean submit(Long id) {
        String billNo = RandomStringUtils.random(10, true, true);
        PackagingDTO packaging = baseMapper.getPackingById(id);
        SplitTask splitTask = splitTaskMapper.selectById(packaging.getSplitTaskId());
        if (null == splitTask) {
            throw new RuntimeException("分割记录丢失");
        }
        Stock stock = stockMapper.selectById(splitTask.getStockId());
        if (null == stock) {
            throw new RuntimeException("库存记录丢失");
        }
        BigDecimal num = BigDecimal.ONE;
        if (SplitTaskStateStringValues.PACKM1.equals(packaging.getPackingManner())) {
            num = packaging.getCylinderNumber();
        } else if (SplitTaskStateStringValues.PACKM2.equals(packaging.getPackingManner())) {
            num = BigDecimal.ONE;
        }
        //库存事务
        stockUtils.createTransaction(stock.getStockQuantity(), packaging.getNumber().negate(), stock.getPartId(),
                stock.getLocationId(), stock.getPartBatchNo(), billNo, TransactionType.STOCK.getValue(), stock.getIfsBatchNo());
        //修改原来库存数据的库存
        stock.setStartMetre(packaging.getStartMetre());
        stock.setEndMetre(packaging.getEndMetre());
        stock.setCustomerOrderNo(packaging.getCustomerOrderNo());
        stock.setStockQuantity(stock.getStockQuantity().add(packaging.getNumber().negate()));
        stock.setReserveQuantity(stock.getReserveQuantity().add(packaging.getNumber().negate()));
        stockMapper.updateById(stock);
        List<Stock> stockList = stockMapper.selectList(Wrappers.<Stock>lambdaQuery().like(Stock::getPartBatchNo, stock.getPartBatchNo() + "_").orderByDesc(Stock::getPartBatchNo));
        int j = 0;
        if (!CollectionUtils.isEmpty(stockList)) {
            String partBatchNo = stockList.get(0).getPartBatchNo();
            j = Integer.parseInt(partBatchNo.substring(partBatchNo.length() - 3, partBatchNo.length()));
        }
        //新增库存数据
        for (int i = 1; i <= num.intValue(); i++) {
            j++;
            Stock stockInsert = new Stock();
            String partBatchNo = stock.getPartBatchNo() + "_" + String.format("%03d", j);
            stockInsert.setPartId(stock.getPartId());
            stockInsert.setPartBatchNo(partBatchNo);
            stockInsert.setLocationId(packaging.getInLocationId());
            stockInsert.setReserveQuantity(BigDecimal.ZERO);
            stockInsert.setStockQuantity(packaging.getNumber().divide(num, 6, BigDecimal.ROUND_HALF_UP));
            stockInsert.setAvailableStockQuantity(packaging.getNumber().divide(num, 6, BigDecimal.ROUND_HALF_UP));
            stockInsert.setSystemNo(stock.getSystemNo());
            stockInsert.setReelNumber(packaging.getRoutineReelNumber());
            stockInsert.setStartMetre(packaging.getStartMetre());
            stockInsert.setEndMetre(packaging.getEndMetre());
            stockInsert.setCustomerOrderNo(packaging.getCustomerOrderNo());
            stockMapper.insert(stockInsert);
            PackagingItem packagingItem = new PackagingItem();
            packagingItem.setOutBatchNo(partBatchNo);
            packagingItem.setPackageQty(packaging.getNumber().divide(num, 6, BigDecimal.ROUND_HALF_UP));
            packagingItem.setPackagingId(packaging.getId());
            packagingItem.setPartId(packaging.getPartId());
            packagingItem.setStockId(stockInsert.getId());
            packagingItem.setSystemNo(stock.getSystemNo());
            packagingItemMapper.insert(packagingItem);
            stockUtils.createTransaction(BigDecimal.ZERO, packaging.getNumber().divide(num, 6,
                    BigDecimal.ROUND_HALF_UP), stock.getPartId(), packaging.getInLocationId(), partBatchNo, billNo,
                    TransactionType.STOCK.getValue(), stock.getIfsBatchNo());
        }
        packaging.setStatus(SplitTaskStateStringValues.SUBMIT);
        baseMapper.updateById(packaging);
 
        return true;
    }
 
    @Override
    public R weighVerifyCheck(PackagingDTO packaging) {
        //目前前台传过来的值跟跳线的不一样,不能用前台穿过来的对象进行更新,后台需要重新查询一遍
        if(null == packaging.getId() || packaging.getId() == 0){
            throw new RuntimeException("传入包装主表id = 【" + packaging.getId() + "】信息异常");
        }else{
            packaging = baseMapper.getPackingById(packaging.getId());
            if(null == packaging){
                throw new RuntimeException("根据包装主表id = 【" + packaging.getId() + "】 --> 无法查询包装信息");
            }
        }
        String ok = "OK";
        String key = "result";
        String weight = "message";
        BigDecimal partWeight = BigDecimal.ZERO;
        //查询包装的从表
        List<PackagingItem> packagingItemList = packagingItemMapper.selectList(Wrappers.<PackagingItem>lambdaQuery().eq(PackagingItem::getPackagingId, packaging.getId()));
        JSONObject jsonObject = new JSONObject();
        try {
            //从地磅获取称重
            Map<String, Object> paramMap = new HashMap<>(16);
            String result = HttpRequest.get(packingBean.getHost()).form(paramMap).execute().body();
            //String result = "[{\"result\":\"OK\",\"message\":\"0.5\"}]";//测试用
            JSONArray jsonArray = JSONObject.parseArray(result);
            jsonObject = jsonArray.getJSONObject(0);
        } catch (Exception e) {
            throw new RuntimeException("调用接口失败");
        }
        if (packagingItemList.size() == 0) {
            throw new RuntimeException("包装的零件为空,请重新检查箱子");
        } else if (packagingItemList.size() > 1)  {
            //当从表不止一根产出,所以是最后的称重,先判断产出与理论装箱数量,数量必须要等于理论装箱数量
            if (packaging.getNumber().compareTo(packaging.getTheoreticalNumber()) != 0) {
                throw new RuntimeException("最后称重时,实际数量必须等于理论装箱数量");
            } else {
                if (jsonObject.getString(key).equals(ok)) {
                    packaging.setRealWeight(new BigDecimal(jsonObject.getString(weight)));
                    packaging.setDifferenceWeight(packaging.getNetWeight().subtract(packaging.getRealWeight()));
 
                    //称重防呆提醒
                    String res = remoteParamService.getByKey(TX_PACK_WEIGHT_DIFF_LIMIT_VALUE, SecurityConstants.FROM_IN).getData();
                    if (null == res) {
                        throw new RuntimeException("未设置称重防呆阈值");
                    }
                    int a = weighVerify(packaging.getDifferenceWeight(),res);
                    if(a<0){
                        return R.ok(ValidateWeighPackagingDTO.builder().success(Boolean.FALSE).message("实际重量偏小,偏差超过系统预设值【"+ res +"】,请确认是否继续称重?").build());
                    }else if(a>0){
                        return R.ok(ValidateWeighPackagingDTO.builder().success(Boolean.FALSE).message("实际重量偏大,偏差超过系统预设值【"+ res +"】,请确认是否继续称重?").build());
                    }else{
                        return R.ok(ValidateWeighPackagingDTO.builder().success(Boolean.TRUE).build());
                    }
 
                } else {
                    throw new RuntimeException("获取称重" + jsonObject.getString(weight));
                }
            }
        }
        return R.ok(ValidateWeighPackagingDTO.builder().success(Boolean.TRUE).build());
    }
 
 
    @Override
    public R getWeight(PackagingDTO packaging) {
        Boolean isRecException = packaging.getIsRecException();
        //目前前台传过来的值跟跳线的不一样,不能用前台穿过来的对象进行更新,后台需要重新查询一遍
        if(null == packaging.getId() || packaging.getId() == 0){
            throw new RuntimeException("传入包装主表id = 【" + packaging.getId() + "】信息异常");
        }else{
            packaging = baseMapper.getPackingById(packaging.getId());
            if(null == packaging){
                throw new RuntimeException("根据包装主表id = 【" + packaging.getId() + "】 --> 无法查询包装信息");
            }
        }
        String ok = "OK";
        String key = "result";
        String weight = "message";
        BigDecimal partWeight = BigDecimal.ZERO;
        //查询包装的从表
        List<PackagingItem> packagingItemList = packagingItemMapper.selectList(Wrappers.<PackagingItem>lambdaQuery().eq(PackagingItem::getPackagingId, packaging.getId()));
        JSONObject jsonObject = new JSONObject();
        try {
            //从地磅获取称重
            Map<String, Object> paramMap = new HashMap<>(16);
            String result = HttpRequest.get(packingBean.getHost()).form(paramMap).execute().body();
            //String result = "[{\"result\":\"OK\",\"message\":\"0.5\"}]";//测试用
            JSONArray jsonArray = JSONObject.parseArray(result);
            jsonObject = jsonArray.getJSONObject(0);
        } catch (Exception e) {
            throw new RuntimeException("调用接口失败");
        }
        if (packagingItemList.size() == 0) {
            throw new RuntimeException("包装的零件为空,请重新检查箱子");
        } else if (packagingItemList.size() == 1) {
            //当从表只有一根产出时,同步称重重量到产出零件的重量,并更新包装
            if (jsonObject.getString(key).equals(ok)) {
                //同步称重重量到产出零件的重量
                Part part = partMapper.selectOne(Wrappers.<Part>lambdaQuery().eq(Part::getId, packagingItemList.get(0).getPartId()));
                if (part != null) {
                    part.setWeight(new BigDecimal(jsonObject.getString(weight)));
                    partMapper.updateById(part);
                    Stock stock = stockMapper.selectById(packagingItemList.get(0).getStockId());
                    if (stock != null) {
                        partWeight = partWeight.add(part.getWeight().multiply(stock.getAvailableStockQuantity()));
                        //更新包装主表
                        packaging.setNetWeight(partWeight);
                        packaging.setDifferenceWeight(packaging.getNetWeight().subtract(packaging.getRealWeight()));
                        //更新毛重
                        packaging.setGrossWeight(packaging.getNetWeight().add(packaging.getPackWeight()));
                        //不是最后一把称重不需要设置 包装称重是否接收异常
                        packaging.setIsRecException(null);
                        //更新明细的重量(第一条称重明细的计算重量不是通过称重获取的单位重量)
                        packagingItemList.get(0).setTheoryWeight(packagingItemList.get(0).getPackageQty().multiply(part.getWeight()));
                        packagingItemMapper.updateById(packagingItemList.get(0));
                        baseMapper.updateById(packaging);
                    }
                }
            } else {
                throw new RuntimeException("获取称重" + jsonObject.getString(weight));
            }
        } else {
            //当从表不止一根产出,所以是最后的称重,先判断产出与理论装箱数量,数量必须要等于理论装箱数量
            if (packaging.getNumber().compareTo(packaging.getTheoreticalNumber()) != 0) {
                throw new RuntimeException("最后称重时,实际数量必须等于理论装箱数量");
            } else {
                if (jsonObject.getString(key).equals(ok)) {
                    packaging.setRealWeight(new BigDecimal(jsonObject.getString(weight)));
                    packaging.setDifferenceWeight(packaging.getNetWeight().subtract(packaging.getRealWeight()));
                    //更新毛重
                    packaging.setGrossWeight(packaging.getNetWeight().add(packaging.getPackWeight()));
                    packaging.setIsRecException(isRecException);
                    baseMapper.updateById(packaging);
                } else {
                    throw new RuntimeException("获取称重" + jsonObject.getString(weight));
                }
            }
        }
        return R.ok(packaging);
    }
 
 
 
 
    //称重防呆提醒
    public int weighVerify(BigDecimal differenceWeight,String res){
        //实际重量偏小
        if(differenceWeight.compareTo(BigDecimal.ZERO)<0){
            if(differenceWeight.abs().compareTo(new BigDecimal(res))>0){
                return -1;
            }
        }
        //实际重量偏大
        if(differenceWeight.compareTo(BigDecimal.ZERO)>0){
            if(differenceWeight.abs().compareTo(new BigDecimal(res))>0){
                return 1;
            }
        }
        return 0;
    }
 
 
 
 
    @Override
    public IPage<PackageReportDTO> getEveryDayReport(Page page, PackageReportDTO packageReportDTO) {
        return packagingItemMapper.getPackageReport(page, packageReportDTO);
    }
 
    @Override
    public R getPackJmreportUrl(String reportCode) {
        switch (reportCode) {
            case ReportCodeStringValues.GDHHL_HUAWEI:
                return R.ok(packingBean.getGdhhlHuawei());
            case ReportCodeStringValues.WEIGHT_LABLE:
                return R.ok(packingBean.getWeightLable());
            case ReportCodeStringValues.GW_HUAWEI:
                return R.ok(packingBean.getGwHuaweiUrl());
            case ReportCodeStringValues.GD_HUAWEI:
                return R.ok(packingBean.getGdHuaweiUrl());
            default:
                return R.failed("该报表code=" + reportCode + "->无法识别");
        }
    }
 
    @Override
    public R packConfirm(Long id) {
        if (wareHouseUtils.isPackConfirm(id)) {
            return R.failed("包装状态为=已确认->请勿重复确认");
        }
 
        List<MoveLibraryBoxDTO> moveLibraryBoxDTOList = packagingItemMapper.getMoveLibraryBoxDTOListBypackagingId(id);
 
        //数据校验
        R r = wareHouseUtils.checkMoveLibraryBox(moveLibraryBoxDTOList, id);
        if (r.getCode() == 1) {
            return R.failed(r.getMsg());
        }
 
        //更新包装主表确认状态
        baseMapper.updatePackagingIsConfirmById(id, true);
 
        //移库
        EscortEvents escortEvents = EscortEvents.COMPLETE;
        wareHouseUtils.packagingMoveLibrary(moveLibraryBoxDTOList, escortEvents, id);
 
        return R.ok(null, "操作成功");
    }
 
 
    @Override
    public R packCancelConfirm(Long id) {
        if (!wareHouseUtils.isPackConfirm(id)) {
            return R.failed("包装状态为=未确认->请勿重复取消");
        }
 
        List<MoveLibraryBoxDTO> moveLibraryBoxDTOList = packagingItemMapper.getMoveLibraryBoxDTOListBypackagingId(id);
 
        //数据校验
        R r = wareHouseUtils.checkMoveLibraryBox(moveLibraryBoxDTOList, id);
        if (r.getCode() == 1) {
            return R.failed(r.getMsg());
        }
 
        //更新包装主表确认状态
        baseMapper.updatePackagingIsConfirmById(id, false);
 
        //移库
        EscortEvents escortEvents = EscortEvents.CANCEL;
        wareHouseUtils.packagingMoveLibrary(moveLibraryBoxDTOList, escortEvents, id);
 
        return R.ok(null, "操作成功");
    }
 
    @Override
    public R getPackHeadBasicInfoList() {
        PackHeadBasicInfoDTO packHeadBasicInfoDTO = new PackHeadBasicInfoDTO();
        List<PackHeadBasicInfoDTO.DataBean> packSizeWeightList = new ArrayList<>();
        List<String> packSizeList = new ArrayList<>();//包装尺寸
        List<String> packMaterialList = new ArrayList<>();//包装材质
        List<String> locationNoList = new ArrayList<>();//库位编号
        List<SysDictItem> dictItemList;
        //包装尺寸-重量
        dictItemList = dictUtils.getDict("pack_size_weight");
        if (CollectionUtil.isNotEmpty(dictItemList)) {
            for (SysDictItem dictItem : dictItemList) {
                PackHeadBasicInfoDTO.DataBean dataBean = new PackHeadBasicInfoDTO.DataBean();
                dataBean.setPackSize(dictItem.getValue());
                dataBean.setPackWeight(dictItem.getDescription());
                packSizeWeightList.add(dataBean);
            }
        }
 
        //包装材质
        dictItemList = dictUtils.getDict("pack_material");
        if (CollectionUtil.isNotEmpty(dictItemList)) {
            for (SysDictItem dictItem : dictItemList) {
                packMaterialList.add(dictItem.getValue());
            }
        }
 
        //成品库位
        locationNoList = packagingItemMapper.getEnableFinishProdList(LocationTypeStringValues.FINISHLOCATIONCODE);
 
        packHeadBasicInfoDTO.setPackSizeWeightList(packSizeWeightList);
        packHeadBasicInfoDTO.setPackMaterialList(packMaterialList);
        packHeadBasicInfoDTO.setLocationNoList(locationNoList);
 
 
        return R.ok(packHeadBasicInfoDTO);
    }
 
 
    @Override
    public R getPackagingAndSizeByPackagingNo(String packagingNo) {
        Packaging packaging = baseMapper.selectOne(Wrappers.<Packaging>lambdaQuery().eq(Packaging::getNo, packagingNo));
        if(packaging==null){
            throw new RuntimeException("{"+packagingNo+"}未进行包装登记");
        }
        List<PackagingItem> packagingItemList = packagingItemMapper.getPackagingItemList(packagingNo);
        if(CollectionUtil.isEmpty(packagingItemList)){
            throw new RuntimeException("{"+packagingNo+"}未进行扫码装箱");
        }
        List<String> outBatchNoList = packagingItemList.stream().map(r -> r.getOutBatchNo()).collect(Collectors.toList());
        PackingPdaDTO packingPdaDTO = new PackingPdaDTO();
        BeanUtils.copyProperties(packaging, packingPdaDTO);
        packingPdaDTO.setItemSize(packagingItemList.size());
        packingPdaDTO.setSnList(outBatchNoList);
        return R.ok(packingPdaDTO);
    }
}