|  |  |  | 
|---|
|  |  |  | 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()); | 
|---|
|  |  |  | //数据分类 1.平库数据  2. TUC数据 | 
|---|
|  |  |  | //数据分类 1.平库数据  2. CTU数据 | 
|---|
|  |  |  | Map<Long, List<OrderOutMergeParam>> listMap = mergeParam.stream().collect(Collectors.groupingBy(OrderOutMergeParam::getTypeId)); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | listMap.keySet().forEach(key -> { | 
|---|
|  |  |  | 
|---|
|  |  |  | //平库出库 | 
|---|
|  |  |  | 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()) { | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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("缓存站更新失败"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //库位F => R | 
|---|
|  |  |  | loc.setLocStsId(LocStsType.R.val()); | 
|---|
|  |  |  | loc.setUpdateTime(new Date()); | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //锁定库存量 | 
|---|
|  |  |  | locDetl.setWorkQty(locDetl.getWorkQty() + outOder.getAnfme()); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | if (!locDetlService.updateById(locDetl)) { | 
|---|
|  |  |  | throw new CoolException("库存加锁失败!!"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | }); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Transactional | 
|---|
|  |  |  | @Transactional(rollbackFor = Exception.class) | 
|---|
|  |  |  | public void cancelWave(List<Long> waveIds) { | 
|---|
|  |  |  | if (waveIds == null) { | 
|---|
|  |  |  | throw new CoolException("参数不能为空"); | 
|---|
|  |  |  | 
|---|
|  |  |  | throw new CoolException("已存在任务,禁止取消波次"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<PickSheet> pickSheets = pickSheetService.list(new LambdaQueryWrapper<PickSheet>() | 
|---|
|  |  |  | .eq(PickSheet::getWaveNo, wave.getWaveNo()) | 
|---|
|  |  |  | .eq(PickSheet::getDeleted, 0) | 
|---|
|  |  |  | .eq(PickSheet::getStatus, 1)); | 
|---|
|  |  |  | if (!pickSheets.isEmpty()) { | 
|---|
|  |  |  | throw new CoolException("当前波次有拣货单存在!!"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | List<Order> orders = orderService.list(new LambdaQueryWrapper<Order>().eq(Order::getWaveId, wave.getId())); | 
|---|
|  |  |  | for (Order order : orders) { | 
|---|
|  |  |  | order.setWaveId(null); | 
|---|
|  |  |  | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 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("缓存站清空失败"); | 
|---|
|  |  |  | 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("缓存站清空失败"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|