自动化立体仓库 - WMS系统
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -11,8 +11,7 @@
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.LocAreaType;
import com.zy.asrs.enums.LocStsType;
import com.zy.asrs.enums.*;
import com.zy.asrs.enums.OrderSettle;
import com.zy.asrs.mapper.LocMastMapper;
import com.zy.asrs.mapper.ManLocDetlMapper;
@@ -23,7 +22,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;
@@ -121,6 +122,8 @@
    private BasContainerService basContainerService;
    @Autowired
    private BasAreasService basAreasService;
    @Autowired
    private StationRelaService stationRelaService;
    @Override
    @Transactional
@@ -653,7 +656,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());
@@ -1276,8 +1279,8 @@
        /**生成缓存区出库任务*/
        generateCacheOutTask(station, locCaches, userId);
        /**生成立库出库任务*/
        generateCRNOutTask(locCaches);
//        /**生成立库出库任务*/
        generateCRNOutTask(station, locCaches, userId);
        return R.ok();
    }
@@ -1314,31 +1317,165 @@
     */
    @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);
        }
    }
        });
    /**
     * 生成堆垛机出库任务
     * @author Ryan
     * @date 2025/12/6 14:44
     * @param locMasts
     */
    @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() + "库位不是在库状态");
            }
        }
    }
    /**
@@ -1397,9 +1534,6 @@
                    .setModiUser(userId);
            taskDetls.add(wrkDetl);
        });
        //保存工作档明细
        if (!taskDetlService.insertBatch(taskDetls)) {
            throw new CoolException("保存工作档明细失败");