自动化立体仓库 - WMS系统
zhou zhou
2025-12-25 418a73bcee019e078307a1c2c255235de33d20ca
src/main/java/com/zy/common/web/WcsController.java
@@ -1,23 +1,36 @@
package com.zy.common.web;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.result.FindLocNoAttributeVo;
import com.zy.asrs.enums.LocAreaType;
import com.zy.asrs.enums.LocStsType;
import com.zy.asrs.enums.TaskIOType;
import com.zy.asrs.service.*;
import com.zy.common.CodeRes;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
import com.zy.common.web.param.GenerateAgvTaskParam;
import com.zy.common.web.param.SearchLocParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static com.zy.asrs.enums.TaskIOType.EMPTY_IN;
/**
 * Created by vincent on 2020/10/30
@@ -40,11 +53,112 @@
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private  LocDetlService locDetlService;
    private LocDetlService locDetlService;
    @Autowired
    private RowLastnoService rowLastnoService;
    @Autowired
    private WorkService workService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private TaskDetlService taskDetlService;
    @Autowired
    private BasAreasService basAreasService;
    @Autowired
    private LocCacheService locCacheService;
    @PostMapping("/generate/AgvTask/v1")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public synchronized R generateAgvTask(@RequestBody GenerateAgvTaskParam param) {
        if (Cools.isEmpty(param.getStaNo(),param.getWrkNo())){
            return R.error("站点编号和工作号不能为空");
        }
        Task searchTask = taskService.selectOne(new EntityWrapper<Task>()
                .eq("source_sta_no", param.getStaNo())
        );
        if (!Cools.isEmpty(searchTask)){
            return R.error("任务已存在");
        }
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
                .eq("wrk_no", param.getWrkNo())
                .eq("sta_no", param.getStaNo())
        );
        List<WrkDetl> wrkDetls = wrkDetlService.selectList(new EntityWrapper<WrkDetl>()
                .eq("wrk_no", param.getWrkNo())
        );
        if (Cools.isEmpty(wrkMast) || Cools.isEmpty(wrkDetls)){
            return R.error("工作关联任务或明细不存在");
        }
        BasAreas basAreas = basAreasService
                .selectOne(new EntityWrapper<BasAreas>().eq("whs_type_id", LocAreaType.LOC_AREA_TYPE_CK.type));
        LocCache locCache = locCacheService.selectOne(new EntityWrapper<LocCache>()
                .eq("area_id", basAreas.getId())
                .eq("frozen", 0)
                .eq("loc_sts", LocStsType.LOC_STS_TYPE_O.type)
                // .eq("loc_no", params.getTarSite())
                .orderAsc(Arrays.asList("loc_no"))
                .last("OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY"));
        // 获取工作号
        int workNo = commonService.getWorkNo(WorkNoType.PICK.type);
        // 保存工作档
        Task task = new Task();
        Date now = new Date();
        task.setWrkNo(workNo)
                .setIoTime(now)
                .setWrkSts(7L) // 工作状态:11.生成出库ID
                .setIoType(1) // 入出库状态: 1.入库
                .setTaskType("agv")
                .setIoPri(10D)
                .setLocNo(locCache.getLocNo()) // 目标库位
                .setFullPlt(wrkMast.getIoType().equals(TaskIOType.EMPTY_IN.type) ? "N" : "Y")// 满板:Y
                .setPicking("N") // 拣料
                .setExitMk("N")// 退出
                .setSourceStaNo(param.getStaNo().toString())
                .setEmptyMk(wrkMast.getIoType().equals(TaskIOType.EMPTY_IN.type) ? "Y" : "N")// 空板
                .setBarcode(wrkMast.getBarcode())// 托盘码
                .setLinkMis("N")
                .setAppeTime(now)
                .setModiTime(now);
        if (!taskService.insert(task)) {
            throw new CoolException("保存工作档失败");
        }
        wrkDetls.forEach(wrkDetl -> {
            TaskDetl taskDetl = new TaskDetl();
            BeanUtils.copyProperties(wrkDetl, taskDetl);
            taskDetl.setTaskId(task.getId());
            taskDetl.setWrkNo(task.getWrkNo());
            taskDetl.setAppeTime(now);
            taskDetl.setModiTime(now);
            if (!taskDetlService.insert(taskDetl)) {
                throw new CoolException("保存AGV工作档明细失败");
            }
        });
        // 修改目标库位状态
        if (locCache.getLocSts().equals(LocStsType.LOC_STS_TYPE_O.type)) {
            locCache.setLocSts(LocStsType.LOC_STS_TYPE_S.type); // S.入库预约
            locCache.setModiTime(new Date());
            if (!locCacheService.updateById(locCache)) {
                throw new CoolException("更新目标库位状态失败");
            }
        } else {
            throw new CoolException("移转失败,目标库位状态:" + locCache.getLocSts$());
        }
        return R.ok();
    }
    @PostMapping("/pakin/loc/v1")
    @ResponseBody
    public synchronized R getLocNo(@RequestBody SearchLocParam param) {
        log.info("收到WCS入库接口请求====>>入参:{}", param);
        if (Cools.isEmpty(param.getIoType())) {
            return R.error("入出库类型不能为空");
        }
@@ -56,22 +170,27 @@
            if (Cools.isEmpty(param.getBarcode())) {
                return R.error("条码不能为空");
            }
            waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("barcode", param.getBarcode()));
            waitPakins = waitPakinService.selectList(new EntityWrapper<WaitPakin>().eq("zpallet", param.getBarcode()));
            if (Cools.isEmpty(waitPakins)) {
                return R.error("条码数据错误");
                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);
            }
            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("工作档/库存条码数据已存在");
                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);
        StartupDto dto = null;
@@ -81,15 +200,66 @@
                dto = startupFullPutStore(param.getSourceStaNo(), param.getBarcode(), locTypeDto, waitPakins);
                break;
            case 10://空托盘入库
                dto = emptyPlateIn(param.getSourceStaNo(), locTypeDto);
                dto = emptyPlateIn(param.getSourceStaNo(), locTypeDto, param.getBarcode());
                break;
            default:
                break;
        }
        log.info("WCS入库接口返参:{},托盘码:{}", dto, param.getBarcode());
        return R.ok().add(dto);
    }
    @PostMapping("/auto/emptyIn/v1")
    @ResponseBody
    public R autoEmptyIn(@RequestBody LocTypeDto locTypeDto) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(12, true);
        // 检索库位
        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
        StartupDto dto = commonService.getLocNo(10, 12, findLocNoAttributeVo, locTypeDto);
        Date now = new Date();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(dto.getWorkNo());
        wrkMast.setIoTime(now);
        wrkMast.setWrkSts(1L);
        wrkMast.setIoPri(13D);
        wrkMast.setIoType(10);
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo() + "");
        wrkMast.setStaNo(dto.getStaNo() + "");
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setFullPlt("N"); // 满板:N
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("Y"); // 空板
        wrkMast.setLinkMis("Y");
        wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
        // 操作人员数据
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        wrkMast.setMemo("自动空托入库");
        return wrkMastService.insert(wrkMast) ? R.ok("自动空托入库成功,工作号:" + wrkMast.getWrkNo()) : R.error("生成自动空托入库失败");
    }
    @PostMapping("auto/emptyOut/v1")
    @ResponseBody
    public R autoEmptyOut() {
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("loc_sts", "D"));
        if (Cools.isEmpty(locMast)) {
            return R.error("库存没有空板");
        }
        EmptyPlateOutParam emptyPlateOutParam = new EmptyPlateOutParam();
        emptyPlateOutParam.setOutSite(12);
        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("生成自动空托出库失败"));
    }
    /**
     * 全板入库
@@ -99,8 +269,8 @@
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        List<String> matNos = waitPakins.stream().map(WaitPakin::getMatnr).distinct().collect(Collectors.toList());
        StartupDto dto = commonService.getLocNo(1, 1, devpNo, matNos, locTypeDto,0);
//        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo(waitPakins.get(0));
        StartupDto dto = commonService.getLocNoBySdyhfz(devpNo,1);
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
@@ -111,8 +281,8 @@
        wrkMast.setIoType(1); // 入出库状态:1.入库
        wrkMast.setIoPri(13D); // 优先级
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo());
        wrkMast.setStaNo(dto.getStaNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo() + "");
        wrkMast.setStaNo(dto.getStaNo() + "");
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setBarcode(barcode); // 托盘码
        wrkMast.setFullPlt("Y"); // 满板:Y
@@ -140,32 +310,45 @@
                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)){
        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(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;
    }
    @Transactional
    public StartupDto emptyPlateIn(Integer devpNo, LocTypeDto locTypeDto) {
    public StartupDto emptyPlateIn(Integer devpNo, LocTypeDto locTypeDto, String barcode) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        StartupDto dto = commonService.getLocNo(1, 10, devpNo, null, locTypeDto,0);
//        FindLocNoAttributeVo findLocNoAttributeVo = new FindLocNoAttributeVo();
//        StartupDto dto = commonService.getLocNo(10, devpNo, findLocNoAttributeVo, locTypeDto);
        StartupDto dto = commonService.getLocNoBySdyhfz(devpNo,10);
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
@@ -175,14 +358,15 @@
        wrkMast.setIoType(10); // 入出库状态:10.空板入库
        wrkMast.setIoPri(13D); // 优先级
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo());
        wrkMast.setStaNo(dto.getStaNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo() + "");
        wrkMast.setStaNo(dto.getStaNo() + "");
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setFullPlt("N"); // 满板
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("Y"); // 空板
        wrkMast.setLinkMis("Y");
        wrkMast.setBarcode(barcode);
        wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
        // 操作人员数据
        wrkMast.setAppeTime(new Date());
@@ -194,19 +378,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;
    }