自动化立体仓库 - WMS系统
pang.jiabao
昨天 fc12e6bbc12d0346076fefe7320e99fd14d13193
src/main/java/com/zy/common/service/CommonService.java
@@ -20,8 +20,8 @@
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 货架核心功能
@@ -448,7 +448,7 @@
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setTaskNo(workNo);
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locNo);
@@ -893,7 +893,7 @@
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setTaskNo(workNo);
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locNo);
@@ -1006,7 +1006,7 @@
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setTaskNo(workNo);
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(crnNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setLocNo(locNo);
@@ -1034,56 +1034,113 @@
        // 寻找到的库位
        LocMast locMast = null;
        // 按库位类型获取库位
        List<LocMast> locMasts = locMastMapper.selectLocByTypeAndRowsToList(locType,rows);
        // todo 如果当前类型库位剩余不多,是一直放满,还是兼容到下一种库位类型
        // 考虑移库需要同类型库位,这里限制不能放满,兼容下一种库位类型
        if (locMasts.size() <= 4) {
            switch (locType) {
                case 0:
                    return getLocNoNew(ioType, sourceStaNo, 1,rows);
                case 1:
                    return getLocNoNew(ioType, sourceStaNo, 2,rows);
                case 2:
                    return getLocNoNew(ioType, sourceStaNo, 3,rows);
                case 3:
                    log.warn("当前库位排:{},剩余{}个用于移库,无法占用",rows,locMasts.size());
                    return null;
                default:
            }
        // 可用堆垛机
        List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<BasCrnp>().eq("crn_sts", 3).eq("crn_err", 0).eq("in_enable","Y"));
        if (basCrnps.size() == 0) {
            log.error("入库请求库位失败,没有联机堆垛机或堆垛机异常");
            throw new CoolException("入库请求库位失败,没有联机堆垛机或堆垛机异常");
        }
        // 先取深库位
        Optional<LocMast> first = locMasts.stream().filter(o -> o.getRow1() == 1 || o.getRow1() == 4 || o.getRow1() == 5 || o.getRow1() == 8|| o.getRow1() == 9 || o.getRow1() == 12).findFirst();
        if (first.isPresent()) {
            locMast = first.get();
        } else {
            // 深库位里面没有从浅库位里面取
            Optional<LocMast> first2 = locMasts.stream().filter(o -> o.getRow1() == 2 || o.getRow1() == 3 || o.getRow1() == 6 || o.getRow1() == 7 || o.getRow1() == 10 || o.getRow1() == 11).findFirst();
            if(first2.isPresent()) {
                locMast = first2.get();
        // 一次查所有堆垛机任务数(group by)
        List<Map<String, Object>> countList = locMastMapper.selectMaps(
                new EntityWrapper<LocMast>()
                        .setSqlSelect("crn_no, COUNT(*) AS cnt")
                        .eq("loc_sts", "S")
                        .in("crn_no", basCrnps.stream().map(BasCrnp::getCrnNo).collect(Collectors.toList()))
                        .groupBy("crn_no")
        );
        // 堆垛机对应任务数
        Map<Integer, Integer> countMap = countList.stream()
                .collect(Collectors.toMap(
                        m -> (Integer) m.get("crn_no"),
                        m -> ((Number) m.get("cnt")).intValue()
                ));
        // 所有满足条件的库位
        List<LocMast> allLocs = locMastMapper.selectList(
                new EntityWrapper<LocMast>()
                        .eq("loc_type1", locType)
                        .eq("loc_sts" ,'O')
                        .in("crn_no", basCrnps.stream().map(BasCrnp::getCrnNo).collect(Collectors.toList()))
                        .last("ORDER BY CASE WHEN row1 IN (1,4,5,8,9,12) THEN 0 ELSE 1 END, lev1, bay1, row1")
        );
        // 按堆垛机分组
        Map<Integer, List<LocMast>> locMap = allLocs.stream()
                .collect(Collectors.groupingBy(LocMast::getCrnNo));
        // 堆垛机对应库位类型的剩余库位数大于4个的堆垛机保留
        List<BasCrnp> availableCrn = basCrnps.stream()
                .filter(c -> locMap.containsKey(c.getCrnNo()) && locMap.get(c.getCrnNo()).size() > 4)
                .collect(Collectors.toList());
        if (availableCrn.isEmpty()) {
            // 递归兼容
            if (locType >= 3) return null;
            return getLocNoNew(ioType, sourceStaNo, locType + 1, rows);
        }
        availableCrn.sort(Comparator.comparing(c -> countMap.getOrDefault(c.getCrnNo(), 0)));
        for (BasCrnp crnp : availableCrn) {
            List<LocMast> locs = locMap.get(crnp.getCrnNo());
            if (locs == null || locs.isEmpty()) {
                continue;
            }
            Map<String, LocMast> locNoMap = locs.stream()
                    .collect(Collectors.toMap(LocMast::getLocNo, e -> e));
            for(LocMast locMast1: locs) {
                String locNo = locMast1.getLocNo();
                // 是深库位
                if(Utils.isDeepLoc(slaveProperties,locMast1.getLocNo())){
                    // 获取浅库位
                    String shallowLoc = Utils.getShallowLoc(slaveProperties, locNo);
                    LocMast shallow = locNoMap.get(shallowLoc);
                    // 浅库位无货
                    if (shallow == null) {
                        locMast = locMast1;
                        break;
                    }
                } else { // 是浅库位,判断深库位是否为空,是则放,不是则跳过
                    // 获取深库位
                    String deepLoc = Utils.getDeepLoc(slaveProperties, locNo);
                    LocMast deep = locNoMap.get(deepLoc);
                    // 深库位不空放深库位
                    if (deep != null) {
                        locMast = deep;
                        break;
                    } else {
                        locMast = locMast1;
                        break;
                    }
                }
            }
            if (locMast != null) {
                break;
            }
        }
        if (locMast == null) {
            return null;
            if (locType >= 3) return null;
            return getLocNoNew(ioType, sourceStaNo, locType + 1, rows);
        }
        // 根据入库类型和源站点获取工作路径
//        StaDesc staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>().eq("type_no", ioType).eq("stn_no", sourceStaNo).eq("crn_no",locMast.getCrnNo()));
//        if (staDesc == null) {
//            log.error("获取工作路径异常,类型:{},源站点:{},库位:{}",ioType,sourceStaNo,locMast.getLocNo());
//            return null;
//        }
        StaDesc staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>().eq("type_no", ioType).eq("stn_no", sourceStaNo).eq("crn_no",locMast.getCrnNo()));
        if (staDesc == null) {
            log.error("获取工作路径异常,类型:{},源站点:{},库位:{}",ioType,sourceStaNo,locMast.getLocNo());
            throw new CoolException("获取工作路径异常");
        }
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        StartupDto startupDto = new StartupDto();
        startupDto.setTaskNo(workNo);
        startupDto.setWorkNo(workNo);
        startupDto.setCrnNo(locMast.getCrnNo());
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setStaNo(0);
        startupDto.setStaNo(staDesc.getCrnStn());
        startupDto.setLocNo(locMast.getLocNo());
        startupDto.setTaskPri(13D);