自动化立体仓库 - WMS系统
skyouc
1 天以前 afe9f011522d1511019fe4e0471c686438845e11
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -8,11 +8,11 @@
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.*;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.entity.result.ForwardAGVTaskDTO;
import com.zy.asrs.entity.result.HIKApiDTO;
import com.zy.asrs.entity.result.HIKResultDTO;
import com.zy.asrs.enums.*;
import com.zy.asrs.enums.OrderSettle;
import com.zy.asrs.enums.LocAreaType;
import com.zy.asrs.enums.LocStsType;
import com.zy.asrs.mapper.LocMastMapper;
@@ -24,8 +24,9 @@
import com.zy.common.constant.MesConstant;
import com.zy.common.entity.Parameter;
import com.zy.common.model.DetlDto;
import com.zy.common.model.LocDetlDto;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.MesCombParam;
import com.zy.common.model.StartupDto;
import com.zy.common.model.enums.IoWorkType;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
@@ -40,6 +41,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
@@ -126,6 +128,8 @@
    private BasAreasService basAreasService;
    @Autowired
    private StationRelaService stationRelaService;
    @Autowired
    private BasStationDetlService basStationDetlService;
    @Override
    @Transactional
@@ -1362,10 +1366,11 @@
    /**
     * 缓存出库组托上架
     * @author Ryan
     * @date 2025/12/8 13:47
     *
     * @param params 
     * @return com.core.common.R
     * @author Ryan
     * @date 2025/12/8 13:47
     */
    @Override
    public R combOutPub(AgvCallParams params) {
@@ -1375,10 +1380,11 @@
    /**
     * 缓存组托数据
     * @author Ryan
     * @date 2025/12/8 15:37
     *
     * @param params
     * @return com.core.common.R
     * @author Ryan
     * @date 2025/12/8 15:37
     */
    @Override
    public R combCacehList(AgvCallParams params) {
@@ -1408,7 +1414,240 @@
    }
    /**
     * 缓存区上架组托
     *
     * @param param
     * @param userId
     * @author Ryan
     * @date 2025/12/9 13:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cacheComb(CombParam param, Long userId) {
        if (Objects.isNull(param.getBarcode())) {
            throw new CoolException("托盘码不能为空!!");
        }
        if (Objects.isNull(param.getCombMats()) || param.getCombMats().isEmpty()) {
            throw new CoolException("组托明细不能为空!!");
        }
        // 判断是否有相同条码的数据
        if (waitPakinService.selectCount(new EntityWrapper<WaitPakin>().
                eq("zpallet", param.getBarcode())
                .eq("io_status", "N")) > 0) {
            throw new CoolException(param.getBarcode() + "数据正在进行入库");
        }
        int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", param.getBarcode()));
        int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet", param.getBarcode()));
        int countwait = waitPakinService.selectCount(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBarcode()));
        if (countLoc > 0 || countWrk > 0 || countwait > 0) {
            throw new CoolException("组托档/工作档/库存条码数据已存在===>>" + param.getBarcode());
        }
        // 生成入库通知档
        List<DetlDto> detlDtos = new ArrayList<>();
        param.getCombMats().forEach(elem -> {
            DetlDto detlDto = new DetlDto(elem.getMatnr(), elem.getBatch(), elem.getBrand(), elem.getStandby1(), elem.getStandby2(), elem.getStandby3(),
                    elem.getBoxType1(), elem.getBoxType2(), elem.getBoxType3(), elem.getAnfme(), elem.getThreeCode());
            if (DetlDto.has(detlDtos, detlDto)) {
                DetlDto one = DetlDto.findDto(detlDtos, detlDto);
                assert one != null;
                one.setAnfme(one.getAnfme() + detlDto.getAnfme());
            } else {
                detlDtos.add(detlDto);
            }
        });
        Date now = new Date();
        for (DetlDto detlDto : detlDtos) {
            Mat mat = matService.selectByMatnr(detlDto.getMatnr());
            if (Cools.isEmpty(mat)) {
                throw new CoolException(detlDto.getMatnr() + "商品档案不存在");
            }
            if (mat.getUpQty().compareTo(detlDto.getAnfme()) < 0) {
                throw new CoolException("物料:" + detlDto.getMatnr() + "单次最大组托上限为:" + mat.getUpQty());
            }
            WaitPakin waitPakin = new WaitPakin();
            BeanUtils.copyProperties(mat, waitPakin);
            waitPakin.setBatch(detlDto.getBatch());
            waitPakin.setZpallet(param.getBarcode());
            //设置组托类型
            waitPakin.setType(CommonEnum.COMMON_ENUM_Y.type + "");
            waitPakin.setIoStatus("N");
            waitPakin.setAnfme(detlDto.getAnfme());
            waitPakin.setThreeCode(detlDto.getThreeCode());
            waitPakin.setStatus("Y");
            waitPakin.setStandby1(detlDto.getStandby1());
            waitPakin.setStandby2(detlDto.getStandby2());
            waitPakin.setStandby3(detlDto.getStandby3());
            waitPakin.setBoxType1(detlDto.getBoxType1());
            waitPakin.setBoxType2(detlDto.getBoxType2());
            waitPakin.setBoxType3(detlDto.getBoxType3());
            waitPakin.setAppeUser(userId);
            waitPakin.setAppeTime(now);
            waitPakin.setModiUser(userId);
            waitPakin.setModiTime(now);
            if (!waitPakinService.insert(waitPakin)) {
                throw new CoolException("保存入库通知档失败");
            }
        }
    }
    /**
     * 缓存入库上架
     *
     * @param param
     * @param userId
     * @author Ryan
     * @date 2025/12/9 15:05
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void combInPub(CompleteParam param, Long userId) {
        if (Objects.isNull(param.getBarcode())) {
            throw new CoolException("托盘码不能为空!!");
        }
        if (Objects.isNull(param.getStation())) {
            throw new CoolException("站点不能为空!!");
        }
        //TODO 修改缓存站点状态及数据
        Task task = taskService.selectOne(new EntityWrapper<Task>().eq("barcode", param.getBarcode()));
        if (Objects.isNull(task)) {
            throw new CoolException("数据错误,任务不存在!!");
        }
        List<TaskDetl> taskDetls = taskDetlService.selectList(new EntityWrapper<TaskDetl>().eq("wrk_no", task.getWrkNo()));
        if (Objects.isNull(taskDetls) || taskDetls.isEmpty()) {
            throw new CoolException("数据错误,任务明细不存在!!");
        }
        BasStation station = basStationService.selectOne(new EntityWrapper<BasStation>()
                .eq("dev_no", task.getStaNo()));
        if (Objects.isNull(station)) {
            throw new CoolException("站点不存在!!");
        }
        station.setLocSts(LocStsType.LOC_STS_TYPE_O.type);
        if (!basStationService.updateById(station)) {
            throw new CoolException("站点状态修改失败!");
        }
        if (!basStationDetlService.delete(new EntityWrapper<BasStationDetl>().eq("dev_no", station.getDevNo()))) {
            throw new CoolException("站点删除失败!");
        }
        //任务完成
        task.setWrkSts(15L);
        if (!taskService.updateById(task)) {
            throw new CoolException("AGV任务完成失败!!");
        }
        List<WaitPakin> waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("barcodee", param.getBarcode()));
        if (Objects.isNull(waitPakins) || waitPakins.isEmpty()) {
            throw new CoolException("数据错误,组拖档已不存在!!");
        }
        generateCrnInTask(waitPakins, station, param.getLocType1(), userId);
    }
    /**
     * 生成堆垛机入库任务
     *
     * @param station
     * @author Ryan
     * @date 2025/12/9 13:54
     */
    @Transactional(rollbackFor = Exception.class)
    public void generateCrnInTask(List<WaitPakin> waitPakins, BasStation station, Short locType,  Long userId) {
        Date now = new Date();
        StationRela rela = stationRelaService.selectOne(new EntityWrapper<StationRela>()
                .eq("dev_no", station.getDevNo())
                .last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY"));
        if (Objects.isNull(rela)) {
            throw new CoolException("未绑定作业站点!!");
        }
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(Integer.parseInt(rela.getCrnSta()), true);
        sourceStaNo.setLocType1(locType);
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        WaitPakin pakin = waitPakins.stream().findFirst().get();
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(pakin);
        StartupDto dto = commonService.getLocNo( 1, sourceStaNo.getDevNo(),findLocNoAttributeVo, locTypeDto);
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(new Date());
        wrkMast.setWrkSts(2L); // 工作状态:生成入库ID
        wrkMast.setIoType(1); // 入出库状态:1.入库
        wrkMast.setIoPri(13D); // 优先级
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo() + "");
        wrkMast.setStaNo(dto.getStaNo() + "");
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setBarcode(pakin.getBarcode()); // 托盘码
        wrkMast.setFullPlt("Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("N"); // 空板
        wrkMast.setLinkMis("Y");
        wrkMast.setModiUser(userId);
        wrkMast.setAppeUser(userId);
        wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
        // 操作人员数据
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            throw new CoolException("保存工作档失败");
        }
        // 生成工作档明细
        waitPakins.forEach(waitPakin -> {
            WrkDetl wrkDetl = new WrkDetl();
            wrkDetl.sync(waitPakin);
            wrkDetl.setWrkNo(wrkMast.getWrkNo());
            wrkDetl.setIoTime(wrkMast.getIoTime());
            wrkDetl.setAppeTime(now);
            wrkDetl.setModiTime(now);
            if (!wrkDetlService.insert(wrkDetl)) {
                throw new CoolException("保存工作明细失败");
            }
        });
        // 更新入库通知档 ioStatus ===>> Y
        Wrapper<WaitPakin> wrapper = new EntityWrapper<WaitPakin>()
                .eq("zpallet", pakin.getBarcode());
        WaitPakin setParam = new WaitPakin();
        setParam.setLocNo(dto.getLocNo());
        setParam.setIoStatus("Y");
        setParam.setModiTime(now);
        if (!waitPakinService.update(setParam, wrapper)) {
            throw new CoolException("更新通知档失败");
        }
        // 更新源站点信息
        sourceStaNo.setWrkNo(workNo);
        sourceStaNo.setModiTime(now);
        if (!basDevpService.updateById(sourceStaNo)){
            throw new CoolException("更新源站失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")){
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)){
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
        }
    }
    /**
     * 生成立库出库任务
     * 台车过来默认是同一种物料类型
     *
     * @param locCaches
     * @author Ryan
@@ -1428,9 +1667,20 @@
        List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>()
                .eq("area_id", basAreas.getId())
                .eq("loc_id", locCaches.getId()));
        if (Objects.isNull(locDetls)) {
        if (Objects.isNull(locDetls) || locDetls.isEmpty()) {
            throw new CoolException("库存明细不存在!!");
        }
        Set<String> set = locDetls.stream().map(LocDetl::getMatnr).collect(Collectors.toSet());
        List<Mat> matList = matService.selectList(new EntityWrapper<Mat>().in("matnr", set));
        if (Objects.isNull(matList) || matList.isEmpty()) {
            throw new CoolException("物料库不存在该物料!!");
        }
        Set<Long> longs = matList.stream().map(Mat::getTagId).collect(Collectors.toSet());
        if (!longs.isEmpty() && longs.size() > 1) {
            throw new CoolException("物料类型不一致,请检查数据是否正确!!");
        }
        //获取立库区信息
        BasAreas one = basAreasService.selectOne(new EntityWrapper<BasAreas>().eq("whs_type_id", LocAreaType.LOC_AREA_TYPE_CRN.type));
        if (Objects.isNull(one)) {
@@ -1450,9 +1700,9 @@
        }
        Collections.shuffle(devps);
        BasDevp basDevp = devps.stream().findFirst().get();
        List<LocMast> locMasts = new ArrayList<>();
        Map<String, List<LocDetl>> listMap = locDetls.stream().collect(Collectors.groupingBy(LocDetl::getMatnr));
        AtomicReference<Double> totalOut = new AtomicReference<>(locDetls.stream().mapToDouble(LocDetl::getAnfme).sum());
        listMap.forEach((matnr, detls) -> {
            //根据supId(供应商)分类,得到出库总数
            Map<String, List<LocDetl>> supIds = detls.stream().collect(Collectors.groupingBy(LocDetl::getStandby1));
@@ -1488,6 +1738,7 @@
                            if (sum.compareTo(v) <= 0) {
                                //可放下
                                locMasts.add(locMast);
                                totalOut.set(Math.round((totalOut.get() - sum) * 10000) / 10000.0);
                            }
                        }
                    });
@@ -1495,11 +1746,28 @@
            });
        });
        //判断根据分拣出库后,还需要出多少托盘或料箱;如果余料大于0, 出新托盘或料箱
        if (totalOut.get().compareTo(0.0) > 0) {
//            Set<String> matnrs = locDetls.stream().map(LocDetl::getMatnr).collect(Collectors.toSet());
//            List<Mat> mats = matService.selectList(new EntityWrapper<Mat>().in("matnr", matnrs));
            LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                    //todo 根据物料种类,区分库区类型
                    .eq("loc_sts", LocStsType.LOC_STS_TYPE_D.type)
                    .orderAsc(Arrays.asList("row1", "bay1", "lev1"))
                    .last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY"));
            locMasts.add(locMast);
            //空板出库
            generateTask(locMasts, TaskIOType.EMPTY_OUT.type, basDevp, userId);
        } else {
        if (!locMasts.isEmpty()) {
            //生成堆垛机出库任务
            generateOutTask(locMasts, TaskIOType.MERGE_OUT.type, basDevp, userId);
                generateTask(locMasts, TaskIOType.MERGE_OUT.type, basDevp, userId);
        }
    }
    }
    /**
     * 生成堆垛机出库任务
@@ -1509,7 +1777,7 @@
     * @date 2025/12/6 14:44
     */
    @Transactional(rollbackFor = Exception.class)
    public void generateOutTask(List<LocMast> locMasts, Integer ioType, BasDevp devp, Long userId) {
    public void generateTask(List<LocMast> locMasts, Integer ioType, BasDevp devp, Long userId) {
        Date now = new Date();
        for (LocMast locMast : locMasts) {
            if (Objects.isNull(ioType)) {