自动化立体仓库 - WMS系统
zwl
22 小时以前 a1b99c6eb0e36c36f7696eff9bc23ecf57206661
src/main/java/com/zy/api/service/impl/WcsApiServiceImpl.java
@@ -7,6 +7,7 @@
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.api.controller.params.ReassignLocParams;
import com.zy.api.controller.params.ReceviceTaskParams;
import com.zy.api.controller.params.StopOutTaskParams;
import com.zy.api.controller.params.WorkTaskParams;
@@ -18,6 +19,8 @@
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.constant.MesConstant;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import lombok.extern.slf4j.Slf4j;
@@ -28,6 +31,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -90,6 +94,8 @@
    private BasCrnpService basCrnpService;
    @Autowired
    private ApiLogService apiLogService;
    @Autowired
    private RowLastnoService rowLastnoService;
    /**
@@ -607,6 +613,62 @@
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R reassignInboundLoc(ReassignLocParams params) {
        if (params == null) {
            return R.error("参数不能为空!!");
        }
        if (Cools.isEmpty(params.getTaskNo())) {
            return R.error("任务号不能为空!!");
        }
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", params.getTaskNo()));
        String validateMsg = validateReassignInboundTask(wrkMast);
        if (!Cools.isEmpty(validateMsg)) {
            return R.error(validateMsg);
        }
        LocMast currentLoc = locMastService.selectById(wrkMast.getLocNo());
        if (Cools.isEmpty(currentLoc)) {
            return R.error("当前目标库位不存在");
        }
        Integer preferredArea = resolveReassignArea(wrkMast, currentLoc);
        if (preferredArea == null) {
            return R.error("无法确定任务所属库区");
        }
        List<Integer> candidateCrnNos = buildReassignCandidateCrnNos(preferredArea, wrkMast.getCrnNo());
        if (candidateCrnNos.isEmpty()) {
            return R.error("当前库区没有其他堆垛机可供重分配");
        }
        LocTypeDto locTypeDto = buildReassignLocTypeDto(currentLoc);
        StartupDto startupDto = commonService.findRun2InboundLocByCandidateCrnNos(
                wrkMast.getSourceStaNo(), wrkMast.getIoType(), preferredArea, candidateCrnNos, locTypeDto);
        if (startupDto == null || Cools.isEmpty(startupDto.getLocNo())) {
            return R.error("当前库区没有可重新分配的空库位");
        }
        LocMast targetLoc = locMastService.selectById(startupDto.getLocNo());
        if (Cools.isEmpty(targetLoc)) {
            throw new CoolException("新目标库位不存在");
        }
        if (!"O".equals(targetLoc.getLocSts())) {
            throw new CoolException(targetLoc.getLocNo() + "目标库位已被占用");
        }
        Date now = new Date();
        updateReassignTargetLoc(targetLoc, wrkMast, currentLoc, now);
        updateReassignWorkMast(wrkMast, startupDto, now);
        releaseOldReservedLocIfNeeded(currentLoc, targetLoc.getLocNo(), now);
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("locNo", Utils.WMSLocToWCSLoc(targetLoc.getLocNo()));
        return R.ok("操作成功").add(result);
    }
    private boolean requiresOutboundErpConfirm(WrkMast wrkMast) {
        Integer ioType = wrkMast == null ? null : wrkMast.getIoType();
        return ioType != null && (ioType == 101 || ioType == 103 || ioType == 104 || ioType == 107 || ioType == 110);
@@ -643,6 +705,172 @@
        return null;
    }
    private String validateReassignInboundTask(WrkMast wrkMast) {
        if (wrkMast == null) {
            return "任务不存在";
        }
        if (wrkMast.getIoType() == null || (wrkMast.getIoType() != 1 && wrkMast.getIoType() != 10)) {
            return "当前任务不是入库任务";
        }
        if (!Objects.equals(wrkMast.getWrkSts(), 2L)) {
            return "当前任务状态不允许重新分配入库位";
        }
        if (wrkMast.getCrnNo() == null) {
            return "当前任务未分配堆垛机";
        }
        if (Cools.isEmpty(wrkMast.getLocNo())) {
            return "当前任务未分配目标库位";
        }
        if (wrkMast.getSourceStaNo() == null) {
            return "当前任务缺少源站信息";
        }
        return null;
    }
    private Integer resolveReassignArea(WrkMast wrkMast, LocMast currentLoc) {
        Integer stationArea = Utils.getStationStorageArea(wrkMast.getSourceStaNo());
        if (belongsToArea(stationArea, wrkMast.getCrnNo(), currentLoc)) {
            return stationArea;
        }
        Integer fallbackArea = findAreaByCurrentTask(wrkMast.getCrnNo(), currentLoc);
        if (fallbackArea != null) {
            return fallbackArea;
        }
        return stationArea;
    }
    private Integer findAreaByCurrentTask(Integer currentCrnNo, LocMast currentLoc) {
        for (int area = 1; area <= 3; area++) {
            if (belongsToArea(area, currentCrnNo, currentLoc)) {
                return area;
            }
        }
        return null;
    }
    private boolean belongsToArea(Integer area, Integer currentCrnNo, LocMast currentLoc) {
        if (area == null || area <= 0) {
            return false;
        }
        RowLastno areaRowLastno = rowLastnoService.selectById(area);
        if (areaRowLastno == null) {
            return false;
        }
        Integer startCrnNo = resolveAreaStartCrnNo(areaRowLastno);
        Integer endCrnNo = resolveAreaEndCrnNo(areaRowLastno, startCrnNo);
        if (currentCrnNo != null && currentCrnNo >= startCrnNo && currentCrnNo <= endCrnNo) {
            return true;
        }
        Integer row = currentLoc == null ? null : currentLoc.getRow1();
        Integer startRow = areaRowLastno.getsRow();
        Integer endRow = areaRowLastno.geteRow();
        return row != null && startRow != null && endRow != null && row >= startRow && row <= endRow;
    }
    private List<Integer> buildReassignCandidateCrnNos(Integer area, Integer currentCrnNo) {
        RowLastno areaRowLastno = rowLastnoService.selectById(area);
        if (areaRowLastno == null) {
            throw new CoolException("未找到库区轮询规则");
        }
        int startCrnNo = resolveAreaStartCrnNo(areaRowLastno);
        int endCrnNo = resolveAreaEndCrnNo(areaRowLastno, startCrnNo);
        if (currentCrnNo == null || currentCrnNo < startCrnNo || currentCrnNo > endCrnNo) {
            throw new CoolException("当前任务堆垛机不在所属库区范围内");
        }
        List<Integer> candidateCrnNos = new ArrayList<>();
        for (int crnNo = currentCrnNo - 1; crnNo >= startCrnNo; crnNo--) {
            candidateCrnNos.add(crnNo);
        }
        for (int crnNo = endCrnNo; crnNo > currentCrnNo; crnNo--) {
            candidateCrnNos.add(crnNo);
        }
        return candidateCrnNos;
    }
    private int resolveAreaStartCrnNo(RowLastno areaRowLastno) {
        if (areaRowLastno.getsCrnNo() != null && areaRowLastno.getsCrnNo() > 0) {
            return areaRowLastno.getsCrnNo();
        }
        return 1;
    }
    private int resolveAreaEndCrnNo(RowLastno areaRowLastno, int startCrnNo) {
        if (areaRowLastno.geteCrnNo() != null && areaRowLastno.geteCrnNo() >= startCrnNo) {
            return areaRowLastno.geteCrnNo();
        }
        int crnQty = areaRowLastno.getCrnQty() == null || areaRowLastno.getCrnQty() <= 0 ? 1 : areaRowLastno.getCrnQty();
        return startCrnNo + crnQty - 1;
    }
    private LocTypeDto buildReassignLocTypeDto(LocMast currentLoc) {
        LocTypeDto locTypeDto = new LocTypeDto();
        if (currentLoc == null) {
            return locTypeDto;
        }
        locTypeDto.setLocType1(normalizeLocType(currentLoc.getLocType1()));
        locTypeDto.setLocType2(normalizeLocType(currentLoc.getLocType2()));
        locTypeDto.setLocType3(normalizeLocType(currentLoc.getLocType3()));
        return locTypeDto;
    }
    private Short normalizeLocType(Short locType) {
        return locType == null || locType <= 0 ? null : locType;
    }
    private void updateReassignTargetLoc(LocMast targetLoc, WrkMast wrkMast, LocMast currentLoc, Date now) {
        targetLoc.setLocSts("S");
        targetLoc.setModiUser(WCS_SYNC_USER);
        targetLoc.setModiTime(now);
        if (!Cools.isEmpty(wrkMast.getBarcode())) {
            targetLoc.setBarcode(wrkMast.getBarcode());
        } else if (!Cools.isEmpty(currentLoc) && !Cools.isEmpty(currentLoc.getBarcode())) {
            targetLoc.setBarcode(currentLoc.getBarcode());
        } else {
            targetLoc.setBarcode("");
        }
        if (wrkMast.getScWeight() != null) {
            targetLoc.setScWeight(wrkMast.getScWeight());
        } else if (!Cools.isEmpty(currentLoc) && currentLoc.getScWeight() != null) {
            targetLoc.setScWeight(currentLoc.getScWeight());
        } else {
            targetLoc.setScWeight(BigDecimal.ZERO);
        }
        if (!locMastService.updateById(targetLoc)) {
            throw new CoolException("改变库位状态失败");
        }
    }
    private void updateReassignWorkMast(WrkMast wrkMast, StartupDto startupDto, Date now) {
        wrkMast.setLocNo(startupDto.getLocNo());
        wrkMast.setCrnNo(startupDto.getCrnNo());
        if (startupDto.getStaNo() != null) {
            wrkMast.setStaNo(startupDto.getStaNo());
        }
        wrkMast.setWrkSts(2L);
        wrkMast.setModiUser(WCS_SYNC_USER);
        wrkMast.setModiTime(now);
        if (!wrkMastService.updateById(wrkMast)) {
            throw new CoolException("修改工作档失败");
        }
    }
    private void releaseOldReservedLocIfNeeded(LocMast currentLoc, String newLocNo, Date now) {
        if (currentLoc == null || Cools.isEmpty(currentLoc.getLocNo()) || currentLoc.getLocNo().equals(newLocNo)) {
            return;
        }
        if (!"S".equals(currentLoc.getLocSts())) {
            return;
        }
        currentLoc.setLocSts("O");
        currentLoc.setBarcode("");
        currentLoc.setScWeight(BigDecimal.ZERO);
        currentLoc.setModiUser(WCS_SYNC_USER);
        currentLoc.setModiTime(now);
        if (!locMastService.updateById(currentLoc)) {
            throw new CoolException("释放原目标库位失败");
        }
    }
    /**
     * 按任务类型选择 WCS 接口地址。
     * in -> 入库接口