| | |
| | | package com.zy.asrs.task.handler; |
| | | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.mapper.Wrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.enums.LocStsType; |
| | | import com.zy.asrs.mapper.BasDevpMapper; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.service.impl.BasStationServiceImpl; |
| | | import com.zy.asrs.task.AbstractHandler; |
| | | import com.zy.asrs.task.core.ReturnT; |
| | | import com.zy.common.model.enums.WorkNoType; |
| | | import com.zy.common.properties.AgvProperties; |
| | | import com.zy.common.service.CommonService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.interceptor.TransactionAspectSupport; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.atomic.AtomicInteger; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * Created by vincent on 2020/7/4 |
| | |
| | | private LocDetlService locDetlService; |
| | | @Autowired |
| | | private WaitPakinService waitPakinService; |
| | | @Autowired |
| | | private OrderDetlService orderDetlService; |
| | | @Autowired |
| | | private OrderDetlPakinService orderDetlPakinService; |
| | | @Autowired |
| | | private OrderDetlPakoutService orderDetlPakoutService; |
| | | @Autowired |
| | | private LocCacheService locCacheService; |
| | | @Autowired |
| | | private OrderPakinService orderPakinService; |
| | | @Autowired |
| | | private TaskService taskService; |
| | | @Autowired |
| | | private TaskDetlService taskDetlService; |
| | | @Autowired |
| | | private BasStationServiceImpl basStationService; |
| | | |
| | | @Autowired |
| | | private LocCacheDetlService locCacheDetlService; |
| | | |
| | | @Autowired |
| | | private CommonService commonService; |
| | | |
| | | @Autowired |
| | | private AgvProperties agvProperties; |
| | | |
| | | @Autowired |
| | | private WrkMastLogService wrkMastLogService; |
| | | |
| | | @Autowired |
| | | private BasDevpMapper basDevpMapper; |
| | | |
| | | /** |
| | | * 站点轮询计数器,用于平均分配站点 |
| | | * Key: 站点组标识(如 "east" 或 "west"),Value: 当前轮询索引 |
| | | */ |
| | | private final Map<String, AtomicInteger> siteRoundRobinCounters = new ConcurrentHashMap<>(); |
| | | |
| | | public ReturnT<String> start(WrkMast wrkMast) { |
| | | // 4.入库完成 |
| | | if (wrkMast.getWrkSts() == 4) { |
| | | return doIn(wrkMast); |
| | | // 14.出库完成 |
| | | } else if (wrkMast.getWrkSts() == 14) { |
| | | // 14.出库完成 |
| | | } else if (wrkMast.getWrkSts() == 14) { |
| | | return doOut(wrkMast); |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | private ReturnT<String> doIn(WrkMast wrkMast){ |
| | | |
| | | public ReturnT<String> doIn(WrkMast wrkMast) { |
| | | Date now = new Date(); |
| | | LocMast locMast = locMastService.selectById(wrkMast.getLocNo()); |
| | | try { |
| | | if (null == locMast) { |
| | | exceptionHandle("工作档[workNo={0}]库位号错误[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("工作档[workNo={0}]库位号错误[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("工作档[workNo=" + wrkMast.getWrkNo() + "]库位号错误[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | assert locMast != null; |
| | | switch (wrkMast.getIoType()) { |
| | |
| | | locMast.setIoTime(now); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("空板入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("空板入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("空板入库 ===>> 修改库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls.isEmpty()) { |
| | | exceptionHandle("全板入库 ===>> 工作明细档不存在;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("全板入库 ===>> 工作明细档不存在;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 工作明细档不存在; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | // 遍历工作明细,更新库存明细和入库通知档 |
| | | for (WrkDetl wrkDetl : wrkDetls) { |
| | | |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch()); |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand() |
| | | , wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | | if (!locDetlService.updateAnfme(wrkDetl.getAnfme(), wrkMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch())) { |
| | | exceptionHandle("全板入库 ===>> 更新库存明细失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | if (!locDetlService.updateAnfme(wrkDetl.getAnfme(), wrkMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3() |
| | | , wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3())) { |
| | | // exceptionHandle("全板入库 ===>> 更新库存明细失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 更新库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } else { |
| | | locDetl = new LocDetl(); |
| | | locDetl.sync(wrkDetl); |
| | | BeanUtils.copyProperties(wrkDetl, locDetl); |
| | | // locDetl.sync(wrkDetl); |
| | | locDetl.setLocNo(wrkMast.getLocNo()); // 库位号 |
| | | locDetl.setAnfme(wrkDetl.getAnfme()); // 数量 |
| | | locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码 |
| | | locDetl.setModiTime(now); |
| | | locDetl.setAppeTime(now); |
| | | if (!locDetlService.insert(locDetl)) { |
| | | exceptionHandle("全板入库 ===>> 添加库存明细失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("全板入库 ===>> 添加库存明细失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 添加库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | |
| | | // 更新入库通知档 ioStatus ===>> Y |
| | | // 更新订单完成数量 |
| | | OrderDetlPakin orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (orderDetlPakin == null) { |
| | | orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), |
| | | wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | } |
| | | try { |
| | | Wrapper<WaitPakin> wrapper = new EntityWrapper<WaitPakin>() |
| | | .eq("zpallet", wrkDetl.getZpallet()) |
| | | .eq("matnr", wrkDetl.getMatnr()) |
| | | .eq("anfme", wrkDetl.getAnfme()); |
| | | if (Cools.isEmpty(wrkDetl.getBatch())) { |
| | | wrapper.eq("batch", wrkDetl.getBatch()); |
| | | } else { |
| | | wrapper.isNull("batch").or().eq("batch", ""); |
| | | if (!Cools.isEmpty(orderDetlPakin)) { |
| | | if (!orderDetlPakinService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakin.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | // exceptionHandle("全板入库 ===>> 更新订单完成数量失败;[workNo={0}],[locNo={1}]", |
| | | // wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | WaitPakin setParam = new WaitPakin(); |
| | | setParam.setIoStatus("Y"); |
| | | setParam.setModiTime(now); |
| | | waitPakinService.update(setParam, wrapper); |
| | | } catch (Exception ignore){} |
| | | } catch (Exception ignore) { |
| | | } |
| | | |
| | | } |
| | | // 修改库位状态 S ====>> F |
| | |
| | | locMast.setIoTime(now); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("全板入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("全板入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板入库 ===>> 修改库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | | // 拣料途中并板 |
| | | case 8: |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls8 = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls8.isEmpty()) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料途中并板 ===>> 工作明细档不存在; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | // 遍历工作明细,更新库存明细和入库通知档 |
| | | for (WrkDetl wrkDetl : wrkDetls8) { |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand() |
| | | , wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | | if (!locDetlService.updateAnfme(wrkDetl.getAnfme() + locDetl.getAnfme(), wrkMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3() |
| | | , wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料途中并板 ===>> 更新库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } else { |
| | | locDetl = new LocDetl(); |
| | | BeanUtils.copyProperties(wrkDetl, locDetl); |
| | | // locDetl.sync(wrkDetl); |
| | | locDetl.setLocNo(wrkMast.getLocNo()); // 库位号 |
| | | locDetl.setAnfme(wrkDetl.getAnfme()); // 数量 |
| | | locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码 |
| | | locDetl.setModiTime(now); |
| | | locDetl.setAppeTime(now); |
| | | if (!locDetlService.insert(locDetl)) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料途中并板 ===>> 添加库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | |
| | | if (!Cools.isEmpty(wrkDetl.getOrderNo())) { |
| | | // 更新订单完成数量 |
| | | if (!orderDetlPakinService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料途中并板 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | } |
| | | break; |
| | |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls53 = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls53.isEmpty()) { |
| | | exceptionHandle("拣料入库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("拣料入库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料入库 ===>> 工作明细档为空; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | for (WrkDetl wrkDetl : wrkDetls53) { |
| | | |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch()); |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand() |
| | | , wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | | if (!locDetlService.updateAnfme(locDetl.getAnfme() - wrkDetl.getAnfme(), locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch())) { |
| | | exceptionHandle("拣料入库 ===>> 修改库存明细数量失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | if (!locDetlService.updateAnfme(locDetl.getAnfme() - wrkDetl.getAnfme(), locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3() |
| | | , wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3())) { |
| | | // exceptionHandle("拣料入库 ===>> 修改库存明细数量失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料入库 ===>> 修改库存明细数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | |
| | | // 更新订单完成数量 |
| | | OrderDetlPakin orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), |
| | | wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (orderDetlPakin == null) { |
| | | orderDetlPakin = orderDetlPakinService.selectItem |
| | | (wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | } |
| | | try { |
| | | if (!Cools.isEmpty(orderDetlPakin)) { |
| | | if (!orderDetlPakinService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakin.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | // exceptionHandle("拣料入库 ===>> 更新订单完成数量失败;[workNo={0}],[locNo={1}]", |
| | | // wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料入库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore) { |
| | | } |
| | | |
| | | } |
| | | // 修改库位状态 Q ====>> F |
| | | if (locMast.getLocSts().equals("Q")) { |
| | |
| | | locMast.setIoTime(now); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("拣料入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("拣料入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("拣料入库 ===>> 修改库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls54 = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls54.isEmpty()) { |
| | | exceptionHandle("并板入库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("并板入库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板入库 ===>> 工作明细档为空; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | // 修改库存明细数量,如无库存,曾新增 |
| | | for (WrkDetl wrkDetl:wrkDetls54) { |
| | | for (WrkDetl wrkDetl : wrkDetls54) { |
| | | |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch()); |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand() |
| | | , wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | | if (!locDetlService.updateAnfme(wrkDetl.getAnfme(), locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch())) { |
| | | exceptionHandle("并板入库 ===>> 修改库存明细数量失败;[workNo={0}],[matnr={1}]", wrkMast.getWrkNo(), wrkDetl.getMatnr()); |
| | | if (!locDetlService.updateAnfme(wrkDetl.getAnfme(), locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3() |
| | | , wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3())) { |
| | | // exceptionHandle("并板入库 ===>> 修改库存明细数量失败;[workNo={0}],[matnr={1}]", wrkMast.getWrkNo(), wrkDetl.getMatnr()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板入库 ===>> 修改库存明细数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } else { |
| | | locDetl = new LocDetl(); |
| | | locDetl.sync(wrkDetl); |
| | | BeanUtils.copyProperties(wrkDetl, locDetl); |
| | | // locDetl.sync(wrkDetl); |
| | | locDetl.setLocNo(wrkMast.getLocNo()); // 库位号 |
| | | locDetl.setAnfme(wrkDetl.getAnfme()); // 数量 |
| | | locDetl.setZpallet(wrkDetl.getZpallet()); // 托盘条码 |
| | | locDetl.setModiTime(now); |
| | | locDetl.setAppeTime(now); |
| | | if (!locDetlService.insert(locDetl)) { |
| | | exceptionHandle("并板入库 ===>> 新增库存明细失败;[workNo={0}],[matnr={1}]", wrkMast.getWrkNo(), wrkDetl.getMatnr()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板入库 ===>> 新增库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | |
| | | // 更新订单完成数量 |
| | | OrderDetlPakin orderDetlPakin = orderDetlPakinService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | try { |
| | | if (!Cools.isEmpty(orderDetlPakin)) { |
| | | if (!orderDetlPakinService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakin.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板入库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore) { |
| | | |
| | | } |
| | | |
| | | } |
| | | // 修改库位状态 Q ====>> F |
| | | if (locMast.getLocSts().equals("Q")) { |
| | |
| | | locMast.setIoTime(now); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("并板入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("并板入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板入库 ===>> 修改库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls57 = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls57.isEmpty()) { |
| | | exceptionHandle("盘点入库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("盘点入库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("盘点入库 ===>> 工作明细档为空; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | for (WrkDetl wrkDetl : wrkDetls57) { |
| | | if (!Cools.isEmpty(wrkDetl.getOrderNo())) { |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (!Cools.isEmpty(orderDetlPakout)) { |
| | | if (!orderDetlPakoutService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakout.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("盘点入库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 修改库位状态 Q ====>> F |
| | | if (locMast.getLocSts().equals("Q")) { |
| | | locMast.setLocSts(wrkMast.getFullPlt().equals("Y")?"F":"D"); |
| | | locMast.setLocSts(wrkMast.getFullPlt().equals("Y") ? "F" : "D"); |
| | | locMast.setBarcode(wrkMast.getBarcode()); |
| | | locMast.setIoTime(now); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("盘点入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("盘点入库 ===>> 修改库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("盘点入库 ===>> 修改库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | |
| | | locSts = "F"; |
| | | // 转移库存明细数据: 库存号 由工作档源库位变为目标库位 |
| | | if (!locDetlService.updateLocNo(wrkMast.getLocNo(), wrkMast.getSourceLocNo())) { |
| | | exceptionHandle("库位移转 ===>> 转移库存明细数据失败;[源库位={0}],[目标库位={1}]", wrkMast.getSourceLocNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("库位移转 ===>> 转移库存明细数据失败;[源库位={0}],[目标库位={1}]", wrkMast.getSourceLocNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("库位移转 ===>> 转移库存明细数据失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | // 修改源库位状态 ==> O |
| | |
| | | sourceLoc.setModiTime(now); |
| | | sourceLoc.setIoTime(now); |
| | | if (!locMastService.updateById(sourceLoc)) { |
| | | exceptionHandle("库位移转 ===>> 修改源库位状态失败;[workNo={0}],[sourceLoc={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | // exceptionHandle("库位移转 ===>> 修改源库位状态失败;[workNo={0}],[sourceLoc={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("库位移转 ===>> 修改源库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | // 修改目标库位状态 ==> .locSts |
| | |
| | | locMast.setIoTime(now); |
| | | locMast.setModiTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("库位移转 ===>> 修改目标库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("库位移转 ===>> 修改目标库位状态失败;[workNo={0}],[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("库位移转 ===>> 修改目标库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | break; |
| | | default: |
| | |
| | | wrkMast.setWrkSts(5L); |
| | | wrkMast.setModiTime(now); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | exceptionHandle("更新入库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("更新入库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("更新入库完成状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("fail", e); |
| | |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg(e.getMessage()); |
| | | } |
| | | |
| | | return SUCCESS; |
| | | } |
| | | |
| | | private ReturnT<String> doOut(WrkMast wrkMast){ |
| | | private ReturnT<String> doOut(WrkMast wrkMast) { |
| | | Date now = new Date(); |
| | | LocMast locMast = locMastService.selectById(wrkMast.getSourceLocNo()); |
| | | try { |
| | | if (null == locMast) { |
| | | exceptionHandle("工作档[workNo={0}]库位号错误[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | // exceptionHandle("工作档[workNo={0}]库位号错误[locNo={1}]", wrkMast.getWrkNo(), wrkMast.getLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("工作档库位号错误; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | assert locMast != null; |
| | | switch (wrkMast.getIoType()) { |
| | | // 全板出库 |
| | | case 101: |
| | | // 出库确认信号位 |
| | | if (Cools.isEmpty(wrkMast.getInvWh()) || wrkMast.getInvWh().equals("N")) { |
| | | return SUCCESS; |
| | | } |
| | | // // 出库确认信号位 |
| | | // if (Cools.isEmpty(wrkMast.getInvWh()) || wrkMast.getInvWh().equals("N")) { |
| | | // return SUCCESS; |
| | | // } |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls101 = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls101.isEmpty()) { |
| | | exceptionHandle("全板出库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("全板出库 ===>> 工作明细档为空;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 工作明细档为空; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | for (WrkDetl wrkDetl : wrkDetls101) { |
| | | // todo:luxiaotao 3)修改出库通知档 status ==> Y |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (orderDetlPakout == null) { |
| | | orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | } |
| | | try { |
| | | if (!Cools.isEmpty(orderDetlPakout)) { |
| | | if (!orderDetlPakoutService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakout.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore) { |
| | | |
| | | } |
| | | } |
| | | // 删除工作档源库位的库存明细 |
| | | if (!locDetlService.delete(new EntityWrapper<LocDetl>().eq("loc_no", wrkMast.getSourceLocNo()))) { |
| | | exceptionHandle("全板出库 ===>> 删除库存明细失败;[workNo={0}],[sourceLocNo={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 删除库存明细失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | // 修改源库位状态 R ===>> O |
| | | if (locMast.getLocSts().equals("R")) { |
| | |
| | | locMast.setModiTime(now); |
| | | locMast.setIoTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("全板出库 ===>> 修改源库位状态失败;[workNo={0}],[sourceLocNo={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 修改源库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | | // 并板途中捡料 |
| | | case 108: |
| | | // 根据工作号,查询工作明细档 |
| | | List<WrkDetl> wrkDetls108 = wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("wrk_no", wrkMast.getWrkNo())); |
| | | if (wrkDetls108.isEmpty()) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板途中捡料 ===>> 工作明细档为空; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | for (WrkDetl wrkDetl : wrkDetls108) { |
| | | LocDetl locDetl = locDetlService.selectItem(locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand() |
| | | , wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (null != locDetl) { |
| | | if (!locDetlService.updateAnfme(locDetl.getAnfme() - wrkDetl.getAnfme(), locMast.getLocNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3() |
| | | , wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板途中捡料 ===>> 修改库存明细数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getLocNo() + "]"); |
| | | } |
| | | } |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | try { |
| | | if (!Cools.isEmpty(orderDetlPakout)) { |
| | | if (!orderDetlPakoutService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | orderDetlPakout.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme())) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板途中捡料 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | } catch (Exception ignore) { |
| | | } |
| | | } |
| | | break; |
| | |
| | | locMast.setModiTime(now); |
| | | locMast.setIoTime(now); |
| | | if (!locMastService.updateById(locMast)) { |
| | | exceptionHandle("空板出库 ===>> 修改源库位状态失败;[workNo={0}],[sourceLocNo={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | // exceptionHandle("空板出库 ===>> 修改源库位状态失败;[workNo={0}],[sourceLocNo={1}]", wrkMast.getWrkNo(), wrkMast.getSourceLocNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("空板出库 ===>> 修改源库位状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } |
| | | break; |
| | |
| | | wrkMast.setWrkSts(15L); |
| | | wrkMast.setModiTime(now); |
| | | if (!wrkMastService.updateById(wrkMast)) { |
| | | exceptionHandle("更新出库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | | // exceptionHandle("更新出库完成状态失败;[workNo={0}]", wrkMast.getWrkNo()); |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("更新出库完成状态失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("fail", e); |
| | |
| | | return SUCCESS; |
| | | } |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/9/23 |
| | | * @description: AGV任务完成加入历史档 |
| | | * @version 1.0 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ReturnT<String> AgvStart(Task task) { |
| | | // 4.入库完成 |
| | | if (task.getWrkSts() == 4) { |
| | | return agvDoIn(task); |
| | | // 14.出库完成 |
| | | } else if (task.getWrkSts() == 14) { |
| | | return agvDoOut(task); |
| | | // 15.出库更新完成 - 生成空托/满托出库任务 |
| | | } else if (task.getWrkSts() == 15) { |
| | | return generateEmptyOrFullPalletOutTaskForCompleted(task); |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @author Ryan |
| | | * @date 2025/9/25 |
| | | * @description: AGV出库任务 |
| | | * @version 1.0 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ReturnT<String> agvDoOut(Task task) { |
| | | if (task.getIoType().equals(101)) { |
| | | Date now = new Date(); |
| | | LocCache locMast = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", task.getSourceLocNo())); |
| | | if (Objects.isNull(locMast)) { |
| | | throw new RuntimeException("数据错误:库位信息不能为空!!"); |
| | | } |
| | | List<TaskDetl> wrkDetls101 = taskDetlService.selectList(new EntityWrapper<TaskDetl>().eq("wrk_no", task.getWrkNo())); |
| | | if (wrkDetls101.isEmpty()) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 工作明细档为空; [workNo=" + task.getWrkNo() + "],[locNo=" + task.getSourceLocNo() + "]"); |
| | | } |
| | | // 删除工作档源库位的库存明细 |
| | | if (!locDetlService.delete(new EntityWrapper<LocDetl>().eq("loc_no", task.getSourceLocNo()))) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 删除库存明细失败; [workNo=" + task.getWrkNo() + "],[locNo=" + task.getSourceLocNo() + "]"); |
| | | } |
| | | // 修改源库位状态 R ===>> O |
| | | if (locMast.getLocSts().equals(LocStsType.LOC_STS_TYPE_R.type)) { |
| | | locMast.setLocSts(LocStsType.LOC_STS_TYPE_O.type); |
| | | locMast.setBarcode(""); |
| | | locMast.setModiTime(now); |
| | | locMast.setIoTime(now); |
| | | if (!locCacheService.updateById(locMast)) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 修改源库位状态失败; [workNo=" + task.getWrkNo() + "],[locNo=" + task.getSourceLocNo() + "]"); |
| | | } |
| | | } else { |
| | | throw new CoolException("当前库位状态" + locMast.getLocSts() + ", 无法执行出库操作!!"); |
| | | } |
| | | task.setWrkSts(15L); |
| | | if (!taskService.updateById(task)) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | // 注意:生成空托/满托出库任务的逻辑已移至状态15的处理方法中 |
| | | } else if(task.getIoType().equals(53) || task.getIoType().equals(54) || task.getIoType().equals(57)){ |
| | | LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", task.getSourceLocNo())); |
| | | if (Objects.isNull(locCache)) { |
| | | throw new CoolException("数据错误,库位不存在!!"); |
| | | } |
| | | if (!locCache.getLocSts().equals(LocStsType.LOC_STS_TYPE_R.type)) { |
| | | throw new CoolException("当前库位状态为:" + LocStsType.LOC_STS_TYPE_R.type + "." + LocStsType.LOC_STS_TYPE_R.desc + ",不是出库预约状态"); |
| | | } |
| | | |
| | | locCache.setLocSts(LocStsType.LOC_STS_TYPE_O.type); |
| | | locCache.setModiTime(new Date()); |
| | | locCache.setBarcode(null); |
| | | locCache.setModiTime(new Date()); |
| | | locCache.setIoTime(new Date()); |
| | | if (!locCacheService.updateById(locCache)) { |
| | | throw new CoolException("库位状态修改失败!"); |
| | | } |
| | | |
| | | boolean deleted = locCacheDetlService.delete(new EntityWrapper<LocCacheDetl>().eq("loc_id", locCache.getId())); |
| | | |
| | | if (!deleted){ |
| | | throw new CoolException("库位明细删除失败!"); |
| | | } |
| | | |
| | | task.setWrkSts(15L); |
| | | task.setModiTime(new Date()); |
| | | if (!taskService.updateById(task)) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | } |
| | | return SUCCESS; |
| | | } |
| | | |
| | | /** |
| | | * 状态15(出库更新完成)时,生成空托出库或满托出库任务,将托盘放入缓存库位 |
| | | * @param completedTask 已完成出库更新的任务(状态15) |
| | | * @return 处理结果 |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ReturnT<String> generateEmptyOrFullPalletOutTaskForCompleted(Task completedTask) { |
| | | // 只处理ioType=101的全板出库任务 |
| | | if (!completedTask.getIoType().equals(101)) { |
| | | return SUCCESS; |
| | | } |
| | | |
| | | // 检查是否已经生成过空托/满托出库任务(避免重复生成) |
| | | List<Task> existingTasks = taskService.selectList(new EntityWrapper<Task>() |
| | | .eq("barcode", completedTask.getBarcode()) |
| | | .in("io_type", 110, 101) // 空板出库或全板出库 |
| | | .eq("wrk_sts", 7) // 待呼叫AGV状态 |
| | | ); |
| | | if (!existingTasks.isEmpty()) { |
| | | log.info("任务ID:{}的托盘码:{}已存在空托/满托出库任务,跳过生成", completedTask.getId(), completedTask.getBarcode()); |
| | | return SUCCESS; |
| | | } |
| | | |
| | | try { |
| | | generateEmptyOrFullPalletOutTask(completedTask, null); |
| | | return SUCCESS; |
| | | } catch (Exception e) { |
| | | log.error("状态15时生成空托/满托出库任务失败,任务ID:{},错误:{}", completedTask.getId(), e.getMessage(), e); |
| | | return FAIL.setMsg("生成空托/满托出库任务失败:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 出库完成后,生成空托出库或满托出库任务,将托盘放入缓存库位 |
| | | * @param outTask 出库任务 |
| | | * @param sourceLocCache 源库位(可为null) |
| | | */ |
| | | private void generateEmptyOrFullPalletOutTask(Task outTask, LocCache sourceLocCache) { |
| | | // 判断托盘类型:空托或满托 |
| | | boolean isEmptyPallet = "Y".equals(outTask.getEmptyMk()); |
| | | Integer ioType = isEmptyPallet ? 110 : 101; // 110=空板出库,101=全板出库(满托出库) |
| | | |
| | | log.info("出库任务完成,生成{}任务,任务ID:{},托盘码:{}", isEmptyPallet ? "空托出库" : "满托出库", outTask.getId(), outTask.getBarcode()); |
| | | |
| | | // 获取出库站点(出库任务的staNo是出库站点,将作为空托/满托出库任务的源站点) |
| | | String outboundStaNo = outTask.getStaNo(); |
| | | if (outboundStaNo == null || outboundStaNo.isEmpty()) { |
| | | log.warn("出库任务没有出库站点,无法生成{}任务,任务ID:{}", isEmptyPallet ? "空托出库" : "满托出库", outTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | // 根据出库站点判断是东侧还是西侧 |
| | | Set<String> eastStations = new HashSet<>(agvProperties.getEastStations()); |
| | | Set<String> westStations = new HashSet<>(agvProperties.getWestStations()); |
| | | |
| | | List<String> cacheStations; |
| | | String robotGroup; |
| | | Long targetWhsType; |
| | | String sideName; |
| | | |
| | | if (eastStations.contains(outboundStaNo)) { |
| | | // 东侧出库站点,查找东侧WA库位(whs_type=1) |
| | | cacheStations = agvProperties.getEastStations(); |
| | | robotGroup = agvProperties.getRobotGroupEast(); |
| | | targetWhsType = agvProperties.getWhsTypeMapping().getInboundArea(); // whs_type=1 |
| | | sideName = agvProperties.getEastDisplayName(); // 从配置读取显示名称 |
| | | log.info("出库站点{}在{},查找{}WA库位(whs_type={})", outboundStaNo, sideName, sideName, targetWhsType); |
| | | } else if (westStations.contains(outboundStaNo)) { |
| | | // 西侧出库站点,查找西侧WA库位(whs_type=2) |
| | | cacheStations = agvProperties.getWestStations(); |
| | | robotGroup = agvProperties.getRobotGroupWest(); |
| | | targetWhsType = agvProperties.getWhsTypeMapping().getCacheArea(); // whs_type=2 |
| | | sideName = agvProperties.getWestDisplayName(); // 从配置读取显示名称 |
| | | log.info("出库站点{}在{},查找{}WA库位(whs_type={})", outboundStaNo, sideName, sideName, targetWhsType); |
| | | } else { |
| | | log.warn("出库站点{}不在配置的站点列表中,无法判断{}/{},任务ID:{}", |
| | | outboundStaNo, agvProperties.getEastDisplayName(), agvProperties.getWestDisplayName(), outTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | if (cacheStations.isEmpty()) { |
| | | log.warn("{}侧没有配置站点,无法生成{}任务,任务ID:{}", |
| | | sideName, isEmptyPallet ? "空托出库" : "满托出库", outTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | // 分配缓存库位:只查找WA开头的库位(CA开头只做入库,WA开头才会被出库分配缓存区) |
| | | // 使用新的分配逻辑:按列优先级(第三列→第二列→第一列)分配 |
| | | String cacheAreaPrefix = agvProperties.getLocationPrefix().getCacheArea(); |
| | | LocCache cacheLoc = allocateCacheLocationByPriority(targetWhsType, cacheAreaPrefix, isEmptyPallet); |
| | | |
| | | if (cacheLoc == null) { |
| | | log.warn("{}侧没有可用的{}缓存库位,不生成{}AGV任务,任务ID:{}", |
| | | sideName, cacheAreaPrefix, isEmptyPallet ? "空托出库" : "满托出库", outTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | // 检查工作档是否已完成或已转历史档 |
| | | boolean workCompleted = false; |
| | | if (outTask.getWrkNo() != null) { |
| | | // 检查工作档是否存在且已完成 |
| | | WrkMast wrkMast = wrkMastService.selectOne( |
| | | new EntityWrapper<WrkMast>().eq("wrk_no", outTask.getWrkNo()) |
| | | ); |
| | | |
| | | if (wrkMast != null) { |
| | | Long wrkSts = wrkMast.getWrkSts(); |
| | | // 出库任务完成状态:14(已出库未确认)或15(出库更新完成) |
| | | if (wrkSts != null && (wrkSts == 14L || wrkSts == 15L)) { |
| | | workCompleted = true; |
| | | log.debug("工作档{}已完成,状态:{}", outTask.getWrkNo(), wrkSts); |
| | | } |
| | | } else { |
| | | // 如果工作档不存在,检查历史档 |
| | | WrkMastLog wrkMastLog = wrkMastLogService.selectOne( |
| | | new EntityWrapper<WrkMastLog>().eq("wrk_no", outTask.getWrkNo()) |
| | | ); |
| | | if (wrkMastLog != null) { |
| | | long logWrkSts = wrkMastLog.getWrkSts(); |
| | | // 出库任务历史档完成状态:15(出库更新完成) |
| | | if (logWrkSts == 15L) { |
| | | workCompleted = true; |
| | | log.debug("工作档{}已转历史档并完结,历史档状态:{}", outTask.getWrkNo(), logWrkSts); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 检查是否有从该出库站点到缓存区的正在搬运任务(状态8:已呼叫AGV,正在搬运) |
| | | // 出库到缓存区的任务类型:101(全板出库)或110(空板出库) |
| | | List<Task> transportingTasks = taskService.selectList( |
| | | new EntityWrapper<Task>() |
| | | .eq("source_sta_no", outboundStaNo) // 源站点是出库站点 |
| | | .in("sta_no", cacheStations) // 目标站点是缓存区站点 |
| | | .eq("task_type", "agv") |
| | | .eq("wrk_sts", 8L) // 只检查正在搬运状态的任务 |
| | | .in("io_type", 101, 110) // 出库到缓存区的任务类型 |
| | | ); |
| | | |
| | | // 如果有正在搬运的任务,且工作档未完成,则不分配缓存库位 |
| | | if (!transportingTasks.isEmpty() && !workCompleted) { |
| | | log.info("出库站点{}到缓存区有{}个正在搬运的AGV任务,且工作档未完成,暂不分配缓存库位,等待搬运完成。出库任务ID:{}", |
| | | outboundStaNo, transportingTasks.size(), outTask.getId()); |
| | | return; // 有正在搬运的任务且工作档未完成,不分配缓存库位,等待下次检查 |
| | | } |
| | | |
| | | if (!transportingTasks.isEmpty() && workCompleted) { |
| | | log.info("出库站点{}到缓存区有{}个正在搬运的AGV任务,但工作档已完成或已转历史档,允许分配缓存库位。出库任务ID:{}", |
| | | outboundStaNo, transportingTasks.size(), outTask.getId()); |
| | | } |
| | | |
| | | // 选择缓存区目标站点(使用和入库一样的分配策略:轮询、最少任务数) |
| | | String cacheStaNo = allocateCacheStation(cacheStations, ioType); |
| | | if (cacheStaNo == null) { |
| | | log.warn("无法为出库任务ID:{}分配缓存区站点,所有站点都在使用中", outTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | // 生成工作号 |
| | | int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type); |
| | | |
| | | // 创建空托出库/满托出库任务 |
| | | Task cacheTask = new Task(); |
| | | Date now = new Date(); |
| | | cacheTask.setWrkNo(workNo) |
| | | .setIoTime(now) |
| | | .setWrkSts(7L) // 工作状态:7.待呼叫AGV |
| | | .setIoType(ioType) // 110=空板出库,101=全板出库 |
| | | .setTaskType("agv") |
| | | .setIoPri(10D) |
| | | .setStaNo(cacheStaNo) // 目标站点(缓存区站点) |
| | | .setSourceStaNo(outboundStaNo) // 源站点(出库站点) |
| | | .setInvWh(robotGroup) // 机器人组(西侧) |
| | | .setFullPlt(isEmptyPallet ? "N" : "Y") // 满板:空托=N,满托=Y |
| | | .setPicking("N") |
| | | .setExitMk("N") |
| | | .setSourceLocNo(null) // 出库任务不需要源库位 |
| | | .setLocNo(cacheLoc.getLocNo()) // 目标库位(缓存库位) |
| | | .setEmptyMk(isEmptyPallet ? "Y" : "N") // 空板标记 |
| | | .setBarcode(outTask.getBarcode()) // 托盘码 |
| | | .setLinkMis("N") |
| | | .setAppeTime(now) |
| | | .setModiTime(now); |
| | | |
| | | if (!taskService.insert(cacheTask)) { |
| | | log.error("生成{}任务失败,任务ID:{}", isEmptyPallet ? "空托出库" : "满托出库", outTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | // 更新缓存库位状态:O.闲置 → S.入库预约 |
| | | cacheLoc.setLocSts(LocStsType.LOC_STS_TYPE_S.type); |
| | | cacheLoc.setBarcode(outTask.getBarcode()); |
| | | cacheLoc.setModiTime(now); |
| | | if (!locCacheService.updateById(cacheLoc)) { |
| | | log.error("更新缓存库位状态失败,库位:{}", cacheLoc.getLocNo()); |
| | | // 回滚任务 |
| | | taskService.deleteById(cacheTask.getId()); |
| | | return; |
| | | } |
| | | |
| | | log.info("成功生成{}任务,任务ID:{},工作号:{},源站点:{},目标站点:{},缓存库位:{}", |
| | | isEmptyPallet ? "空托出库" : "满托出库", cacheTask.getId(), workNo, outboundStaNo, cacheStaNo, cacheLoc.getLocNo()); |
| | | } |
| | | |
| | | /** |
| | | * 按优先级分配缓存库位 |
| | | * 优先级规则: |
| | | * 1. 优先分配第三列(bay1=3),且该排的1、2、3列都是空的 |
| | | * 2. 如果所有第三列都有货,则分配第二列(bay1=2),且该排的1、2列都是空的 |
| | | * 3. 如果所有排的第二第三列都满了,则分配第一列(bay1=1) |
| | | * 4. 如果所有第一列都满了,再检查第二列和第三列 |
| | | * 5. 层(lev1)从第一层开始 |
| | | * |
| | | * @param whsType 库区类型 |
| | | * @param cacheAreaPrefix 缓存区库位前缀(如"WA") |
| | | * @param isEmptyPallet 是否空托 |
| | | * @return 分配的缓存库位,如果无法分配则返回null |
| | | */ |
| | | private LocCache allocateCacheLocationByPriority(Long whsType, String cacheAreaPrefix, boolean isEmptyPallet) { |
| | | // 查询所有符合条件的空库位 |
| | | List<LocCache> allLocations = locCacheService.selectList(new EntityWrapper<LocCache>() |
| | | .eq("whs_type", whsType) |
| | | .like("loc_no", cacheAreaPrefix + "%") |
| | | .eq("frozen", 0) |
| | | .eq("loc_sts", LocStsType.LOC_STS_TYPE_O.type) // O.闲置 |
| | | .ne("full_plt", isEmptyPallet ? "Y" : "N") // 空托不选满板库位,满托不选空板库位 |
| | | ); |
| | | |
| | | if (allLocations == null || allLocations.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // 按row1分组 |
| | | Map<Integer, List<LocCache>> locationsByRow = allLocations.stream() |
| | | .filter(loc -> loc.getRow1() != null) |
| | | .collect(Collectors.groupingBy(LocCache::getRow1)); |
| | | |
| | | if (locationsByRow.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // 对每个排,检查1、2、3列的状态 |
| | | // 列状态:true表示该列有空库位,false表示该列已满 |
| | | Map<Integer, Map<Integer, Boolean>> rowColumnStatus = new HashMap<>(); |
| | | for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) { |
| | | Integer row = entry.getKey(); |
| | | List<LocCache> rowLocs = entry.getValue(); |
| | | |
| | | Map<Integer, Boolean> columnStatus = new HashMap<>(); |
| | | // 检查第1、2、3列是否有空库位 |
| | | for (int bay = 1; bay <= 3; bay++) { |
| | | final int bayFinal = bay; // 创建final副本供lambda使用 |
| | | boolean hasEmpty = rowLocs.stream() |
| | | .anyMatch(loc -> loc.getBay1() != null && loc.getBay1() == bayFinal); |
| | | columnStatus.put(bay, hasEmpty); |
| | | } |
| | | rowColumnStatus.put(row, columnStatus); |
| | | } |
| | | |
| | | // 优先级1:分配第三列(bay1=3),且该排的1、2、3列都是空的 |
| | | for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) { |
| | | Integer row = entry.getKey(); |
| | | Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row); |
| | | |
| | | // 检查该排的1、2、3列是否都是空的 |
| | | if (Boolean.TRUE.equals(columnStatus.get(1)) && |
| | | Boolean.TRUE.equals(columnStatus.get(2)) && |
| | | Boolean.TRUE.equals(columnStatus.get(3))) { |
| | | // 分配该排的第三列,从第一层开始 |
| | | List<LocCache> bay3Locs = entry.getValue().stream() |
| | | .filter(loc -> loc.getBay1() != null && loc.getBay1() == 3) |
| | | .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!bay3Locs.isEmpty()) { |
| | | log.debug("优先级1:分配排{}的第三列,库位:{}", row, bay3Locs.get(0).getLocNo()); |
| | | return bay3Locs.get(0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 优先级2:分配第二列(bay1=2),且该排的1、2列都是空的(第三列可能已满) |
| | | for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) { |
| | | Integer row = entry.getKey(); |
| | | Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row); |
| | | |
| | | // 检查该排的1、2列是否都是空的 |
| | | if (Boolean.TRUE.equals(columnStatus.get(1)) && |
| | | Boolean.TRUE.equals(columnStatus.get(2))) { |
| | | // 分配该排的第二列,从第一层开始 |
| | | List<LocCache> bay2Locs = entry.getValue().stream() |
| | | .filter(loc -> loc.getBay1() != null && loc.getBay1() == 2) |
| | | .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!bay2Locs.isEmpty()) { |
| | | log.debug("优先级2:分配排{}的第二列,库位:{}", row, bay2Locs.get(0).getLocNo()); |
| | | return bay2Locs.get(0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 优先级3:分配第一列(bay1=1),所有排的第二第三列都满了 |
| | | for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) { |
| | | Integer row = entry.getKey(); |
| | | Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row); |
| | | |
| | | // 检查该排的第一列是否有空库位 |
| | | if (Boolean.TRUE.equals(columnStatus.get(1))) { |
| | | // 分配该排的第一列,从第一层开始 |
| | | List<LocCache> bay1Locs = entry.getValue().stream() |
| | | .filter(loc -> loc.getBay1() != null && loc.getBay1() == 1) |
| | | .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!bay1Locs.isEmpty()) { |
| | | log.debug("优先级3:分配排{}的第一列,库位:{}", row, bay1Locs.get(0).getLocNo()); |
| | | return bay1Locs.get(0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 优先级4:如果所有第一列都满了,再检查第二列和第三列(不要求该排的1、2列都是空的) |
| | | // 先检查第二列 |
| | | for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) { |
| | | Integer row = entry.getKey(); |
| | | Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row); |
| | | |
| | | // 检查该排的第二列是否有空库位 |
| | | if (Boolean.TRUE.equals(columnStatus.get(2))) { |
| | | List<LocCache> bay2Locs = entry.getValue().stream() |
| | | .filter(loc -> loc.getBay1() != null && loc.getBay1() == 2) |
| | | .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!bay2Locs.isEmpty()) { |
| | | log.debug("优先级4:分配排{}的第二列,库位:{}", row, bay2Locs.get(0).getLocNo()); |
| | | return bay2Locs.get(0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 优先级5:最后检查第三列(不要求该排的1、2、3列都是空的) |
| | | for (Map.Entry<Integer, List<LocCache>> entry : locationsByRow.entrySet()) { |
| | | Integer row = entry.getKey(); |
| | | Map<Integer, Boolean> columnStatus = rowColumnStatus.get(row); |
| | | |
| | | // 检查该排的第三列是否有空库位 |
| | | if (Boolean.TRUE.equals(columnStatus.get(3))) { |
| | | List<LocCache> bay3Locs = entry.getValue().stream() |
| | | .filter(loc -> loc.getBay1() != null && loc.getBay1() == 3) |
| | | .sorted(Comparator.comparing(loc -> loc.getLev1() != null ? loc.getLev1() : 0)) |
| | | .collect(Collectors.toList()); |
| | | |
| | | if (!bay3Locs.isEmpty()) { |
| | | log.debug("优先级5:分配排{}的第三列,库位:{}", row, bay3Locs.get(0).getLocNo()); |
| | | return bay3Locs.get(0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 如果所有列都满了,返回null |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 为出库到缓存区的任务分配站点(使用和入库一样的分配策略) |
| | | * @param cacheStations 缓存区站点列表 |
| | | * @param ioType 任务类型(101=全板出库,110=空板出库) |
| | | * @return 分配的站点编号,如果无法分配则返回null |
| | | */ |
| | | private String allocateCacheStation(List<String> cacheStations, Integer ioType) { |
| | | if (cacheStations == null || cacheStations.isEmpty()) { |
| | | log.warn("缓存区站点列表为空,无法分配站点"); |
| | | return null; |
| | | } |
| | | |
| | | // 将站点字符串列表转换为整数列表 |
| | | List<Integer> siteIntList = cacheStations.stream() |
| | | .map(Integer::parseInt) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 查询所有缓存区站点的设备信息(包含任务数) |
| | | List<BasDevp> devList = basDevpMapper.selectList(new EntityWrapper<BasDevp>() |
| | | .in("dev_no", siteIntList) |
| | | ); |
| | | |
| | | if (devList.isEmpty()) { |
| | | log.warn("缓存区站点{}在设备表中不存在", cacheStations); |
| | | return cacheStations.get(0); // 降级:返回第一个站点 |
| | | } |
| | | |
| | | // 按入库任务数排序(出库到缓存区也使用in_qty字段) |
| | | devList.sort(Comparator.comparing(BasDevp::getInQty)); |
| | | |
| | | // 获取最少任务数 |
| | | int minInQty = devList.get(0).getInQty(); |
| | | |
| | | // 筛选出任务数最少的站点列表 |
| | | List<BasDevp> minTaskSites = devList.stream() |
| | | .filter(dev -> dev.getInQty() == minInQty) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 根据配置选择分配策略 |
| | | String strategy = agvProperties.getSiteAllocation().getStrategy(); |
| | | boolean enableRoundRobin = agvProperties.getSiteAllocation().isEnableRoundRobin(); |
| | | |
| | | List<BasDevp> orderedSites = new ArrayList<>(); |
| | | String groupKey = "west"; // 缓存区使用西侧 |
| | | |
| | | if (minTaskSites.size() > 1 && enableRoundRobin && "round-robin".equals(strategy)) { |
| | | // 轮询分配:当多个站点任务数相同时,使用轮询 |
| | | AtomicInteger counter = siteRoundRobinCounters.computeIfAbsent(groupKey, k -> new AtomicInteger(0)); |
| | | int startIndex = counter.get() % minTaskSites.size(); |
| | | // 将轮询选中的站点放在最前面 |
| | | orderedSites.addAll(minTaskSites.subList(startIndex, minTaskSites.size())); |
| | | orderedSites.addAll(minTaskSites.subList(0, startIndex)); |
| | | // 添加其他站点(任务数更多的) |
| | | orderedSites.addAll(devList.stream() |
| | | .filter(dev -> dev.getInQty() > minInQty) |
| | | .collect(Collectors.toList())); |
| | | log.debug("使用轮询分配策略,站点组:{},轮询起始索引:{}", groupKey, startIndex); |
| | | } else if (minTaskSites.size() > 1 && enableRoundRobin && "random".equals(strategy)) { |
| | | // 随机分配:先随机排序任务数最少的站点 |
| | | List<BasDevp> shuffledMinSites = new ArrayList<>(minTaskSites); |
| | | Collections.shuffle(shuffledMinSites); |
| | | orderedSites.addAll(shuffledMinSites); |
| | | // 添加其他站点(任务数更多的) |
| | | orderedSites.addAll(devList.stream() |
| | | .filter(dev -> dev.getInQty() > minInQty) |
| | | .collect(Collectors.toList())); |
| | | log.debug("使用随机分配策略"); |
| | | } else { |
| | | // 默认:按入库任务数排序(已经排序好了) |
| | | orderedSites = devList; |
| | | } |
| | | |
| | | // 依次检查每个站点是否在搬运,找到第一个空闲站点就分配 |
| | | String selectedSite = null; |
| | | List<Integer> checkIoTypes = Arrays.asList(101, 110); // 出库到缓存区的任务类型 |
| | | |
| | | for (BasDevp dev : orderedSites) { |
| | | String staNo = String.valueOf(dev.getDevNo()); |
| | | |
| | | // 检查该站点是否有正在搬运的同类型任务 |
| | | List<Task> transportingTasks = taskService.selectList( |
| | | new EntityWrapper<Task>() |
| | | .eq("sta_no", staNo) |
| | | .eq("task_type", "agv") |
| | | .eq("wrk_sts", 8L) // 只检查正在搬运状态的任务 |
| | | .in("io_type", checkIoTypes) |
| | | ); |
| | | |
| | | if (!transportingTasks.isEmpty()) { |
| | | log.debug("缓存区站点{}有{}个正在搬运的出库AGV任务,检查下一个站点", |
| | | staNo, transportingTasks.size()); |
| | | continue; // 该站点正在搬运,检查下一个站点 |
| | | } |
| | | |
| | | // 找到第一个空闲站点,分配 |
| | | selectedSite = staNo; |
| | | log.info("出库到缓存区任务按规则应分配到站点{},该站点空闲,分配成功", staNo); |
| | | break; |
| | | } |
| | | |
| | | // 如果所有站点都在搬运,则不分配站点 |
| | | if (selectedSite == null) { |
| | | // log.warn("所有缓存区站点都有正在搬运的出库任务,暂不分配站点,等待空闲"); |
| | | return null; |
| | | } |
| | | |
| | | // 更新站点任务数(出库到缓存区也使用in_qty字段) |
| | | basDevpMapper.incrementInQty(Integer.parseInt(selectedSite)); |
| | | |
| | | return selectedSite; |
| | | } |
| | | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public ReturnT<String> agvDoIn(Task wrkMast) { |
| | | Integer ioType = wrkMast.getIoType(); |
| | | if (ioType == null) { |
| | | throw new CoolException("数据错误:ioType为空!!"); |
| | | } |
| | | |
| | | // 处理入库任务类型:1(实托入库)、10(空托入库)、53、57 |
| | | if (ioType == 1 || ioType == 10 || ioType == 53 || ioType == 57) { |
| | | // ioType == 1 需要处理组托数据 |
| | | if (ioType == 1) { |
| | | LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", wrkMast.getLocNo())); |
| | | if (Objects.isNull(locCache)) { |
| | | throw new CoolException("数据错误,库位不存在!!"); |
| | | } |
| | | if (!locCache.getLocSts().equals(LocStsType.LOC_STS_TYPE_S.type)) { |
| | | throw new CoolException("当前库位状态为:" + LocStsType.LOC_STS_TYPE_S.type + "." + LocStsType.LOC_STS_TYPE_S.desc + ",不是出库预约状态"); |
| | | } |
| | | List<TaskDetl> taskDetls = taskDetlService.selectList(new EntityWrapper<TaskDetl>().eq("task_id", wrkMast.getId())); |
| | | if (Objects.isNull(taskDetls)) { |
| | | throw new CoolException("数据错误:组托数据不存在!!"); |
| | | } |
| | | taskDetls.forEach(pakin -> { |
| | | LocCacheDetl detl = new LocCacheDetl(); |
| | | BeanUtils.copyProperties(pakin, detl); |
| | | detl.setBarcode(pakin.getBarcode()) |
| | | .setLocId(locCache.getId()) |
| | | .setAnfme(pakin.getAnfme()) |
| | | .setBrand(pakin.getBrand()) |
| | | .setAppeTime(new Date()) |
| | | .setSpecs(pakin.getSpecs()) |
| | | .setColor(pakin.getColor()) |
| | | .setLocNo(locCache.getLocNo()) |
| | | .setAreaId(locCache.getAreaId()) |
| | | .setAreaName(locCache.getAreaName()) |
| | | .setUnit(pakin.getUnit()) |
| | | .setBatch(pakin.getBatch()); |
| | | if (!locCacheDetlService.insert(detl)) { |
| | | throw new CoolException("库位明细保存失败!!"); |
| | | } |
| | | }); |
| | | |
| | | // 根据fullPlt设置库位状态:满托设置为"F"(在库),空托设置为"D"(空桶/空栈板) |
| | | boolean isFullPlt = wrkMast.getFullPlt() != null && wrkMast.getFullPlt().equals("Y"); |
| | | locCache.setLocSts(isFullPlt ? LocStsType.LOC_STS_TYPE_F.type : LocStsType.LOC_STS_TYPE_D.type); |
| | | locCache.setFullPlt(isFullPlt ? "Y" : "N"); |
| | | locCache.setModiTime(new Date()); |
| | | locCache.setBarcode(wrkMast.getBarcode()); |
| | | locCache.setIoTime(new Date()); |
| | | if (!locCacheService.updateById(locCache)) { |
| | | throw new CoolException("库位状态修改失败!"); |
| | | } |
| | | } else if (ioType == 10 || ioType == 53 || ioType == 57) { |
| | | // 空托入库或其他入库类型,也需要更新缓存库位状态 |
| | | LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>().eq("loc_no", wrkMast.getLocNo())); |
| | | if (locCache != null) { |
| | | // 根据fullPlt设置库位状态:满托设置为"F"(在库),空托设置为"D"(空桶/空栈板) |
| | | // ioType == 10 是空托入库,默认设置为"D" |
| | | boolean isFullPlt = (ioType != 10) && (wrkMast.getFullPlt() != null && wrkMast.getFullPlt().equals("Y")); |
| | | locCache.setLocSts(isFullPlt ? LocStsType.LOC_STS_TYPE_F.type : LocStsType.LOC_STS_TYPE_D.type); |
| | | locCache.setFullPlt(isFullPlt ? "Y" : "N"); |
| | | locCache.setModiTime(new Date()); |
| | | locCache.setBarcode(wrkMast.getBarcode()); |
| | | locCache.setIoTime(new Date()); |
| | | if (!locCacheService.updateById(locCache)) { |
| | | throw new CoolException("库位状态修改失败!"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 更新任务状态为5(库存更新完成) |
| | | wrkMast.setWrkSts(5L); |
| | | wrkMast.setModiTime(new Date()); |
| | | if (!taskService.updateById(wrkMast)) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | } else { |
| | | // 非入库任务类型,记录日志但不抛出异常,允许其他类型的任务通过 |
| | | log.warn("agvDoIn方法收到非入库任务类型,ioType:{},taskId:{},跳过处理", ioType, wrkMast.getId()); |
| | | } |
| | | |
| | | return SUCCESS; |
| | | } |
| | | } |