|  |  | 
 |  |  | package com.zy.asrs.wms.asrs.manage;
 | 
 |  |  | 
 | 
 |  |  | import com.alibaba.fastjson.JSON;
 | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.Wrapper;
 | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 | 
 |  |  | import com.mysql.cj.util.StringUtils;
 | 
 |  |  | import com.zy.asrs.framework.exception.CoolException;
 | 
 |  |  | import com.zy.asrs.wms.asrs.entity.*;
 | 
 |  |  | import com.zy.asrs.wms.asrs.entity.dto.*;
 | 
 |  |  | import com.zy.asrs.wms.asrs.entity.dto.OrderOutMergeDto;
 | 
 |  |  | import com.zy.asrs.wms.asrs.entity.enums.*;
 | 
 |  |  | import com.zy.asrs.wms.asrs.entity.param.*;
 | 
 |  |  | import com.zy.asrs.wms.asrs.entity.*;
 | 
 |  |  | import com.zy.asrs.wms.asrs.service.*;
 | 
 |  |  | import com.zy.asrs.wms.utils.OrderUtils;
 | 
 |  |  | import com.zy.asrs.wms.utils.OutUtils;
 | 
 |  |  | 
 |  |  | import java.text.SimpleDateFormat;
 | 
 |  |  | import java.util.*;
 | 
 |  |  | import java.util.stream.Collectors;
 | 
 |  |  | import java.util.stream.Stream;
 | 
 |  |  | 
 | 
 |  |  | /**
 | 
 |  |  |  * 出库管理
 | 
 |  |  | 
 |  |  |         List<MergePreviewResultDto> resultDtos = new ArrayList<>();
 | 
 |  |  |         //优先查询平库数据
 | 
 |  |  |         param.forEach(pars -> {
 | 
 |  |  |             if (pars.getStatus() == 1) {
 | 
 |  |  |                 return;
 | 
 |  |  |             }
 | 
 |  |  |             List<MergePreviewResultLocDto> locDtos = new ArrayList<>();
 | 
 |  |  |             MergePreviewResultDto resultDto = new MergePreviewResultDto();
 | 
 |  |  |             resultDto.sync(pars);
 | 
 |  |  |             resultDto.setOrderIds(pars.getOrderIds());
 | 
 |  |  |             //总需求数量
 | 
 |  |  |             resultDto.setAnfme(pars.getAnfme());
 | 
 |  |  |             resultDto.setLocs(locDtos);
 | 
 |  |  | 
 | 
 |  |  |             //查询平库中符合条件的库存
 | 
 |  |  |             List<LocDetl> locs = locDetlService.queryFlatStock(pars.getMatnr(), pars.getBatch(), pars.getFieldParams());
 | 
 |  |  |             if (!locs.isEmpty()) {
 | 
 |  |  |                 double anfme = pars.getAnfme() - pars.getWorkQty();
 | 
 |  |  | 
 |  |  |                     locDto.setLocNo(detl.getLocNo());
 | 
 |  |  |                     locDto.setTypeId(LocAreaTypeSts.LOC_AREA_TYPE_FLAT.id);
 | 
 |  |  |                     locDto.setLocDetlId(detl.getId());
 | 
 |  |  | 
 | 
 |  |  |                     locDto.setAnfme(detl.getAnfme());
 | 
 |  |  |                     locDto.setWorkQty(detl.getWorkQty());
 | 
 |  |  |                     locDtos.add(locDto);
 | 
 |  |  |                     //库位实际可用数量
 | 
 |  |  |                     double surplusQty = detl.getAnfme() - detl.getWorkQty();
 | 
 |  |  |                     Double surplusQty = Math.round((detl.getAnfme() - detl.getWorkQty()) * 10000) / 10000.0;
 | 
 |  |  |                     if (surplusQty <= 0) {
 | 
 |  |  |                         continue;
 | 
 |  |  |                     }
 | 
 |  |  |                     //波次数量减去库位可用数量后,盈余数量
 | 
 |  |  |                     anfme = anfme - surplusQty;
 | 
 |  |  |                     if (anfme > 0) {
 | 
 |  |  |                         locDto.setAnfme(detl.getAnfme());
 | 
 |  |  |                         locDto.setWorkQty(surplusQty);
 | 
 |  |  |                         //当前可使用数量
 | 
 |  |  |                         resultDto.setFetchQty(surplusQty);
 | 
 |  |  |                         //余下需求数量
 | 
 |  |  |                         pars.setStatus(2);
 | 
 |  |  |                         pars.setWorkQty(pars.getWorkQty() + surplusQty);
 | 
 |  |  |                         pars.setAnfme(anfme);
 | 
 |  |  |                     } else {
 | 
 |  |  |                         locDto.setAnfme(pars.getAnfme() - pars.getWorkQty());
 | 
 |  |  |                         locDto.setWorkQty(pars.getAnfme() - pars.getWorkQty());
 | 
 |  |  |                         //当前使用数量
 | 
 |  |  |                         resultDto.setFetchQty(pars.getAnfme());
 | 
 |  |  |                         //余下需求
 | 
 |  |  |                         pars.setWorkQty(pars.getWorkQty() + pars.getAnfme());
 | 
 |  |  |                         pars.setStatus(1);
 | 
 |  |  |                         pars.setAnfme(0.0);
 | 
 |  |  |                         break;
 | 
 |  |  |                     }
 | 
 |  |  |                 }
 | 
 |  |  |                 //保存出库数量(平库)
 | 
 |  |  |                 pars.setWorkQty(pars.getAnfme() - pars.getWorkQty() - anfme);
 | 
 |  |  | 
 | 
 |  |  |                 resultDto.setOtherLocs(new ArrayList<>());
 | 
 |  |  |                 if (!Objects.isNull(resultDto.getFetchQty()) && !(new BigDecimal(resultDto.getFetchQty()).compareTo(new BigDecimal("0.00")) == 0)) {
 | 
 |  |  |                     resultDto.setOtherLocs(new ArrayList<>());
 | 
 |  |  | 
 | 
 |  |  |                 resultDto.setAnfme(pars.getAnfme());
 | 
 |  |  |                     resultDto.setType(LocAreaTypeSts.LOC_AREA_TYPE_FLAT.desc);
 | 
 |  |  | 
 | 
 |  |  |                 resultDtos.add(resultDto);
 | 
 |  |  | 
 | 
 |  |  |                     resultDtos.add(resultDto);
 | 
 |  |  |                 }
 | 
 |  |  |             }
 | 
 |  |  |         });
 | 
 |  |  | 
 | 
 |  |  |         //平库查询完成后,再查询TCU
 | 
 |  |  |         for (MergePreviewDto dto : param) {
 | 
 |  |  |             Double anfme = dto.getAnfme() - dto.getWorkQty();
 | 
 |  |  |             //减去平库数量后,小于等于0,跳出处理
 | 
 |  |  |             if (anfme <= 0) {
 | 
 |  |  |             //单据已完成,跳出
 | 
 |  |  |             if (dto.getStatus() == 1) {
 | 
 |  |  |                 continue;
 | 
 |  |  |             }
 | 
 |  |  | //            Double anfme = dto.getAnfme() - dto.getWorkQty();
 | 
 |  |  | //            //减去平库数量后,小于等于0,跳出处理
 | 
 |  |  | //            if (anfme <= 0) {
 | 
 |  |  | //                continue;
 | 
 |  |  | //            }
 | 
 |  |  |             List<LocDetl> locDetls = locDetlService.queryStock(dto.getMatnr(), dto.getBatch(), dto.getFieldParams(), sortParams);
 | 
 |  |  |             if (locDetls.isEmpty()) {
 | 
 |  |  |                 MergePreviewResultDto resultDto = new MergePreviewResultDto();
 | 
 |  |  |                 resultDto.sync(dto);
 | 
 |  |  |                 resultDto.setLocs(new ArrayList<>());
 | 
 |  |  |                 resultDto.setType(LocAreaTypeSts.LOC_AREA_TYPE_UTC.desc);
 | 
 |  |  |                 resultDto.setOrderIds(dto.getOrderIds());
 | 
 |  |  |                 resultDto.setAnfme(dto.getAnfme());
 | 
 |  |  |                 resultDtos.add(resultDto);
 | 
 |  |  | 
 |  |  |             MergePreviewResultDto resultDto = new MergePreviewResultDto();
 | 
 |  |  |             resultDto.sync(dto);
 | 
 |  |  |             resultDto.setOrderIds(dto.getOrderIds());
 | 
 |  |  | //            Double anfme = dto.getAnfme();
 | 
 |  |  |             Double anfme = dto.getAnfme();
 | 
 |  |  |             resultDto.setLocs(locDtos);
 | 
 |  |  |             for (LocDetl locDetl : locDetls) {
 | 
 |  |  |                 Loc loc = locService.getById(locDetl.getLocId());
 | 
 |  |  | 
 |  |  |             resultDto.setOtherLocs(otherLocDtos);
 | 
 |  |  | 
 | 
 |  |  |             resultDto.setAnfme(dto.getAnfme());
 | 
 |  |  | 
 | 
 |  |  |             resultDto.setType(LocAreaTypeSts.LOC_AREA_TYPE_UTC.desc);
 | 
 |  |  | 
 | 
 |  |  |             resultDtos.add(resultDto);
 | 
 |  |  |         }
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |         /**
 | 
 |  |  |          * 波次合并出库
 | 
 |  |  |          * 1. 判断是平库还TCU库
 | 
 |  |  |          * 1. 判断是平库还CTU库
 | 
 |  |  |          * 2. 平库生成拣货单
 | 
 |  |  |          * 3. TCU库生成任务单
 | 
 |  |  |          * 3. CTU库生成任务单
 | 
 |  |  |          */
 | 
 |  |  |         outStockByArea(dto, wave);
 | 
 |  |  | 
 | 
 |  |  | 
 |  |  |     }
 | 
 |  |  | 
 | 
 |  |  |     /**
 | 
 |  |  |      * 根据不同库位类型生成出库拣单及CTU任务档
 | 
 |  |  |      * 根据不同库位类型生成出库拣货单或CTU任务档
 | 
 |  |  |      *
 | 
 |  |  |      * @param dto
 | 
 |  |  |      * @param wave
 | 
 |  |  | 
 |  |  | 
 | 
 |  |  |         //平库数据源
 | 
 |  |  |         List<OrderOutMergeParam> flatOrders = new ArrayList<>();// listMap.get(LocAreaTypeSts.LOC_AREA_TYPE_FLAT);
 | 
 |  |  |         //TUC数据源
 | 
 |  |  |         //CTU数据源
 | 
 |  |  |         List<OrderOutMergeParam> tucOrders = new ArrayList<>();//listMap.get(LocAreaTypeSts.LOC_AREA_TYPE_UTC);
 | 
 |  |  |         //按库位类型分类
 | 
 |  |  |         //fixme 如果库存不足时,生成任务档 过滤掉没有库位信息的数据。找君杰确认
 | 
 |  |  |         List<OrderOutMergeParam> mergeParam = params.stream().filter(par -> {
 | 
 |  |  |             return !StringUtils.isNullOrEmpty(par.getLocNo());
 | 
 |  |  |         }).collect(Collectors.toList());
 | 
 |  |  | 
 |  |  |             //平库出库
 | 
 |  |  |             outStockByFlat(flatOrders, wave);
 | 
 |  |  |         }
 | 
 |  |  | 
 | 
 |  |  |         if (!tucOrders.isEmpty()) {
 | 
 |  |  |             //TUC出库
 | 
 |  |  |             //CTU出库
 | 
 |  |  |             outStockByTUC(tucOrders, wave);
 | 
 |  |  |         }
 | 
 |  |  | 
 | 
 |  |  | 
 | 
 |  |  |     }
 | 
 |  |  | 
 | 
 |  |  |     /**
 | 
 |  |  |      * TUC出库--生成出库任务档
 | 
 |  |  |      * CTU出库--生成出库任务档
 | 
 |  |  |      *
 | 
 |  |  |      * @param tucOrders
 | 
 |  |  |      * @param wave
 | 
 |  |  |      */
 | 
 |  |  |     private void outStockByTUC(List<OrderOutMergeParam> tucOrders, Wave wave) {//123
 | 
 |  |  |     private void outStockByTUC(List<OrderOutMergeParam> tucOrders, Wave wave) {
 | 
 |  |  |         Map<Long, List<OrderOutMergeDto>> map = checkLoc(tucOrders, wave);
 | 
 |  |  | 
 | 
 |  |  |         for (Map.Entry<Long, List<OrderOutMergeDto>> entry : map.entrySet()) {
 | 
 |  |  | 
 |  |  |                 waveDetl.setUpdateTime(new Date());
 | 
 |  |  |                 if (!waveDetlService.updateById(waveDetl)) {
 | 
 |  |  |                     throw new CoolException("波次数据更新失败");
 | 
 |  |  |                 }
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  |             List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().eq(Order::getWaveNo, wave.getWaveNo()));
 | 
 |  |  |             if (orders.isEmpty()) {
 | 
 |  |  |                 throw new CoolException("当前波次订单不存在!!");
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  |             List<CacheSite> cacheSites = cacheSiteService.list(new LambdaQueryWrapper<CacheSite>()
 | 
 |  |  |                     .eq(CacheSite::getSiteStatus, CacheSiteStatusType.O.id).eq(CacheSite::getChannel,task.getTargetSite()));
 | 
 |  |  | 
 | 
 |  |  |             if (cacheSites.isEmpty()) {
 | 
 |  |  |                 throw new CoolException("缓存站空间不足,请稍后再试");
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  |             if (cacheSites.size() < orders.size()) {
 | 
 |  |  |                 throw new CoolException("缓存站空间不足,请稍后再试");
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  |             for (int i = 0; i < orders.size(); i++) {
 | 
 |  |  |                 CacheSite cacheSite = cacheSites.get(i);
 | 
 |  |  |                 cacheSite.setOrderId(orders.get(i).getId());
 | 
 |  |  |                 cacheSite.setOrderNo(orders.get(i).getOrderNo());
 | 
 |  |  |                 cacheSite.setSiteStatus(CacheSiteStatusType.R.id);
 | 
 |  |  |                 cacheSite.setBarcode(loc.getBarcode());
 | 
 |  |  |                 cacheSite.setUpdateTime(new Date());
 | 
 |  |  |                 if (!cacheSiteService.updateById(cacheSite)) {
 | 
 |  |  |                     throw new CoolException("缓存站更新失败");
 | 
 |  |  |                 }
 | 
 |  |  |             }
 | 
 |  |  | 
 | 
 |  |  | 
 |  |  |                         throw new CoolException("订单反写失败");
 | 
 |  |  |                     }
 | 
 |  |  | 
 | 
 |  |  | //                    CacheSite cacheSite = cacheSiteService.getOne(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getOrderId, order.getId()));
 | 
 |  |  | //                    if (cacheSite == null) {
 | 
 |  |  | //                        throw new CoolException("缓存站不存在");
 | 
 |  |  | //                    }
 | 
 |  |  | //                    cacheSite.setSiteStatus(CacheSiteStatusType.O.id);
 | 
 |  |  | //                    cacheSite.setOrderId(null);
 | 
 |  |  | //                    cacheSite.setOrderNo(null);
 | 
 |  |  | //                    cacheSite.setUpdateTime(new Date());
 | 
 |  |  | //                    if (!cacheSiteService.updateById(cacheSite)) {
 | 
 |  |  | //                        throw new CoolException("缓存站清空失败");
 | 
 |  |  | //                    }
 | 
 |  |  |                     CacheSite cacheSite = cacheSiteService.getOne(new LambdaQueryWrapper<CacheSite>().eq(CacheSite::getOrderId, order.getId()));
 | 
 |  |  |                     if (cacheSite != null) {
 | 
 |  |  |                         cacheSite.setSiteStatus(CacheSiteStatusType.O.id);
 | 
 |  |  |                         cacheSite.setOrderId(null);
 | 
 |  |  |                         cacheSite.setOrderNo(null);
 | 
 |  |  |                         cacheSite.setBarcode(null);
 | 
 |  |  |                         cacheSite.setUpdateTime(new Date());
 | 
 |  |  |                         if (!cacheSiteService.updateById(cacheSite)) {
 | 
 |  |  |                             throw new CoolException("缓存站清空失败");
 | 
 |  |  |                         }
 | 
 |  |  |                     }
 | 
 |  |  |                 }
 | 
 |  |  | 
 | 
 |  |  |                 waveDetlService.removeById(waveDetl.getId());
 |