李林
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
package com.chinaztt.mes.production.service.impl;
 
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.mes.basic.dto.LocationIfsMoveDTO;
import com.chinaztt.mes.basic.entity.Location;
import com.chinaztt.mes.basic.entity.Part;
import com.chinaztt.mes.basic.entity.Workstation;
import com.chinaztt.mes.basic.entity.WorkstationLocation;
import com.chinaztt.mes.basic.mapper.LocationMapper;
import com.chinaztt.mes.basic.mapper.PartMapper;
import com.chinaztt.mes.basic.mapper.WorkstationLocationMapper;
import com.chinaztt.mes.basic.mapper.WorkstationMapper;
import com.chinaztt.mes.basic.util.PartUtils;
import com.chinaztt.mes.common.constant.Constant;
import com.chinaztt.mes.plan.entity.MoStructureComponent;
import com.chinaztt.mes.production.dto.FeedingDTO;
import com.chinaztt.mes.production.dto.FeedingInDTO;
import com.chinaztt.mes.production.entity.Feeding;
import com.chinaztt.mes.production.entity.FeedingRecord;
import com.chinaztt.mes.production.entity.OperationTask;
import com.chinaztt.mes.production.mapper.FeedingMapper;
import com.chinaztt.mes.production.mapper.FeedingRecordMapper;
import com.chinaztt.mes.production.mapper.OperationTaskMapper;
import com.chinaztt.mes.production.service.FeedingService;
import com.chinaztt.mes.production.service.ProductMainService;
import com.chinaztt.mes.production.util.FeedingUtils;
import com.chinaztt.mes.quality.entity.ApplyPart;
import com.chinaztt.mes.quality.entity.Report;
import com.chinaztt.mes.quality.mapper.ApplyPartMapper;
import com.chinaztt.mes.quality.mapper.ReportMapper;
import com.chinaztt.mes.warehouse.dto.FeedingStockDTO;
import com.chinaztt.mes.warehouse.dto.StockDTO;
import com.chinaztt.mes.warehouse.entity.JoinStockOrder;
import com.chinaztt.mes.warehouse.entity.Stock;
import com.chinaztt.mes.warehouse.mapper.JoinStockOrderMapper;
import com.chinaztt.mes.warehouse.mapper.StockMapper;
import com.chinaztt.mes.warehouse.service.StockService;
import com.chinaztt.mes.warehouse.util.StockUtils;
import com.chinaztt.mes.warehouse.util.TransactionType;
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.apache.commons.lang3.StringUtils;
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 cxf
 * @date 2020-11-12 10:48:37
 */
@Service
@AllArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class FeedingServiceImpl extends ServiceImpl<FeedingMapper, Feeding> implements FeedingService {
    private StockUtils stockUtils;
    private FeedingUtils feedingUtils;
    private FeedingRecordMapper feedingRecordMapper;
    private StockMapper stockMapper;
    private WorkstationLocationMapper workstationLocationMapper;
    private WorkstationMapper workstationMapper;
    private PartMapper partMapper;
    private ApplyPartMapper applyPartMapper;
    private ReportMapper reportMapper;
    private PartUtils partUtils;
    private JoinStockOrderMapper joinStockOrderMapper;
    private OperationTaskMapper operationTaskMapper;
    private LocationMapper locationMapper;
    private ProductMainService productMainService;
    private RemoteParamService remoteParamService;
    private StockService stockService;
 
 
    @Override
    public List<FeedingDTO> getFeedingByWorkstationId(QueryWrapper<FeedingDTO> gen) {
        return baseMapper.getFeedingByParam(gen);
    }
 
    /**
     * 旧版本投料,将物料从线边仓或者预留投入到 投料登记中 再从投料登记中扣除数量 该方法暂停使用中
     *
     * @param feedingInDTO
     * @return
     */
    @Override
    public boolean saveList(FeedingInDTO feedingInDTO) {
        List<FeedingDTO> feedingList = feedingInDTO.getFeeds();
        for (FeedingDTO feeding : feedingList) {
            if ("joinStocker".equals(feedingInDTO.getFeedingFrom())) {
                // 1.去修改预留中零件数量
                JoinStockOrder joinStockOrder = joinStockOrderMapper.selectById(feeding.getJoinStockOrderId());
                Part part = partMapper.selectOne(Wrappers.<Part>lambdaQuery().eq(Part::getPartNo, joinStockOrder.getPartNo()));
                feeding.setStockId(joinStockOrder.getStockId());
                feeding.setPartId(part.getId());
                stockUtils.joinStockerChange(feeding.getJoinStockOrderId(), feeding.getSuppliedQuantity());
            }
            if ("stocker".equals(feedingInDTO.getFeedingFrom())) {
                // 1.去修改线边仓零件数量
                stockUtils.updateById(feeding.getStockId(), feeding.getSuppliedQuantity().negate(), BigDecimal.ZERO, BigDecimal.ZERO, null, null, "FEED");
            }
            // 2.投料登记,保存投料记录
            FeedingRecord feedingRecord = new FeedingRecord();
            feedingRecord.setFeedingQuantity(feeding.getSuppliedQuantity());
            // 2.1 根据工作站和零件\批次号去查询投料记录,如果存在就加上去
            Feeding feedingExist = baseMapper.selectOne(Wrappers.<Feeding>lambdaQuery()
                    .eq(Feeding::getWorkstationId, feeding.getWorkstationId()).eq(Feeding::getPartId, feeding.getPartId())
                    .eq(Feeding::getPartBatchNo, feeding.getPartBatchNo()).eq(Feeding::getSystemNo, feeding.getSystemNo())
                    .eq(Feeding::getStockId, feeding.getStockId()));
            if (feedingExist != null) {
                feedingUtils.updateById(feedingExist.getId(), feedingRecord.getFeedingQuantity(), feedingRecord.getFeedingQuantity());
                feedingRecord.setFeedingId(feedingExist.getId());
            } else {
                feeding.setResidualQuantity(feeding.getSuppliedQuantity());
                baseMapper.insert(feeding);
                feedingRecord.setFeedingId(feeding.getId());
            }
            // 2.2 保存投料记录
            feedingRecordMapper.insert(feedingRecord);
        }
        return true;
    }
 
    /**
     * 投料,将物料从线边仓或者预留 移库到已投料库位置中
     *
     * @param feedingInDTO
     * @return
     */
    @Override
    public boolean feeding(FeedingInDTO feedingInDTO) {
 
        String billNo = RandomStringUtils.random(10, true, true);
        List<FeedingDTO> feedingList = feedingInDTO.getFeeds();
        OperationTask operationTask = operationTaskMapper.selectById(feedingInDTO.getOperationTaskId());
        if (operationTask == null) {
            throw new RuntimeException("未找到工序任务");
        }
        Map<Long, List<MoStructureComponent>> componentList = productMainService.getComponentList(operationTask.getId());
        if (componentList.isEmpty()) {
            throw new RuntimeException("未找到所需物料");
        }
//        // 校验是否原材料检
//        Part basicPart = partMapper.selectOne(new LambdaQueryWrapper<Part>().eq(Part::getPartNo, feedingList.get(0).getPartNo()));
//        if (basicPart == null){
//            throw new RuntimeException("零件不存在");
//        }
//        if (basicPart.getTestRuleType()!=null && basicPart.getTestRuleType() == 1){
//            List<ApplyPart> applyParts = applyPartMapper.selectList(new LambdaQueryWrapper<ApplyPart>().eq(ApplyPart::getPartNo, basicPart.getPartNo()));
//            if (CollectionUtil.isEmpty(applyParts)){
//                throw new RuntimeException("请先进行原材料检");
//            }
//            List<Long> reportIds = applyParts.stream().map(ApplyPart::getReportId).collect(Collectors.toList());
//
//            List<Report> reports = reportMapper.selectList(new LambdaQueryWrapper<Report>().in(Report::getId, reportIds));
//            List<Report> collect = reports.stream().filter(e -> "01checked".equals(e.getCheckState())).collect(Collectors.toList());
//            if (CollectionUtil.isEmpty(collect)){
//                throw new RuntimeException("请先进行原材料检");
//            }
//        }
        // 存在行项号进行ifs移库
        List<Part> parts = null;
        Long locationId = null;
        if (!"erp".equals(feedingInDTO.getSource())) {
            for (FeedingDTO feedingDTO : feedingList) {
                if (!componentList.containsKey(feedingDTO.getPartId())) {
                    throw new RuntimeException(feedingDTO.getPartName() + "不在该工序所需物料中,请确认");
                }
            }
        } else {
            Set<Long> partIds = componentList.keySet();
            parts = partMapper.selectBatchIds(partIds);
            for (FeedingDTO feedingDTO : feedingList) {
                if (parts.stream().noneMatch(e -> e.getPartNo().equals(feedingDTO.getPartNo()))) {
                    throw new RuntimeException(feedingDTO.getPartName() + "不在该工序所需物料中,请确认");
                }
            }
 
            List<Location> locations = locationMapper.selectList(new LambdaQueryWrapper<Location>().eq(Location::getLocName, "erp入库库位").or().eq(Location::getLocName, "ERP入库库位"));
            if (CollectionUtil.isEmpty(locations)) {
                throw new RuntimeException("请取基础数据添加ERP入库库位");
            }
            locationId = locations.get(0).getId();
 
        }
 
        for (FeedingDTO feeding : feedingList) {
            if ("joinStocker".equals(feedingInDTO.getFeedingFrom())) {
                // 1.去修改预留中零件数量
                JoinStockOrder joinStockOrder = joinStockOrderMapper.selectById(feeding.getJoinStockOrderId());
                Part part = partMapper.selectOne(Wrappers.<Part>lambdaQuery().eq(Part::getPartNo, joinStockOrder.getPartNo()));
                feeding.setStockId(joinStockOrder.getStockId());
                feeding.setPartId(part.getId());
                stockUtils.joinStockerChange(feeding.getJoinStockOrderId(), feeding.getSuppliedQuantity());
            }
            if ("stocker".equals(feedingInDTO.getFeedingFrom())) {
                // 2.去修改线边仓零件数量
//                if(!"erp".equals(feedingInDTO.getSource())) {
                stockUtils.updateById(feeding.getStockId(), feeding.getSuppliedQuantity().negate(), BigDecimal.ZERO,
                        BigDecimal.ZERO, null, billNo, "FEED");
//                }else{
//                    StockDTO stockDTO = new StockDTO();
//                    stockDTO.setNum(feeding.getSuppliedQuantity());
//                    stockDTO.setPartNo(basicPart.getPartNo());
//                    stockDTO.setPartBatchNo("");
//                    R r = stockService.lockStore(stockDTO);
//                    if (r.getCode() != 0){
//                        throw new RuntimeException(r.getMsg());
//                    }
//                }
            }
            // 3.移库将库存移到已投料库
            if ("erp".equals(feedingInDTO.getSource())) {
                Part part = parts.stream().filter(e -> e.getPartNo().equals(feeding.getPartNo())).findFirst().get();
//                Stock stock = stockMapper.selectOne(new LambdaQueryWrapper<Stock>().eq(Stock::getPartBatchNo,feeding.getPartBatchNo()).eq(Stock::getPartId,part.getId()).eq(Stock::getLocationId,locationId));
//                if (stock == null){
//                    throw new RuntimeException("mes 没有库存信息");
//                }
//                feeding.setStockId(stock.getId());
                stockUtils.erpFeeding(feeding.getPartBatchNo(), feeding.getWorkstationId(), feeding.getSuppliedQuantity(), billNo, part);
            } else {
                stockUtils.feeding(feeding.getStockId(), feeding.getWorkstationId(), feeding.getSuppliedQuantity(), billNo, feedingInDTO.getSource());
            }
        }
//        String feedCheck = remoteParamService.getByKey(Constant.FEED_IFS_NEED_SYNC, SecurityConstants.FROM_IN).getData();
//        if (!StringUtils.equals(feedCheck, "false")) {
//            this.ifsMove(feedingList, 1);
//        }
        return true;
    }
 
    /**
     * type 1投料,2退料
     *
     * @param feedingList
     */
    private void ifsMove(List<FeedingDTO> feedingList, Integer type) {
        Location location = null;
        // type 1 获取投料库位,2获取线边仓
        if (type == 1) {
            List<WorkstationLocation> locationList = workstationLocationMapper.selectList(Wrappers.<WorkstationLocation>lambdaQuery()
                    .eq(WorkstationLocation::getWorkstationId, feedingList.get(0).getWorkstationId())
                    .eq(WorkstationLocation::getLocationType, WorkstationLocation.FED_LOCATION));
            if (CollectionUtils.isEmpty(locationList)) {
                throw new RuntimeException("缺少已投料库位");
            }
            location = locationMapper.selectById(locationList.get(0).getLocationId());
        } else {
            //查询是否存在线边仓
            //List<Location> locationList = locationMapper.getLocationByWorkstationId(feedingList.get(0).getWorkstationId(), WorkstationLocation.FEED_LOCATION);
            //if (CollectionUtils.isEmpty(locationList)) {
            //    throw new RuntimeException("缺少线边仓");
            //}
            //location = locationList.get(0);
            boolean present = feedingList.stream().anyMatch(f -> null == f.getReturnLocationId());
            if (present) {
                throw new RuntimeException("存在未选退料库位行");
            }
        }
        List<StockDTO> stockList = new ArrayList<>();
        LocationIfsMoveDTO moveDTO = new LocationIfsMoveDTO();
        moveDTO.setRECORD_ID(UUID.randomUUID().toString().replace("-", ""));
        List<LocationIfsMoveDTO.DataBean> dataBeans = new ArrayList<>();
        moveDTO.setBATCH_INFO(dataBeans);
        for (FeedingDTO feeding : feedingList) {
            if (type == 2) {
                location = locationMapper.selectById(feeding.getReturnLocationId());
            }
            StockDTO stock;
            BigDecimal qty;
            if (type == 1) {
                qty = feeding.getSuppliedQuantity();
                stock = BeanUtil.copyProperties(stockMapper.selectById(feeding.getStockId()), StockDTO.class);
            } else {
                qty = feeding.getReturnQuantity();
                stock = BeanUtil.copyProperties(stockMapper.selectById(feeding.getId()), StockDTO.class);
            }
 
            // 是否工序库存为false执行ifs移库
//            Part part = partMapper.selectById(stock.getPartId());
            if (stock.getOperationStockStatus() != null && !stock.getOperationStockStatus()) {
                if (location.getIfsLocation() != null) {
                    stock.setFeedQuantity(qty);
                    stockList.add(stock);
                }
            }
            assembleMoveDataBean(dataBeans, stock, location);
        }
        if (stockList.size() > 0) {
            // 调用ifs移库接口
            stockUtils.feedingIfsMoveByDTO(stockList, moveDTO);
        }
    }
 
    private void assembleMoveDataBean(List<LocationIfsMoveDTO.DataBean> dataBeans, StockDTO stock, Location location) {
        // 库存件退料需要ifs移库
        Part part = partMapper.selectById(stock.getPartId());
        if (stock.getOperationStockStatus() == null) {
            if (StringUtils.equals("3", part.getMaterialType())) {
                stock.setOperationStockStatus(Boolean.FALSE);
            }
        }
        if (BooleanUtil.isTrue(stock.getOperationStockStatus())) {
            return;
        }
        Location nowLocation = locationMapper.selectById(stock.getLocationId());
        if (nowLocation.getIfsLocation() == null) {
            throw new RuntimeException("库存库位未绑定ifs库位");
        }
 
        LocationIfsMoveDTO.DataBean bean = new LocationIfsMoveDTO.DataBean();
        bean.setPART_NO(part.getPartNo());
        if (part.getLotTrackingIfs() != null && part.getLotTrackingIfs()) {
            bean.setLOT_BATCH_NO(stock.getIfsBatchNo());
            bean.setWAIV_DEV_REJ_NO(stock.getPartBatchNo());
        } else {
            bean.setLOT_BATCH_NO("*");
            bean.setWAIV_DEV_REJ_NO("*");
        }
        bean.setMOVE_QTY(stock.getFeedQuantity());
        bean.setLOCATION_NO(nowLocation.getIfsLocation());
        bean.setTO_LOCATION_NO(location.getIfsLocation());
        dataBeans.add(bean);
    }
 
 
    @Override
    public boolean updateList(List<FeedingDTO> feedingList) {
        for (FeedingDTO feedingDTO : feedingList) {
            Feeding feeding = baseMapper.selectById(feedingDTO.getId());
            // 1.去修改线边仓零件数量(PDA扫的erp库存就直接减去)
            if (feeding.getStockId() != null) {
                stockUtils.updateById(feeding.getStockId(), feedingDTO.getReturnQuantity(), BigDecimal.ZERO, BigDecimal.ZERO, null, null, "FEED");
            }
            // 2.保存投料记录
            FeedingRecord feedingRecord = new FeedingRecord();
            feedingRecord.setFeedingQuantity(feedingDTO.getReturnQuantity().negate());
            feedingRecord.setFeedingId(feedingDTO.getId());
            feedingRecordMapper.insert(feedingRecord);
            // 3.更新投料
            feedingUtils.updateById(feedingDTO.getId(), feedingDTO.getReturnQuantity().negate(), feedingDTO.getReturnQuantity().negate());
        }
        return true;
    }
 
 
    @Override
    public boolean rejectFeeding(List<FeedingDTO> feedingList) {
        for (FeedingDTO feedingDTO : feedingList) {
            stockUtils.rejectFeeding(feedingDTO.getWorkstationId(), feedingDTO.getReturnQuantity(),
                    feedingDTO.getPartId(), feedingDTO.getPartBatchNo(), feedingDTO.getSystemNo(), feedingDTO.getId()
                    , feedingDTO.getReturnLocationId());
        }
        String feedCheck = remoteParamService.getByKey(Constant.FEED_IFS_NEED_SYNC, SecurityConstants.FROM_IN).getData();
        if (!StringUtils.equals(feedCheck, "false")) {
            this.ifsMove(feedingList, 2);
        }
        return true;
    }
 
    private Stock getOneStockByWorkstation(Long workStationId, Long partId, String partBatchNo, String systemNo) {
        List<WorkstationLocation> locationList = workstationLocationMapper.selectList(Wrappers.<WorkstationLocation>lambdaQuery()
                .eq(WorkstationLocation::getWorkstationId, workStationId)
                .eq(WorkstationLocation::getLocationType, WorkstationLocation.FEED_LOCATION));
        if (CollectionUtil.isEmpty(locationList)) {
            throw new RuntimeException("该工作站尚未配置线边仓");
        }
        Set<Long> locationIds = locationList.stream().map(WorkstationLocation::getLocationId).collect(Collectors.toSet());
        //根据机台绑定的库位,零件id,批次号去找到线边仓库存记录行
        Stock stock = stockMapper.selectOne(Wrappers.<Stock>lambdaQuery()
                .eq(Stock::getPartId, partId)
                .eq(Stock::getPartBatchNo, partBatchNo)
                .eq(Stock::getSystemNo, systemNo)
                .in(Stock::getLocationId, locationIds));
        return stock;
    }
 
    @Override
    public List<JSONObject> pdaList(QueryWrapper<FeedingDTO> gen) {
        return baseMapper.pdaList(gen);
    }
 
    /**
     * 老的PDA投料
     *
     * @param feedingDTO
     */
    @Override
    public void pdaAdd(FeedingDTO feedingDTO) {
        boolean partIsExist = getIdByNo(feedingDTO);
        if (partIsExist) {
            Stock stock = getOneStockByWorkstation(feedingDTO.getWorkstationId(), feedingDTO.getPartId(), feedingDTO.getPartBatchNo(), feedingDTO.getSystemNo());
            if (stock != null) {
                feedingDTO.setStockId(stock.getId());
                // 1.去修改线边仓零件数量
                stockUtils.updateById(stock.getId(), feedingDTO.getSuppliedQuantity().negate(), BigDecimal.ZERO, BigDecimal.ZERO, null, null, "FEED");
            }
        }
        // 2.投料登记,保存投料记录
        FeedingRecord feedingRecord = new FeedingRecord();
        feedingRecord.setFeedingQuantity(feedingDTO.getSuppliedQuantity());
        // 2.1 根据工作站和零件\批次号\系统号去查询投料记录,如果存在就加上去
        Feeding feedingExist = baseMapper.selectOne(getQuery(feedingDTO));
        if (feedingExist != null) {
            feedingUtils.updateById(feedingExist.getId(), feedingRecord.getFeedingQuantity(), feedingRecord.getFeedingQuantity());
            feedingRecord.setFeedingId(feedingExist.getId());
        } else {
            feedingDTO.setResidualQuantity(feedingDTO.getSuppliedQuantity());
            baseMapper.insert(feedingDTO);
            feedingRecord.setFeedingId(feedingDTO.getId());
        }
        // 2.2 保存投料记录
        feedingRecordMapper.insert(feedingRecord);
    }
 
    @Override
    public void pdaReturn(FeedingDTO feedingDTO) {
        getIdByNo(feedingDTO);
        Feeding feeding = baseMapper.selectOne(getQuery(feedingDTO));
        if (feeding == null) {
            throw new RuntimeException("投入物料不存在");
        }
        if (feeding.getStockId() != null) {
            // 1.去修改线边仓零件数量
            stockUtils.updateById(feeding.getStockId(), feedingDTO.getReturnQuantity(), null, BigDecimal.ZERO, BigDecimal.ZERO, null, "FEED");
        }
        // 2.保存投料记录
        FeedingRecord feedingRecord = new FeedingRecord();
        feedingRecord.setFeedingQuantity(feedingDTO.getReturnQuantity().negate());
        feedingRecord.setFeedingId(feeding.getId());
        feedingRecordMapper.insert(feedingRecord);
        // 3.更新投料
        feedingUtils.updateById(feeding.getId(), feedingDTO.getReturnQuantity().negate(), feedingDTO.getReturnQuantity().negate());
    }
 
    /**
     * workstationNo
     *
     * @param feedingDTO
     * @return
     */
    public boolean getIdByNo(FeedingDTO feedingDTO) {
        boolean result = true;
        Workstation workstation = workstationMapper.selectOne(Wrappers.<Workstation>lambdaQuery().eq(Workstation::getWorkstationNo, feedingDTO.getWorkstationNo()));
        if (workstation == null) {
            throw new RuntimeException(feedingDTO.getWorkstationNo() + "工作站不存在");
        } else {
            feedingDTO.setWorkstationId(workstation.getId());
        }
        Part part = partMapper.selectOne(Wrappers.<Part>lambdaQuery().eq(Part::getPartNo, feedingDTO.getPartNo()));
        if (part == null) {
            // 如果零件不存在,去erp接口查询零件,并生成零件
            part = partUtils.getErpPartByPartNo(feedingDTO.getPartNo());
            result = false;
        }
        feedingDTO.setPartId(part.getId());
        return result;
    }
 
    /**
     * 新的PDA投料
     *
     * @param feedingStockDTO
     */
    @Override
    public void pdaAdd(FeedingStockDTO feedingStockDTO) {
        boolean partIsExist = getIdByNo(feedingStockDTO);
        String billNo = RandomStringUtils.random(10, true, true);
        if (partIsExist) {
            Stock stock = getOneStockByWorkstation(feedingStockDTO.getWorkstationId(), feedingStockDTO.getPartId(), feedingStockDTO.getPartBatchNo(), feedingStockDTO.getSystemNo());
            if (stock != null) {
                List<WorkstationLocation> locationList = workstationLocationMapper.selectList(Wrappers.<WorkstationLocation>lambdaQuery()
                        .eq(WorkstationLocation::getWorkstationId, feedingStockDTO.getWorkstationId())
                        .eq(WorkstationLocation::getLocationType, WorkstationLocation.FED_LOCATION));
                if (CollectionUtils.isEmpty(locationList)) {
                    throw new RuntimeException(feedingStockDTO.getWorkstationNo() + "缺少已投料库");
                }
                feedingStockDTO.setId(stock.getId());
                // 1、去修改线边仓零件数量
                stockUtils.updateById(stock.getId(), feedingStockDTO.getSuppliedQuantity().negate(), BigDecimal.ZERO,
                        BigDecimal.ZERO, null, billNo, "FEED");
                // 2、查询已投未消耗的物料
                Stock stockExist = stockMapper.selectOne(Wrappers.<Stock>lambdaQuery()
                        .eq(Stock::getLocationId, locationList.get(0).getLocationId())
                        .eq(Stock::getPartId, stock.getPartId())
                        .eq(Stock::getPartBatchNo, stock.getPartBatchNo())
                        .eq(Stock::getSystemNo, stock.getSystemNo()));
                if (stockExist != null) {
                    stockUtils.updateById(stockExist.getId(), feedingStockDTO.getSuppliedQuantity(), BigDecimal.ZERO,
                            BigDecimal.ZERO, null, billNo, "FEED");
                } else {
                    stockExist = new Stock();
                    stockExist.setPartId(stock.getPartId());
                    stockExist.setSystemNo(stock.getSystemNo());
                    stockExist.setPartBatchNo(stock.getPartBatchNo());
                    stockExist.setLocationId(locationList.get(0).getLocationId());
                    stockExist.setStockQuantity(feedingStockDTO.getSuppliedQuantity());
                    stockExist.setReserveQuantity(BigDecimal.ZERO);
                    stockExist.setAvailableStockQuantity(feedingStockDTO.getSuppliedQuantity());
                    stockExist.setOperationStockStatus(stock.getOperationStockStatus());
                    stockExist.setReelNumber(stock.getReelNumber());
                    stockExist.setIfsBatchNo(stock.getIfsBatchNo());
                    stockExist.setCustomerOrderNo(stock.getCustomerOrderNo());
                    stockExist.setMpsNo(stock.getMpsNo());
                    stockMapper.insert(stockExist);
                    stockUtils.createTransaction(BigDecimal.ZERO, stockExist.getStockQuantity(),
                            stockExist.getPartId(), locationList.get(0).getLocationId(), stockExist.getPartBatchNo(),
                            billNo, TransactionType.PRODUCT_FEEDING.getValue(), stockExist.getIfsBatchNo());
                }
                FeedingDTO feedingDTO = new FeedingDTO();
                feedingDTO.setStockId(stock.getId());
                feedingDTO.setWorkstationId(feedingStockDTO.getWorkstationId());
                feedingDTO.setSuppliedQuantity(feedingStockDTO.getSuppliedQuantity());
                ifsMove(Collections.singletonList(feedingDTO), 1);
            }
        }
    }
 
    /**
     * @param feedingStockDTO
     */
    @Override
    public void pdaReturn(FeedingStockDTO feedingStockDTO) {
        getIdByNo(feedingStockDTO);
        //被退库位
        WorkstationLocation workstationLocationFrom = workstationLocationMapper.selectOne(Wrappers.<WorkstationLocation>lambdaQuery()
                .eq(WorkstationLocation::getLocationType, WorkstationLocation.FED_LOCATION)
                .eq(WorkstationLocation::getWorkstationId, feedingStockDTO.getWorkstationId()));
        Stock stockfrom = stockMapper.selectOne(Wrappers.<Stock>lambdaQuery()
                .eq(Stock::getPartBatchNo, feedingStockDTO.getPartBatchNo())
                .eq(Stock::getSystemNo, feedingStockDTO.getSystemNo())
                .eq(Stock::getLocationId, workstationLocationFrom.getLocationId())
                .eq(Stock::getPartId, feedingStockDTO.getPartId()));
        if (null == stockfrom) {
            throw new RuntimeException("退库物料丢失");
        }
        stockUtils.updateById(stockfrom.getId(), feedingStockDTO.getReturnQuantity().negate(), BigDecimal.ZERO, BigDecimal.ZERO, null, null, TransactionType.PRODUCT_CANCEL.getValue());
        //退入库位
        WorkstationLocation workstationLocationTo = workstationLocationMapper.selectOne(Wrappers.<WorkstationLocation>lambdaQuery()
                .eq(WorkstationLocation::getLocationType, WorkstationLocation.FEED_LOCATION)
                .eq(WorkstationLocation::getWorkstationId, feedingStockDTO.getWorkstationId()));
        Stock stockTo = stockMapper.selectOne(Wrappers.<Stock>lambdaQuery()
                .eq(Stock::getPartBatchNo, feedingStockDTO.getPartBatchNo())
                .eq(Stock::getSystemNo, feedingStockDTO.getSystemNo())
                .eq(Stock::getLocationId, workstationLocationTo.getLocationId())
                .eq(Stock::getPartId, feedingStockDTO.getPartId()));
        stockUtils.updateById(stockTo.getId(), feedingStockDTO.getReturnQuantity(), BigDecimal.ZERO, BigDecimal.ZERO, null, null, TransactionType.PRODUCT_CANCEL.getValue());
    }
 
    @Override
    public List<Location> getReturnLocations(Long workstationId) {
        return locationMapper.getReturnLocationByWorkstationId(workstationId,
                Arrays.asList(WorkstationLocation.FEED_LOCATION, WorkstationLocation.PENDING_LOCATION));
    }
 
    /**
     * workstationNo
     *
     * @param feedingStockDTO
     * @return
     */
    public boolean getIdByNo(FeedingStockDTO feedingStockDTO) {
        boolean result = true;
        Workstation workstation = workstationMapper.selectOne(Wrappers.<Workstation>lambdaQuery().eq(Workstation::getWorkstationNo, feedingStockDTO.getWorkstationNo()));
        if (workstation == null) {
            throw new RuntimeException(feedingStockDTO.getWorkstationNo() + "工作站不存在");
        } else {
            feedingStockDTO.setWorkstationId(workstation.getId());
        }
        Part part = partMapper.selectOne(Wrappers.<Part>lambdaQuery().eq(Part::getPartNo, feedingStockDTO.getPartNo()));
        if (part == null) {
            // 如果零件不存在,去erp接口查询零件,并生成零件
            part = partUtils.getErpPartByPartNo(feedingStockDTO.getPartNo());
            result = false;
        }
        feedingStockDTO.setPartId(part.getId());
        return result;
    }
 
    private LambdaQueryWrapper<Feeding> getQuery(FeedingDTO feedingDTO) {
        LambdaQueryWrapper<Feeding> wrapper = Wrappers.<Feeding>lambdaQuery()
                .eq(Feeding::getWorkstationId, feedingDTO.getWorkstationId()).eq(Feeding::getPartId, feedingDTO.getPartId())
                .eq(Feeding::getPartBatchNo, feedingDTO.getPartBatchNo());
        if (StringUtils.isNotBlank(feedingDTO.getSystemNo())) {
            wrapper = wrapper.eq(Feeding::getSystemNo, feedingDTO.getSystemNo());
        }
        if (feedingDTO.getStockId() != null) {
            wrapper = wrapper.eq(Feeding::getStockId, feedingDTO.getStockId());
        }
        return wrapper;
    }
}