自动化立体仓库 - WMS系统
skyouc
14 小时以前 4693c6fa42d2cb72594b6b58e9fab9e0d4c224aa
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -11,6 +11,8 @@
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;
@@ -22,7 +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.MesCombParam;
import com.zy.common.model.enums.IoWorkType;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
@@ -120,6 +124,8 @@
    private BasContainerService basContainerService;
    @Autowired
    private BasAreasService basAreasService;
    @Autowired
    private StationRelaService stationRelaService;
    @Override
    @Transactional
@@ -658,7 +664,7 @@
                }
                if (elem.getAnfme() > detls.getEnableQty()) {
                    throw new CoolException(detls.getMatnr() + "入库数量不合法");
                    throw new CoolException(detls.getMatnr() + "入库数量不合规则");
                }
                OrderInAndOutUtil.increaseWorkQty(Boolean.TRUE, order.getId(), elem.getMatnr(), elem.getBatch(), elem.getBrand(), elem.getStandby1(), elem.getStandby2(), elem.getStandby3(),
                        elem.getBoxType1(), elem.getBoxType2(), elem.getBoxType3(), elem.getAnfme());
@@ -1282,7 +1288,7 @@
        generateCacheOutTask(station, locCaches, userId);
        /**生成立库出库任务*/
        generateCRNOutTask(locCaches);
        generateCRNOutTask(station, locCaches, userId);
        return R.ok();
    }
@@ -1297,7 +1303,7 @@
                .eq("loc_sts", LocStsType.LOC_STS_TYPE_D.type)
                .eq("area_id", basAreas.getId())
        );
        if (locCaches.isEmpty()){
        if (locCaches.isEmpty()) {
            throw new CoolException("暂无空板库位");
        }
@@ -1335,7 +1341,7 @@
        }
        List<Task> tasks = taskService.selectList(new EntityWrapper<Task>().eq("barcode", params.getBarcode()));
        if (!tasks.isEmpty()){
        if (!tasks.isEmpty()) {
            throw new CoolException("托盘码已生成任务");
        }
@@ -1343,8 +1349,7 @@
        List<LocCache> locCaches = locCacheService.selectList(new EntityWrapper<LocCache>()
                .in("loc_sts", LocStsType.LOC_STS_TYPE_O.type, LocStsType.LOC_STS_TYPE_D.type)
                .eq("area_id", basAreas.getId())
        );
                .eq("area_id", basAreas.getId()));
        if (locCaches.isEmpty()) {
            throw new CoolException("当前暂无空库位!!");
        }
@@ -1355,38 +1360,221 @@
    }
    /**
     * 缓存出库组托上架
     * @author Ryan
     * @date 2025/12/8 13:47
     * @param params
     * @return com.core.common.R
     */
    @Override
    public R combOutPub(AgvCallParams params) {
        return R.ok();
    }
    /**
     * 缓存组托数据
     * @author Ryan
     * @date 2025/12/8 15:37
     * @param params
     * @return com.core.common.R
     */
    @Override
    public R combCacehList(AgvCallParams params) {
        if (Objects.isNull(params.getBarcode())) {
            throw new CoolException("托盘码不能为空!!");
        }
        if (Objects.isNull(params.getBsCode())) {
            throw new CoolException("BS码不能为空!!");
        }
        Task task = taskService.selectOne(new EntityWrapper<Task>()
                .eq("io_type", TaskIOType.PICK_OUT.type)
                .eq("wrk_sts", 14)
                .eq("barcode", params.getBarcode()));
        if (Objects.isNull(task)) {
            throw new CoolException("数据错误:任务信息存在!!");
        }
        List<TaskDetl> taskDetl = taskDetlService.selectList(new EntityWrapper<TaskDetl>()
                .eq("three_code", params.getBsCode())
                .eq("zpallet", params.getBarcode()));
        if (Objects.isNull(taskDetl) || taskDetl.isEmpty()) {
            throw new CoolException("当前BS编码不存在!!");
        }
        return R.ok().add(taskDetl);
    }
    /**
     * 生成立库出库任务
     *
     * @param locCaches
     * @author Ryan
     * @date 2025/12/3 8:06
     * @param locCaches
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateCRNOutTask(LocCache locCaches) {
    public void generateCRNOutTask(BasStation station, LocCache locCaches, Long userId) {
        if (Objects.isNull(locCaches)) {
            throw new CoolException("库位不能为空!!");
        }
        //获取缓存区信息
        BasAreas basAreas = basAreasService.selectOne(new EntityWrapper<BasAreas>().eq("whs_type_id", LocAreaType.LOC_AREA_TYPE_IN_CACHE.type));
        if (Objects.isNull(basAreas)) {
            throw new CoolException("库区不存在!!");
        }
        List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>()
                .eq("area_id", basAreas.getAreaNo())
                .eq("area_id", basAreas.getId())
                .eq("loc_id", locCaches.getId()));
        if (Objects.isNull(locDetls)) {
            throw new CoolException("库存明细不存在!!");
        }
        //获取立库区信息
        BasAreas one = basAreasService.selectOne(new EntityWrapper<BasAreas>().eq("whs_type_id", LocAreaType.LOC_AREA_TYPE_CRN.type));
        if (Objects.isNull(one)) {
            throw new CoolException("数据错误:库区不存在!!");
        }
        //按物料编码分类
        List<StationRela> relas = stationRelaService.selectList(new EntityWrapper<StationRela>().eq("agv_sta", station.getDevNo()));
        if (Objects.isNull(relas) || relas.isEmpty()) {
            throw new CoolException("站点未关联堆垛机作业站点!!");
        }
        Set<String> crnStas = relas.stream().map(StationRela::getCrnSta).collect(Collectors.toSet());
        List<BasDevp> devps = basDevpService.selectList(new EntityWrapper<BasDevp>().in("dev_no", crnStas).eq("loading", CommonStation.COMMON_STATION_Y.type));
        if (Objects.isNull(devps) || devps.isEmpty()) {
            throw new CoolException("无站点可用!");
        }
        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));
        listMap.forEach((key, detls) -> {
        listMap.forEach((matnr, detls) -> {
            //根据supId(供应商)分类,得到出库总数
            Map<String, List<LocDetl>> supIds = detls.stream().collect(Collectors.groupingBy(LocDetl::getStandby1));
            supIds.forEach((supId, sups) -> {
                Double sum = sups.stream().mapToDouble(LocDetl::getAnfme).sum();
                //获取当前供应商+ 物料在库
                List<LocDetl> detlList = locDetlService.selectList(new EntityWrapper<LocDetl>()
                        .eq("matnr", matnr)
                        .eq("area_id", one.getId())
                        .eq("standby1", supId).orderAsc(Arrays.asList("appe_time")));
                //TODO  判断是否有新库位,没有新库位,再找有空格的位置放   1. 判断当前物料是否有库存 2. 没有余料查询新库位
                if (!Objects.isNull(detlList) && !detlList.isEmpty()) {
                    Map<String, List<LocDetl>> locMaps = detlList.stream().collect(Collectors.groupingBy(LocDetl::getLocNo));
                    locMaps.forEach((locNo, adetls) -> {
                        LocMast locMast = locMastService.selectById(locNo);
                        if (Objects.isNull(locMast)) {
                            throw new CoolException("数据错误,库位信息不存在!!");
                        }
                        BasContainer container = basContainerService.selectOne(new EntityWrapper<BasContainer>().eq("barcode", locMast.getBarcode()));
                        if (Objects.isNull(container)) {
                            throw new CoolException("数据错误,容器不存在!!");
                        }
                        Set<String> sets = adetls.stream().map(LocDetl::getMatnr).collect(Collectors.toSet());
                        //判断容器是否还可混放,及当前物料可放多少
                        if (container.getMixMax() > sets.size()) {
                            int suplus = container.getMixMax() - sets.size();
                            Mat mats = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", matnr));
                            if (Objects.isNull(mats)) {
                                throw new CoolException("物料不存在!!");
                            }
                            Double v = mats.getUpQty() * suplus;
                            //小于零
                            if (sum.compareTo(v) <= 0) {
                                //可放下
                                locMasts.add(locMast);
                            }
                        }
                    });
                }
            });
        });
        locDetls.forEach(locDetl -> {
        if (!locMasts.isEmpty()) {
            //生成堆垛机出库任务
            generateOutTask(locMasts, TaskIOType.MERGE_OUT.type, basDevp, userId);
        }
    }
        });
    /**
     * 生成堆垛机出库任务
     *
     * @param locMasts
     * @author Ryan
     * @date 2025/12/6 14:44
     */
    @Transactional(rollbackFor = Exception.class)
    public void generateOutTask(List<LocMast> locMasts, Integer ioType, BasDevp devp, Long userId) {
        Date now = new Date();
        for (LocMast locMast : locMasts) {
            if (Objects.isNull(ioType)) {
                continue;
            }
            Integer outSta = devp.getDevNo();
            // 获取路径
            StaDesc staDesc = staDescService.queryCrnStn(ioType, locMast.getCrnNo(), outSta);
            // 生成工作号
            int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
            // 生成工作档
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
            wrkMast.setIoType(ioType); // 入出库类型
            wrkMast.setIoPri(13D); // 优先级:13
            wrkMast.setCrnNo(locMast.getCrnNo());
            wrkMast.setSourceStaNo(staDesc.getCrnStn() + ""); // 源站
            wrkMast.setStaNo(staDesc.getStnNo() + ""); // 目标站
            wrkMast.setSourceLocNo(locMast.getLocNo()); // 源库位
            wrkMast.setFullPlt("Y"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("N"); // 空板
            wrkMast.setLinkMis("N");
            wrkMast.setBarcode(locMast.getBarcode());
            wrkMast.setAppeUser(userId); // 操作人员数据
            wrkMast.setAppeTime(now);
            wrkMast.setModiUser(userId);
            wrkMast.setModiTime(now);
            if (!wrkMastService.insert(wrkMast)) {
                throw new CoolException("保存工作档失败,出库库位号:" + locMast.getLocNo());
            }
            List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", locMast.getLocNo()));
            // 生成工作档明细
            for (LocDetl detlDto : locDetls) {
                WrkDetl wrkDetl = new WrkDetl();
                BeanUtils.copyProperties(detlDto, wrkDetl);
                wrkDetl.setOrderNo(""); // 手动出库不需要带出库存中的单据编号
                wrkDetl.setWrkNo(workNo);
                wrkDetl.setIoTime(now);
                wrkDetl.setAppeTime(now);
                wrkDetl.setAppeUser(userId);
                wrkDetl.setModiTime(now);
                wrkDetl.setModiUser(userId);
                if (!wrkDetlService.insert(wrkDetl)) {
                    throw new CoolException("保存工作档明细失败");
                }
            }
            // 修改库位状态:   F.在库 ====>>> R.出库预约/P.拣料/盘点/并板出库中
            locMast = locMastService.selectById(locMast.getLocNo());
            if (locMast.getLocSts().equals(LocStsType.LOC_STS_TYPE_F.type)) {
                locMast.setLocSts(ioType == 101 ? "R" : "P");
                locMast.setModiUser(userId);
                locMast.setModiTime(now);
                if (!locMastService.updateById(locMast)) {
                    throw new CoolException("预约库位状态失败,库位号:" + locMast.getLocNo());
                }
            } else {
                throw new CoolException(locMast.getLocNo() + "库位不是在库状态");
            }
        }
    }
    /**
@@ -1404,7 +1592,7 @@
        task.setWrkNo(workNo)
                .setIoTime(new Date())
                .setWrkSts(11L) // 工作状态:11.生成出库ID
                .setIoType(loc.getLocSts().equals("D") ? 110 : 101) // 入出库状态: 11.库格移载
                .setIoType(loc.getLocSts().equals("D") ? 110 : 103) // 入出库状态: 11.库格移载
                .setTaskType("agv")
                .setIoPri(10D)
                .setFullPlt(loc.getLocSts().equals("D") ? "N" : "Y") // 满板:Y
@@ -1422,7 +1610,9 @@
        if (!taskService.insert(task)) {
            throw new CoolException("保存工作档失败");
        }
        List<LocDetl> detls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_id", loc.getId()));
        List<LocDetl> detls = locDetlService.selectList(new EntityWrapper<LocDetl>()
                .eq("loc_no", loc.getLocNo()));
        if (!detls.isEmpty()) {
            List<TaskDetl> taskDetls = new ArrayList<>();
            detls.forEach(pakin -> {
@@ -1449,7 +1639,6 @@
            }
        }
        loc.setLocSts(LocStsType.LOC_STS_TYPE_R.type);
        loc.setModiUser(userId);
        loc.setModiTime(new Date());
@@ -1459,8 +1648,8 @@
        }
        // 修改目标站点信息
        if (station.getLocSts().equals("O")) {
            station.setLocSts("S"); // S.入库预约
        if (station.getLocSts().equals(LocStsType.LOC_STS_TYPE_O.type)) {
            station.setLocSts(LocStsType.LOC_STS_TYPE_S.type); // S.入库预约
            station.setModiTime(new Date());
            station.setModiUser(userId);
            if (!basStationService.updateById(station)) {
@@ -1534,7 +1723,9 @@
            throw new CoolException("保存工作档明细失败");
        }
        pakins.forEach(pakin -> {pakin.setIoStatus("Y");});
        pakins.forEach(pakin -> {
            pakin.setIoStatus("Y");
        });
        if (!waitPakinService.updateBatchById(pakins)) {
            throw new CoolException("更新组托信息失败");
@@ -1568,7 +1759,7 @@
    }
    public HIKResultDTO sendAgvTask(HIKApiDTO haiKangApiDTO,String path){
    public HIKResultDTO sendAgvTask(HIKApiDTO haiKangApiDTO, String path) {
        HIKResultDTO result = new HIKResultDTO();
        ForwardAGVTaskDTO forwardAGVTaskParam = new ForwardAGVTaskDTO();