自动化立体仓库 - WMS系统
zwl
2 天以前 909cc78ba290cefc3c4623eff234e85ca0140e6d
src/main/java/com/zy/common/web/WcsController.java
@@ -9,6 +9,7 @@
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.CodeRes;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
@@ -46,64 +47,100 @@
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private  LocDetlService locDetlService;
    private LocDetlService locDetlService;
    @Autowired
    private RowLastnoService rowLastnoService;
    @Autowired
    private WorkService workService;
    @Autowired
    private StaDescService staDescService;
    @PostMapping("/pakin/loc/v1")
    @ResponseBody
    public synchronized R getLocNo(@RequestBody SearchLocParam param) {
        log.info("收到WCS入库接口请求====>>入参:{}", param);
        if (Cools.isEmpty(param.getIoType())) {
            return R.error("入出库类型不能为空");
        }
        if (Cools.isEmpty(param.getSourceStaNo())) {
            return R.error("源站编号不能为空");
        }
        List<WaitPakin> waitPakins = null;
        if (param.getIoType() == 1) {
        long startTime = System.currentTimeMillis();
        String barcode = param == null ? null : param.getBarcode();
        Integer sourceStaNo = param == null ? null : param.getSourceStaNo();
        try {
            if(param.getBarcode().contains("-") || param.getBarcode().contains("gsl")){
                log.info("收到WCS入库接口请求====>>入参:{}", param);
            }
            if (Cools.isEmpty(param.getSourceStaNo())) {
                return R.error("源站编号不能为空");
            }
            List<WaitPakin> waitPakins = null;
            if (Cools.isEmpty(param.getBarcode())) {
                return R.error("条码不能为空");
            }
            WrkMast wrkMast1 = wrkMastService.selectByBarcode(param.getBarcode());
            if (!Cools.isEmpty(wrkMast1) && wrkMast1.getWrkSts() == 2) {
                StartupDto dto1 = new StartupDto();
                dto1.setBarcode(param.getBarcode());
                dto1.setStaNo(Integer.valueOf(wrkMast1.getStaNo()));
                String wcsLoc = Utils.WMSLocToWCSLoc(wrkMast1.getLocNo());
                dto1.setLocNo(wcsLoc);
                dto1.setCrnNo(wrkMast1.getCrnNo());
                dto1.setWorkNo(wrkMast1.getWrkNo());
                dto1.setTaskNo(wrkMast1.getWrkNo() + "");
//            dto1.setTaskPri((int) Math.round(wrkMast1.getIoPri()));
                return R.ok(dto1);
            }
//        List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("io_type", 1));
//        if (!Cools.isEmpty(wrkMasts) && wrkMasts.size() > 10) {
//            return R.error("限行");
//        }
            waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBarcode()));
            if (Cools.isEmpty(waitPakins)) {
                WrkMast wrkMast = wrkMastService.selectByBarcode(param.getBarcode());
                if (wrkMast != null && wrkMast.getIoType() == 103) {
                    return R.parse(CodeRes.PICK_600);
                }
                return R.parse(CodeRes.NO_COMB_700);
                return R.error("请先添加入库通知档");
//            WrkMast wrkMast = wrkMastService.selectByBarcode(param.getBarcode());
//            if (wrkMast != null && wrkMast.getIoType() == 103) {
//                return R.parse(CodeRes.PICK_600);
//            }
//            Date now = new Date();
//            WaitPakin waitPakin = new WaitPakin();
//            waitPakin.setMatnr("emptyPallet");
//            waitPakin.setBatch("");
//            waitPakin.setAnfme(1D);
//            waitPakin.setZpallet(param.getBarcode());
//            waitPakin.setIoStatus("N");
//            waitPakin.setStatus("Y");
//            waitPakin.setAppeUser(9999L);
//            waitPakin.setAppeTime(now);
//            waitPakin.setModiUser(9999L);
//            waitPakin.setModiTime(now);
//            if (!waitPakinService.insert(waitPakin)) {
//                return R.error("自动生成入库通知档失败");
//            }
//            waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBarcode()));
//            if (Cools.isEmpty(waitPakins)) {
//                return R.error("自动生成入库通知档后未查询到数据");
//            }
//            log.info("WCS入库接口自动生成入库通知档, zpallet:{}, matnr:{}, anfme:{}", param.getBarcode(), "32149", 1D);
            }
             int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet",param.getBarcode()));
            int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet",param.getBarcode()));
            int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", param.getBarcode()));
            int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet", param.getBarcode()));
            if (countLoc > 0 || countWrk > 0) {
                return R.error(CodeRes.EXIST_500);
            }
        }
        if (Cools.isEmpty(param.getLocType1())){
            return R.error("高低检测信号不能为空");
        }
            if (Cools.isEmpty(param.getLocType1())) {
                return R.error("高低检测信号不能为空");
            }
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(param.getSourceStaNo(), true);
        sourceStaNo.setLocType1(param.getLocType1());
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
            // 源站点状态检测
            BasDevp sourceStaNoEntity = basDevpService.checkSiteStatus(param.getSourceStaNo(), true);
            sourceStaNoEntity.setLocType1(param.getLocType1());
            LocTypeDto locTypeDto = new LocTypeDto(sourceStaNoEntity);
            if (waitPakins.get(0).getMatnr().equals("emptyPallet")) {
                locTypeDto.setLocType2((short) 1);
            }
        StartupDto dto = null;
        switch (param.getIoType()) {
            case 1://满托盘入库
                assert waitPakins != null;
                dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins);
                break;
            case 10://空托盘入库
                dto = emptyPlateIn(param.getSourceStaNo(), locTypeDto, param.getBarcode());
                break;
            default:
                break;
            StartupDto dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins);
            log.info("WCS入库接口返参:{},托盘码:{}", dto, param.getBarcode());
            return R.ok().add(dto);
        } finally {
            log.info("WCS入库接口总耗时:{}ms, sourceStaNo:{}, barcode:{}", System.currentTimeMillis() - startTime, sourceStaNo, barcode);
        }
        log.info("WCS入库接口返参:{},托盘码:{}", dto, param.getBarcode());
        return R.ok().add(dto);
    }
    @PostMapping("/pakin/agv/loc/v1")
@@ -121,19 +158,24 @@
                return R.error("条码不能为空");
            }
        }
        if (Cools.isEmpty(param.getLocType1())){
        if (Cools.isEmpty(param.getLocType1())) {
            return R.error("高低检测信号不能为空");
        }
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(param.getSourceStaNo(), true);
        BasDevp sourceStaNo = basDevpService.selectById(param.getSourceStaNo());
        if (sourceStaNo.getWrkNo() == 0 && sourceStaNo.getDevNo() != 2033) {
            return R.error("站点工作号不存在");
        }
        sourceStaNo.setLocType1(param.getLocType1());
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        param.setIoType(10);
        StartupDto dto = null;
        switch (param.getIoType()) {
            case 1://满托盘入库
                dto = startupFullPutStoreAgv(param.getSourceStaNo(), param.getBarcode(), locTypeDto, param.getOutArea(), 1);
                break;
            case 10://空托盘入库
                dto = startupFullPutStoreAgv(param.getSourceStaNo(), param.getBarcode(), locTypeDto);
                dto = startupFullPutStoreAgv(param.getSourceStaNo(), param.getBarcode(), locTypeDto, param.getOutArea(), 10);
                break;
//                dto = emptyPlateIn(param.getSourceStaNo(), locTypeDto, param.getBarcode());
//                break;
@@ -146,15 +188,15 @@
    @PostMapping("/auto/emptyIn/v1")
    @ResponseBody
    public R autoEmptyIn(@RequestBody LocTypeDto locTypeDto){
    public R autoEmptyIn(@RequestBody LocTypeDto locTypeDto) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(1038, true);
        // 检索库位
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo( 10, 1038, findLocNoAttributeVo, locTypeDto);
        if (dto == null){
        StartupDto dto = commonService.getLocNo(10, 1038, findLocNoAttributeVo, locTypeDto);
        if (dto == null) {
            throw new CoolException("查询库位失败");
        }
        Date now = new Date();
@@ -183,27 +225,27 @@
        sourceStaNo.setWrkNo(dto.getWorkNo());
        sourceStaNo.setModiUser(9999L);
        sourceStaNo.setModiTime(now);
        if (!basDevpService.updateById(sourceStaNo)){
        if (!basDevpService.updateById(sourceStaNo)) {
            throw new CoolException("更新源站失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")){
        if (locMast.getLocSts().equals("O")) {
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiUser(9999L);
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)){
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
            throw new CoolException(dto.getLocNo() + "目标库位已被占用");
        }
        return wrkMastService.insert(wrkMast) ? R.ok("自动空托入库成功,工作号:"+wrkMast.getWrkNo()).add(wrkMast.getWrkNo()) : R.error("生成自动空托入库失败");
        return wrkMastService.insert(wrkMast) ? R.ok("自动空托入库成功,工作号:" + wrkMast.getWrkNo()).add(wrkMast.getWrkNo()) : R.error("生成自动空托入库失败");
    }
    @PostMapping("auto/emptyOut/v1")
    @ResponseBody
    public R autoEmptyOut(@RequestBody LocTypeDto locTypeDto){
    public R autoEmptyOut(@RequestBody LocTypeDto locTypeDto) {
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("loc_sts", "D"));
        if (Cools.isEmpty(locMast)) {
@@ -211,9 +253,11 @@
        }
        EmptyPlateOutParam emptyPlateOutParam = new EmptyPlateOutParam();
        emptyPlateOutParam.setOutSite(locTypeDto.getSiteId());
        emptyPlateOutParam.setLocNos(new ArrayList<String>(){{add(locMast.getLocNo()+"");}});
        emptyPlateOutParam.setLocNos(new ArrayList<String>() {{
            add(locMast.getLocNo() + "");
        }});
        WrkMast wrkMast = workService.emptyPlateOut(emptyPlateOutParam);
        return R.ok(!Cools.isEmpty(wrkMast)? R.ok("自动空托出库成功,工作号:" + wrkMast.getWrkNo()) : R.error("生成自动空托出库失败"));
        return R.ok(!Cools.isEmpty(wrkMast) ? R.ok("自动空托出库成功,工作号:" + wrkMast.getWrkNo()) : R.error("生成自动空托出库失败"));
    }
@@ -256,17 +300,22 @@
        }
        return workNo;
    }
    @PostMapping("/auto/TransplantingOut/v1")
    @ResponseBody
    public R autoTransplantingOut(@RequestBody TransplantWork transplantWork){
    public R autoTransplantingOut(@RequestBody TransplantWork transplantWork) {
        // 源站点状态检测
//        BasDevp sourceStaNo = basDevpService.checkSiteStatus(transplantWork.getStaNo(), true);
        WrkMast wrkMast1 = wrkMastService.selectWrkMast(transplantWork.getWorkNo(),transplantWork.getBarcode());
//        if(sourceStaNo ==null ){
        WrkMast wrkMast1 = wrkMastService.selectWrkMast(transplantWork.getWorkNo(), transplantWork.getBarcode());
//        if(sourceStaNo ==null )hnagbao1{
//            return R.error("该站点盘点移栽许可,请查看源站点状态检测");
//        }
        if(wrkMast1== null){
            return  R.error("无该盘点移栽任务");
        if (wrkMast1 == null) {
            return R.error("无该盘点移栽任务");
        }
        WrkMast wrkMast2 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", 9997));
        if (wrkMast2 != null) {
            throw new CoolException("存在9997盘点移栽任务");
        }
        List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(transplantWork.getWorkNo());
        Date now = new Date();
@@ -302,20 +351,24 @@
                throw new CoolException("保存工作明细失败");
            }
        }
        return wrkMastService.insert(wrkMast) ? R.ok("自动3号堆垛机移栽成功,工作号:"+wrkMast.getWrkNo()) : R.error("生成自动3号堆垛机移栽失败");
        return wrkMastService.insert(wrkMast) ? R.ok("自动3号堆垛机移栽成功,工作号:" + wrkMast.getWrkNo()) : R.error("生成自动3号堆垛机移栽失败");
    }
    @PostMapping("/auto/TransplantingIn/v1")
    @ResponseBody
    public R autoTransplantingIn(@RequestBody TransplantWork transplantWork){
    public R autoTransplantingIn(@RequestBody TransplantWork transplantWork) {
        // 源站点状态检测
//        BasDevp sourceStaNo = basDevpService.checkSiteStatus(transplantWork.getStaNo(), true);
        WrkMast wrkMast1 = wrkMastService.selectWrkMast(transplantWork.getWorkNo(),transplantWork.getBarcode());
        WrkMast wrkMast1 = wrkMastService.selectWrkMast(transplantWork.getWorkNo(), transplantWork.getBarcode());
//        if(sourceStaNo == null){
//
//        }
        if(wrkMast1== null){
            return  R.error("无该盘点移栽任务");
        if (wrkMast1 == null) {
            return R.error("无该盘点移栽任务");
        }
        WrkMast wrkMast2 = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", 9996));
        if (wrkMast2 != null) {
            throw new CoolException("存在9996盘点移栽任务");
        }
        List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(transplantWork.getWorkNo());
        Date now = new Date();
@@ -351,7 +404,7 @@
                throw new CoolException("保存工作明细失败");
            }
        }
        return wrkMastService.insert(wrkMast) ? R.ok("自动3号堆垛机移栽成功,工作号:"+wrkMast.getWrkNo()) : R.error("生成自动3号堆垛机移栽失败");
        return wrkMastService.insert(wrkMast) ? R.ok("自动3号堆垛机移栽成功,工作号:" + wrkMast.getWrkNo()) : R.error("生成自动3号堆垛机移栽失败");
    }
@@ -359,28 +412,29 @@
     * 全板入库AGV
     */
    @Transactional
    public StartupDto startupFullPutStoreAgv(Integer devpNo, String barcode, LocTypeDto locTypeDto) {
    public StartupDto startupFullPutStoreAgv(Integer devpNo, String barcode, LocTypeDto locTypeDto, Integer outArea, Integer staDescId) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
//        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        findLocNoAttributeVo.setOutArea(outArea);
//        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(waitPakins.get(0));
        StartupDto dto = commonService.getLocNo( 1, devpNo,findLocNoAttributeVo, locTypeDto);
        StartupDto dto = commonService.getLocNo(staDescId, devpNo, findLocNoAttributeVo, locTypeDto);
        // 更新目标库位状态
        Date now = new Date();
        if(dto == null){
        if (dto == null) {
            throw new CoolException("未找到库位");
        }
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")){
        if (locMast.getLocSts().equals("O")) {
            locMast.setLocSts("S"); // S.入库预约
            locMast.setBarcode(barcode);
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)){
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
            throw new CoolException(dto.getLocNo() + "目标库位已被占用");
        }
        return dto;
    }
@@ -391,91 +445,149 @@
     */
    @Transactional
    public StartupDto startupFullPutStore(Integer devpNo, String barcode, LocTypeDto locTypeDto, List<WaitPakin> waitPakins) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        List<String> matnrs = waitPakins.stream().map(WaitPakin::getMatnr).distinct().collect(Collectors.toList());
        List<String> batchs = waitPakins.stream().map(WaitPakin::getBatch).distinct().collect(Collectors.toList());
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(matnrs.get(0), batchs.get(0));
        long startTime = System.currentTimeMillis();
        try {
            // 源站点状态检测
            BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
            // 检索库位
            List<String> matnrs = waitPakins.stream().map(WaitPakin::getMatnr).distinct().collect(Collectors.toList());
            List<String> batchs = waitPakins.stream().map(WaitPakin::getBatch).distinct().collect(Collectors.toList());
            FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(matnrs.get(0), batchs.get(0));
//        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(waitPakins.get(0));
        StartupDto dto = commonService.getLocNo( 1, devpNo,findLocNoAttributeVo, locTypeDto);
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
        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(barcode); // 托盘码
        wrkMast.setFullPlt("Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("N"); // 空板
        wrkMast.setLinkMis("Y");
        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("保存工作明细失败");
            // IoT 指定了目标库位时优先尝试该库位;不可用时再退回现有自动找位规则。
            StartupDto dto = buildPreferredStartupDto(devpNo, extractPreferredInboundLoc(waitPakins));
            if (dto == null) {
                dto = commonService.getLocNo(1, devpNo, findLocNoAttributeVo, locTypeDto);
            }
        });
        // 更新入库通知档 ioStatus ===>> Y
        Wrapper<WaitPakin> wrapper = new EntityWrapper<WaitPakin>()
                .eq("zpallet", barcode);
        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("改变库位状态失败");
            int workNo = dto.getWorkNo();
            Date now = new Date();
            // 生成工作档
            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(barcode); // 托盘码
            wrkMast.setFullPlt("Y"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("N"); // 空板
            wrkMast.setLinkMis("Y");
            // 把 referenceId/orderNo 透传到工作主档,便于作业完成后继续回传给 IoT。
            wrkMast.setUserNo(waitPakins.get(0).getOrderNo());
            wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
            // 操作人员数据
            wrkMast.setAppeTime(now);
            wrkMast.setModiTime(now);
            boolean res = wrkMastService.insert(wrkMast);
            if (!res) {
                throw new CoolException("保存工作档失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
            // 生成工作档明细
            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", barcode);
            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() + "目标库位已被占用");
            }
            String wcsLoc = Utils.WMSLocToWCSLoc(dto.getLocNo());
            dto.setLocNo(wcsLoc);
            dto.setTaskNo(workNo + "");
            return dto;
        } finally {
            log.info("startupFullPutStore耗时:{}ms, sourceStaNo:{}, barcode:{}", System.currentTimeMillis() - startTime, devpNo, barcode);
        }
    }
    /**
     * 指定库位暂存在入库通知档 manu 字段,等 WCS 真正建任务时再读取。
     */
    private String extractPreferredInboundLoc(List<WaitPakin> waitPakins) {
        if (Cools.isEmpty(waitPakins)) {
            return null;
        }
        for (WaitPakin waitPakin : waitPakins) {
            if (!Cools.isEmpty(waitPakin.getManu())) {
                return waitPakin.getManu();
            }
        }
        return null;
    }
    /**
     * 把远端指定库位转换成可直接下发给 WCS 的目标站台和作业参数。
     * 如果库位已占用或对应设备不在自动模式,则返回 null 交给原有找位逻辑处理。
     */
    private StartupDto buildPreferredStartupDto(Integer sourceStaNo, String preferredLocNo) {
        if (Cools.isEmpty(preferredLocNo)) {
            return null;
        }
        LocMast targetLoc = locMastService.selectById(preferredLocNo);
        if (targetLoc == null || !"O".equalsIgnoreCase(targetLoc.getLocSts())) {
            return null;
        }
        StaDesc staDesc = staDescService.queryCrnStn(targetLoc.getCrnNo());
        if (staDesc == null) {
            return null;
        }
        BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn());
        if (staNo == null || !"Y".equalsIgnoreCase(staNo.getAutoing())) {
            return null;
        }
        StartupDto dto = new StartupDto();
        dto.setWorkNo(commonService.getWorkNo(0));
        dto.setCrnNo(targetLoc.getCrnNo());
        dto.setSourceStaNo(sourceStaNo);
        dto.setStaNo(staNo.getDevNo());
        dto.setLocNo(targetLoc.getLocNo());
        return dto;
    }
    @Transactional
    public StartupDto emptyPlateIn(Integer devpNo, LocTypeDto locTypeDto, String barcode) {
public StartupDto emptyPlateIn(Integer devpNo, LocTypeDto locTypeDto, String barcode) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo( 10, devpNo, findLocNoAttributeVo, locTypeDto);
        StartupDto dto = commonService.getLocNo(10, devpNo, findLocNoAttributeVo, locTypeDto);
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
@@ -505,19 +617,19 @@
        // 更新源站点信息
        sourceStaNo.setWrkNo(workNo);
        sourceStaNo.setModiTime(new Date());
        if (!basDevpService.updateById(sourceStaNo)){
        if (!basDevpService.updateById(sourceStaNo)) {
            throw new CoolException("更新源站失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")){
        if (locMast.getLocSts().equals("O")) {
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiTime(new Date());
            if (!locMastService.updateById(locMast)){
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
            throw new CoolException(dto.getLocNo() + "目标库位已被占用");
        }
        return dto;
    }