自动化立体仓库 - WMS系统
zyx
2023-10-18 080fdceed464c56f43633e85daeaf929d40496af
src/main/java/com/zy/asrs/service/impl/AgvWorkServiceImpl.java
@@ -2,773 +2,312 @@
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.SnowflakeIdWorker;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.EmptyPlateOutParam;
import com.zy.asrs.entity.param.FullStoreParam;
import com.zy.asrs.entity.param.LocDetlAdjustParam;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.*;
import com.zy.common.model.enums.IoWorkType;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.properties.SlaveProperties;
import com.zy.common.service.CommonService;
import com.zy.common.model.LocDto;
import com.zy.common.model.OrderDto;
import com.zy.common.model.StartupDto;
import com.zy.common.model.TaskDto;
import com.zy.common.service.AgvCommonService;
import com.zy.common.web.BaseController;
import com.zy.common.web.WcsController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/**
 * Created by vincent on 2020/6/11
 */
@Slf4j
@Service
@Transactional
public class AgvWorkServiceImpl implements AgvWorkService {
    // 工作号生成规则默认类型
    private static final int DEFAULT_WORK_NO_TYPE = 0;
    // 库位排号分配默认类别
    private static final int DEFAULT_ROW_NO_TYPE = 1;
    @Autowired
    private AgvWaitPakinService agvWaitPakinService;
    @Autowired
    private AgvBasDevpService agvBasDevpService;
    @Autowired
    private AgvLocMastService agvLocMastService;
    @Autowired
    private AgvLocDetlService agvLocDetlService;
    @Autowired
    private AgvCommonService agvCommonService;
    @Autowired
    private AgvWrkMastService agvWrkMastService;
    @Autowired
    private AgvWrkDetlService agvWrkDetlService;
    @Autowired
    private MatService matService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private StaDescService staDescService;
    @Autowired
    private LocDetlService locDetlService;
    @Autowired
    private AdjDetlService adjDetlService;
    @Autowired
    private WrkMastLogService wrkMastLogService;
    @Autowired
    private WrkDetlLogService wrkDetlLogService;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetlService orderDetlService;
    @Autowired
    private WcsController wcsController;
    private AdjDetlService adjDetlService;
    @Autowired
    private RowLastnoService rowLastnoService;
    private AgvWrkMastLogService agvWrkMastLogService;
    @Autowired
    private SlaveProperties slaveProperties;
    private AgvWrkDetlLogService agvWrkDetlLogService;
    @Override
    /*
    入库
     */
    @Transactional
    public String startupFullPutStore(FullStoreParam param, Long userId) {
        // 参数非空判断
        if (Cools.isEmpty(param.getDevpNo(), param.getList())) {
            throw new CoolException(BaseRes.PARAM);
        }
    public StartupDto createWaitPainWrkMastStart(List<AgvBasDevp> agvBasDevpList, Long userId) {
        Date now = new Date();
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(param.getDevpNo(), true);
        // 检索库位
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        List<String> matnrs = param.getList().stream().map(FullStoreParam.MatCodeStore::getMatnr).distinct().collect(Collectors.toList());
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 1, param.getDevpNo(), matnrs, locTypeDto, 0);
        // 生成工作号
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(new Date());
        wrkMast.setWrkSts(1L); // 工作状态:生成入库ID
        wrkMast.setIoType(1); // 入出库状态:1.入库
        Double ioPri = wrkMastService.getIoPri(1, dto.getLocNo());
        wrkMast.setIoPri(ioPri); // 优先级:13
        wrkMast.setOutMost(locMastService.isOutMost(dto.getLocNo(), true)?1:0);;
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(dto.getSourceStaNo());
        wrkMast.setStaNo(dto.getStaNo());
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setBarcode(param.getBarcode()); // 托盘码
        wrkMast.setFullPlt("Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("N"); // 空板
        wrkMast.setLinkMis("N");
        wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
        wrkMast.setAppeUser(userId);
        wrkMast.setAppeTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(now);
        if (!wrkMastService.insert(wrkMast)) {
            throw new CoolException("保存工作档失败");
        }
        // 生成工作档明细
        List<DetlDto> detlDtos = new ArrayList<>();
        param.getList().forEach(elem -> {
            DetlDto detlDto = new DetlDto(elem.getMatnr(), elem.getBatch(), elem.getAnfme());
            if (DetlDto.has(detlDtos, detlDto)) {
                DetlDto detlDto1 = DetlDto.find(detlDtos, detlDto.getMatnr(), detlDto.getBatch());
                assert detlDto1 != null;
                detlDto1.setAnfme(detlDto1.getAnfme() + detlDto.getAnfme());
            } else {
                detlDtos.add(detlDto);
        agvBasDevpList.forEach(agvBasDevp -> {
            if(Cools.isEmpty(agvBasDevp.getBarcode())){
                throw new CoolException("选中的站点中含有未绑定托盘的站点,请重新选择");
            }
            if(!"F".equals(agvBasDevp.getLocSts())){
                throw new CoolException("选中的站点中含有货位状态不为F.在库的站点,请重新选择");
            }
            List<AgvWaitPakin> agvWaitPakinList = agvWaitPakinService.selectList(new EntityWrapper<AgvWaitPakin>().eq("supp_code", agvBasDevp.getBarcode()));
            //检索库位,选择合适的库位
            AgvLocMast agvLocMast = agvCommonService.getLocNo(agvWaitPakinList, agvBasDevp.getFloor());
            //生成工作档
            //AgvWrkMast wrkMast = createWrkMast(agvBasDevp, agvLocMast, now, userId);
            AgvWrkMast wrkMast = createWrkMast(1,201L,agvBasDevp.getDevNo(),agvLocMast.getLocNo(),agvBasDevp.getBarcode(),now,userId);
            //生成工作档明细
            //createWrkDetlReWrite(agvWaitPakinList,wrkMast,userId);
            agvWaitPakinList.forEach(wp -> {
                createWrkDetlReWrite(wp.getMatnr(),wrkMast.getWrkNo(),wp.getOrderNo(),wp.getBatch(),wp.getAnfme(),wp.getSuppCode(),now,userId,wp.getThreeCode(),wp.getDeadTime());
            });
            //更新源站点信息
            updateAgvBasDevp(agvBasDevp,"R");
            //更新目标库位状态
            updateAgvLocMast(agvLocMast,"S");
        });
        wrkDetlService.createWorkDetail(workNo, detlDtos, param.getBarcode(), userId);
        // 更新源站点信息
        sourceStaNo.setWrkNo(workNo);
        sourceStaNo.setModiUser(userId);
        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.setModiUser(userId);
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)){
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
        }
        return dto.getLocNo();
        //TODO
        return null;
    }
    @Override
    /*
    订单出库
     */
    @Transactional
    public void startupFullTakeStore(StockOutParam param, Long userId) {
        ArrayList<String> locNos = new ArrayList<>();
        for (StockOutParam.LocDetl locDetl:param.getLocDetls()){
            if (!locNos.contains(locDetl.getLocNo())){
                locNos.add(locDetl.getLocNo());
            }
        }
        //检测是否为浅库位
        boolean sign=false;
        String th = "";
        for (String locNo:locNos){
            if (sign){
                break;
            }
            //检测出库的货物中是否有状态为禁止的货物。
            for (LocDetl locDetl : locDetlService.selectByLocNo(locNo)) {
                if (locDetl.getStockFreeze() == 0) {
                    th="库位号:"+locNo+" 有禁止出库的货物!";
                    throw new CoolException("出库失败;"+th);
                }
                Mat mat = matService.selectByMatnr(locDetl.getMatnr());
                if (mat == null) {
                    continue;
                }
                if (mat.getStatus() == 0) {
                    th="库位号:"+locNo+" 有禁止出库的货物!";
                    throw new CoolException("出库失败;"+th);
                }
            }
            List<String> groupInsideLoc = Utils.getGroupInsideLoc(locNo);
            if (!Cools.isEmpty(groupInsideLoc)) {
                for (String insideLoc : groupInsideLoc) {
                    if (locNos.contains(insideLoc)){
                        continue;
                    }
                    LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", insideLoc));
                    if (locMast != null) {
                        if (!locMast.getLocSts().equals("O") && !locMast.getLocSts().equals("R")){
                            sign=true;
                            th="库位号:"+locNo+" 浅库位有非空库位!";
                            break;
                        }
                    }
                }
            }
        }
        if (sign){
            throw new CoolException("出库失败;"+th);
        }
        // 目标站点状态检测
        BasDevp staNo = basDevpService.checkSiteStatus(param.getOutSite());
        // 获取库位明细
        List<LocDetlDto> locDetlDtos = new ArrayList<>();
        for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) {
            if (!Cools.isEmpty(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getCount())) {
                LocDetl one = locDetlService.selectItem(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getBatch());
                if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount()));
            }
        }
        if (!locDetlDtos.isEmpty()) {
            // 启动出库开始 101.出库
            stockOut(staNo, locDetlDtos, null, userId);
        } else {
            throw new CoolException("库存不存在");
        }
    }
    /**
     * 通过库位号获取 排
     */
    public static int getRow(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(0, 2));
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 通过库位号获取 列
     */
    public static int getBay(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(2, 5));
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 通过库位号获取 层
     */
    public static int getLev(String locNo) {
        if (!Cools.isEmpty(locNo)) {
            return Integer.parseInt(locNo.substring(5, 7));
        }
        throw new RuntimeException("库位解析异常");
    }
    @Override
    @Transactional
    public void stockOut(BasDevp staNo, List<LocDetlDto> locDetlDtos, IoWorkType ioWorkType, Long userId) {
    public void stockOutWrkMast(List<TaskDto> agvTaskDtos, Long userId) {
        Date now = new Date();
        // 合并同类项
        Set<String> locNos = new HashSet<>();
        List<OutLocDto> dtos = new ArrayList<>();
        for (LocDetlDto locDetlDto : locDetlDtos) {
            String locNo = locDetlDto.getLocDetl().getLocNo();
            if (locNos.contains(locNo)) {
                for (OutLocDto dto : dtos) {
                    if (dto.getLocNo().equals(locNo)) {
                        dto.getLocDetlDtos().add(locDetlDto);
                        break;
                    }
                }
            } else {
                locNos.add(locNo);
                dtos.add(new OutLocDto(locNo, locDetlDto));
            }
        }
        Integer ioType = null;
        List<String> excludeLocNos = dtos.stream().map(OutLocDto::getLocNo).distinct().collect(Collectors.toList());
        // 生成工作档
        for (OutLocDto dto : dtos) {
            // 如果为深库位,且对应浅库位为X.禁用,则略过此库位
            if (Utils.isDeepLoc(slaveProperties, dto.getLocNo())) {
                String shallowLoc = Utils.getShallowLoc(slaveProperties, dto.getLocNo());
                if (locMastService.selectById(shallowLoc).getLocSts().equals("X")) {
                    continue;
                }
            }
            // 判断入出库类型:101.全板出库 or 103.拣料出库
            if (ioWorkType == null) {
                ioType = dto.isAll() ? 101 : 103;
            } else if (ioWorkType.equals(IoWorkType.CHECK_OUT)) {
                ioType = 107;
            }
            assert ioType != null;
            // 获取库位
            LocMast locMast = locMastService.selectById(dto.getLocNo());
            // 获取路径
            Boolean outMost = locMastService.isOutMost(dto.getLocNo(), false);
            Integer outCrnNo = locMastService.getOutCrnNo(locMast);
            StaDesc staDesc = staDescService.queryCrnStn(ioType, outCrnNo, staNo.getDevNo());
            // 生成工作号
            int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
            // 生成工作档
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(now);
            wrkMast.setWrkSts(21L); // 工作状态:21.生成出库任务
            wrkMast.setIoType(ioType); // 入出库状态
            Double ioPri = wrkMastService.getIoPri(ioType, dto.getLocNo());
            wrkMast.setIoPri(ioPri); // 优先级:13
            wrkMast.setOutMost(outMost?1:0);;
            wrkMast.setCrnNo(outMost?outCrnNo:locMast.getCrnNo());
            wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站
            wrkMast.setStaNo(staDesc.getStnNo()); // 目标站
            wrkMast.setSourceLocNo(dto.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("保存工作档失败,出库库位号:"+dto.getLocNo());
            }
            // 生成工作档明细
            for (LocDetlDto detlDto : dto.getLocDetlDtos()) {
                if (detlDto.getCount()==null || detlDto.getCount() <= 0.0D) {continue;}
                WrkDetl wrkDetl = new WrkDetl();
                wrkDetl.sync(detlDto.getLocDetl());
                wrkDetl.setOrderNo(""); // 手动出库不需要带出库存中的单据编号
                wrkDetl.setWrkNo(workNo);
                wrkDetl.setIoTime(now);
                Double anfme = ioType==101?detlDto.getLocDetl().getAnfme():detlDto.getCount();
                wrkDetl.setAnfme(anfme); // 数量
                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(dto.getLocNo());
            if (locMast.getLocSts().equals("F")) {
                locMast.setLocSts(ioType==101?"R":"P");
                locMast.setModiUser(userId);
                locMast.setModiTime(now);
                if (!locMastService.updateById(locMast)) {
                    throw new CoolException("预约库位状态失败,库位号:"+dto.getLocNo());
                }
            } else {
                throw new CoolException(dto.getLocNo() + "库位不是在库状态");
            }
            locMastService.breakUp(dto.getLocNo(), excludeLocNos);
        }
        agvTaskDtos.forEach(taskDto -> {
            AgvLocMast agvLocMast = agvLocMastService.selectById(taskDto.getLocNo());
            AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", taskDto.getLocNo()));
            //工作档所需参数
            double anfme = taskDto.getLocDtos().get(0).getAnfme();
            long wrkSts = 21L;
            String sourceLocNo = taskDto.getLocNo();
            String targetLocNo = taskDto.getAgvStaNo();
            String barcode = agvLocDetl.getSuppCode();
            //明细档所需参数
            String mantr = taskDto.getLocDtos().get(0).getMatnr();
            String orderNo = taskDto.getLocDtos().get(0).getOrderNo();
            String batch = taskDto.getLocDtos().get(0).getBatch();
            String csocode = agvLocDetl.getThreeCode();
            String isoseq = agvLocDetl.getDeadTime();
            //判断是否全板出库
            int ioType = isPakOut(sourceLocNo,anfme) ?  101 : 103;
            //生成工作档
            AgvWrkMast wrkMast = createWrkMast(ioType,wrkSts,sourceLocNo,targetLocNo,barcode,now,userId);
            //生成工作档明细
            createWrkDetlReWrite(mantr,wrkMast.getWrkNo(),orderNo,batch,anfme,barcode,now,userId,csocode,isoseq);
            //修改订单信息
            modifyOrderDetl(taskDto.getLocDtos().get(0), userId);
            //更新源站点信息
            String locSts = ioType == 101 ? "R" : "P";
            updateAgvLocMast(agvLocMastService.selectById(sourceLocNo),locSts);
            //更新目标站点状态
            //locSts = ioType == 101 ? "S" : "Q";
            updateAgvBasDevp(agvBasDevpService.selectById(targetLocNo),"S");
        });
    }
    @Override
    //拣料入库
    @Transactional
    public void stockOut(BasDevp staNo, TaskDto taskDto, Long userId) {
    public void pickIn(List<AgvWrkMast> agvWrkMastList){
        Date now = new Date();
        List<LocDto> locDtos = taskDto.getLocDtos();
        for (LocDto locDto : locDtos) {
            if (!taskDto.getLocNo().equals(locDto.getLocNo()) && !taskDto.getStaNo().equals(locDto.getStaNo())) {
                throw new CoolException("订单出库异常,请联系管理员");
        agvWrkMastList.forEach(agvWrkMast -> {
            //修改工作党
            agvWrkMast.setWrkSts(201L);
            //根据出库类型 设置入库类型 53拣料入库 57盘点入库
            int ioType = agvWrkMast.getIoType() == 103 ? 53 : 57;
            agvWrkMast.setIoType(ioType);
            String locNo = agvWrkMast.getLocNo();
            agvWrkMast.setLocNo(agvWrkMast.getSourceLocNo());
            agvWrkMast.setSourceLocNo(locNo);
            agvWrkMast.setIoTime(now);
            agvWrkMastService.updateById(agvWrkMast);
            AgvWrkDetl agvWrkDetl = agvWrkDetlService.selectOne(new EntityWrapper<AgvWrkDetl>().eq("wrk_no", agvWrkMast.getWrkNo()));
            AgvLocMast agvLocMast = agvLocMastService.selectById(agvWrkMast.getLocNo());
            AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no",agvLocMast.getLocNo()));
            AgvBasDevp agvBasDevp = agvBasDevpService.selectById(agvWrkMast.getSourceLocNo());
            //拣料入库
            if(ioType == 53){
                //修改工作党明细
                agvWrkDetl.setAnfme(agvLocDetl.getAnfme() - agvWrkDetl.getAnfme());
                agvWrkDetlService.update(agvWrkDetl,new EntityWrapper<AgvWrkDetl>().eq("wrk_no",agvWrkDetl.getWrkNo()));
                //修改库存信息
                agvLocDetl.setAnfme(agvWrkDetl.getAnfme());
                agvLocDetlService.update(agvLocDetl,new EntityWrapper<AgvLocDetl>().eq("loc_no",agvLocDetl.getLocNo()));
            }
        }
        // 获取库位
        LocMast locMast = locMastService.selectById(taskDto.getLocNo());
        // 获取路径
        int ioType = taskDto.isAll() ? 101 : 103;
        Boolean outMost = locMastService.isOutMost(taskDto.getLocNo(), false);
        Integer outCrnNo = locMastService.getOutCrnNo(locMast);
        StaDesc staDesc = staDescService.queryCrnStnAuto(ioType, outCrnNo, staNo.getDevNo());
        // 生成工作号
        int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(now);
        wrkMast.setWrkSts(21L); // 工作状态:21.生成出库任务
        wrkMast.setIoType(ioType); // 入出库状态
        Double ioPri = wrkMastService.getIoPri(ioType, taskDto.getLocNo());
        wrkMast.setIoPri(ioPri); // 优先级:13
        wrkMast.setOutMost(outMost?1:0);;
        wrkMast.setCrnNo(outMost?outCrnNo:locMast.getCrnNo());
        wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站
        wrkMast.setStaNo(staDesc.getStnNo()); // 目标站
        wrkMast.setSourceLocNo(taskDto.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("保存工作档失败,出库库位号:"+taskDto.getLocNo());
        }
        // 生成工作档明细
        for (LocDto locDto : taskDto.getLocDtos()) {
            if (locDto.getAnfme()==null || locDto.getAnfme() <= 0.0D) { continue; }
            LocDetl locDetl = locDetlService.selectItem(locDto.getLocNo(), locDto.getMatnr(), locDto.getBatch());
            if (locDetl == null || locDetl.getAnfme() < locDto.getAnfme()) {
                throw new CoolException(locDto.getLocNo() + "库位中" + locDto.getMatnr() + "商品库存不足!");
            }
            Mat mat = matService.selectByMatnr(locDto.getMatnr());
            assert mat != null;
            WrkDetl wrkDetl = new WrkDetl();
            wrkDetl.sync(mat);
            wrkDetl.setZpallet(wrkMast.getBarcode());
            wrkDetl.setIoTime(now);
            wrkDetl.setWrkNo(workNo);
            wrkDetl.setBatch(locDto.getBatch());
            wrkDetl.setOrderNo(locDto.getOrderNo());
            wrkDetl.setAnfme(locDto.getAnfme()); // 数量
            wrkDetl.setAppeTime(now);
            wrkDetl.setAppeUser(userId);
            wrkDetl.setModiTime(now);
            wrkDetl.setModiUser(userId);
            if (!wrkDetlService.insert(wrkDetl)) {
                throw new CoolException("保存工作档明细失败");
            }
            // 修改订单明细
            if (!BaseController.isJSON(locDto.getOrderNo())) {
                OrderDetl orderDetl = orderDetlService.selectItem(locDto.getOrderNo(), locDto.getMatnr(), locDto.getBatch());
                if (orderDetl == null) {
                    orderDetl = orderDetlService.selectItem(locDto.getOrderNo(), locDto.getMatnr(), null);
                }
                if (!orderDetlService.increase(orderDetl.getOrderId(), orderDetl.getMatnr(), orderDetl.getBatch(), locDto.getAnfme())) {
                    throw new CoolException("修改订单明细数量失败");
                }
                orderService.updateSettle(orderDetl.getOrderId(), 2L, userId);
            } else {
                // 订单合并出库
                List<OrderDto> orderDtoList = JSON.parseArray(locDto.getOrderNo(), OrderDto.class);
                for (OrderDto orderDto : orderDtoList) {
                    OrderDetl orderDetl = orderDetlService.selectItem(orderDto.getOrderNo(), locDto.getMatnr(), locDto.getBatch());
                    if (orderDetl == null) {
                        orderDetl = orderDetlService.selectItem(orderDto.getOrderNo(), locDto.getMatnr(), null);
                    }
                    if (!orderDetlService.increase(orderDetl.getOrderId(), orderDetl.getMatnr(), orderDetl.getBatch(), orderDto.getAnfme())) {
                        throw new CoolException("修改订单明细数量失败");
                    }
                    orderService.updateSettle(orderDetl.getOrderId(), 2L, userId);
                }
            }
        }
        // 修改库位状态:   F.在库 ====>>> R.出库预约/P.拣料/盘点/并板出库中
        locMast = locMastService.selectById(taskDto.getLocNo());
        if (locMast.getLocSts().equals("F")) {
            locMast.setLocSts(ioType==101?"R":"P");
            locMast.setModiUser(userId);
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("预约库位状态失败,库位号:"+taskDto.getLocNo());
            }
        } else {
            throw new CoolException(taskDto.getLocNo() + "库位不是在库状态");
        }
            //修改库位信息
            updateAgvLocMast(agvLocMast,"Q");
            //修改站点信息
            updateAgvBasDevp(agvBasDevp,"R");
        });
    }
    @Override
    @Transactional
    public String emptyPlateIn(Integer devpNo, Long userId) {
        // 源站点状态检测
        BasDevp sourceStaNo = basDevpService.checkSiteStatus(devpNo, true);
        // 检索库位
        LocTypeDto locTypeDto = new LocTypeDto(sourceStaNo);
        StartupDto dto = commonService.getLocNo(DEFAULT_ROW_NO_TYPE, 10, devpNo, null, locTypeDto, 0);
        int workNo = dto.getWorkNo();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(new Date());
        wrkMast.setWrkSts(1L); // 工作状态:生成入库ID
        wrkMast.setIoType(10); // 入出库状态:10.空板入库
        Double ioPri = wrkMastService.getIoPri(10, dto.getLocNo());
        wrkMast.setIoPri(ioPri); // 优先级:10
        wrkMast.setOutMost(locMastService.isOutMost(dto.getLocNo(), true)?1:0);;
        wrkMast.setCrnNo(dto.getCrnNo());
        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("N");
        wrkMast.setCtnType(sourceStaNo.getCtnType()); // 容器类型
        // 操作人员数据
        wrkMast.setAppeUser(userId);
        wrkMast.setAppeTime(new Date());
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(new Date());
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            throw new CoolException("保存工作档失败");
        }
        // 更新源站点信息
        sourceStaNo.setWrkNo(workNo);
        sourceStaNo.setModiUser(userId);
        sourceStaNo.setModiTime(new Date());
        if (!basDevpService.updateById(sourceStaNo)){
            throw new CoolException("更新源站失败");
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")){
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiUser(userId);
            locMast.setModiTime(new Date());
            if (!locMastService.updateById(locMast)){
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
        }
        return dto.getLocNo();
    }
    @Override
    @Transactional
    public void emptyPlateOut(EmptyPlateOutParam param, Long userId) {
        List<String> locNos = param.getLocNos();
        //检测是否为浅库位
        boolean sign=false;
        String th = "";
        for (String locNo:locNos){
            if (sign){
                break;
            }
            List<String> groupInsideLoc = Utils.getGroupInsideLoc(locNo);
            if (!Cools.isEmpty(groupInsideLoc)) {
                for (String insideLoc : groupInsideLoc) {
                    if (locNos.contains(insideLoc)){
                        continue;
                    }
                    LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>().eq("loc_no", insideLoc));
                    if (locMast != null) {
                        if (!locMast.getLocSts().equals("O") && !locMast.getLocSts().equals("R")){
                            sign=true;
                            th="库位号:"+locNo+" 浅库位有非空库位!";
                            break;
                        }
                    }
                }
            }
        }
        if (sign){
            throw new CoolException("出库失败;"+th);
        }
        if (Cools.isEmpty(param.getOutSite())) {
            throw new CoolException("站点不存在");
        }
        for (String locNo : param.getLocNos()) {
            // 如果为深库位,且对应浅库位为X.禁用,则略过此库位
            if (Utils.isDeepLoc(slaveProperties, locNo)) {
                String shallowLoc = Utils.getShallowLoc(slaveProperties, locNo);
                if (locMastService.selectById(shallowLoc).getLocSts().equals("X")) {
                    continue;
                }
            }
            // 获取工作号
            int workNo = commonService.getWorkNo(WorkNoType.PAKOUT.type);
            // 获取库位
            LocMast locMast = locMastService.selectById(locNo);
            if (Cools.isEmpty(locMast)) {
                throw new CoolException(locNo+"库位不存在");
            }
            Boolean outMost = locMastService.isOutMost(locNo, false);
            Integer outCrnNo = locMastService.getOutCrnNo(locMast);
            // 获取源站
            Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                    .eq("type_no", 110)
                    .eq("stn_no", param.getOutSite())
                    .eq("crn_no", outCrnNo);
            StaDesc staDesc = staDescService.selectOne(wrapper);
            if (Cools.isEmpty(staDesc)) {
                throw new CoolException("非法路径!");
            }
            Integer sourceStaNo = staDesc.getCrnStn();
            if (Cools.isEmpty(sourceStaNo)) {
                throw new CoolException("检索源站失败");
            }
            // 保存工作档
            WrkMast wrkMast = new WrkMast();
            wrkMast.setWrkNo(workNo);
            wrkMast.setIoTime(new Date());
            wrkMast.setWrkSts(21L); // 工作状态:21.生成出库任务
            wrkMast.setIoType(110); // 入出库状态: 110.空板出库
            Double ioPri = wrkMastService.getIoPri(110, locNo);
            wrkMast.setIoPri(ioPri);
            wrkMast.setSourceStaNo(sourceStaNo); // 源站
            wrkMast.setStaNo(param.getOutSite()); // 目标站
            wrkMast.setOutMost(outMost?1:0);;
            wrkMast.setCrnNo(outMost?outCrnNo:locMast.getCrnNo());
            wrkMast.setSourceLocNo(locNo); // 源库位
            wrkMast.setFullPlt("N"); // 满板:Y
            wrkMast.setPicking("N"); // 拣料
            wrkMast.setExitMk("N"); // 退出
            wrkMast.setEmptyMk("Y"); // 空板
            wrkMast.setLinkMis("N");
            wrkMast.setAppeUser(userId);
            wrkMast.setAppeTime(new Date());
            wrkMast.setModiUser(userId);
            wrkMast.setModiTime(new Date());
            boolean res = wrkMastService.insert(wrkMast);
            if (!res) {
                throw new CoolException("保存工作档失败");
            }
            // 更新库位状态 D.空板 -> R.出库预约
            if (locMast.getLocSts().equals("D")){
                locMast.setLocSts("R");
                locMast.setModiUser(userId);
                locMast.setModiTime(new Date());
                if (!locMastService.updateById(locMast)) {
                    throw new CoolException("更新库位状态失败");
                }
            }
        }
    }
    @Override
    /*
    盘点出库
     */
    @Transactional
    public void locCheckOut(StockOutParam param, Long userId) {
        // 目标站点状态检测
        BasDevp staNo = basDevpService.checkSiteStatus(param.getOutSite());
        // 获取库位明细
        List<LocDetlDto> locDetlDtos = new ArrayList<>();
        for (StockOutParam.LocDetl paramLocDetl : param.getLocDetls()) {
            if (!Cools.isEmpty(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getCount())) {
                LocDetl one = locDetlService.selectItem(paramLocDetl.getLocNo(), paramLocDetl.getMatnr(), paramLocDetl.getBatch());
                if (null != one) locDetlDtos.add(new LocDetlDto(one, paramLocDetl.getCount()));
            }
        String station = param.getStation();
        List<AgvBasDevp> agvBasDevpList = agvBasDevpService.selectList(new EntityWrapper<AgvBasDevp>()
                .eq("station_code", station)
                .eq("loc_sts","O"));
        if(param.getLocDetls().size() > agvBasDevpList.size()){
            throw new CoolException("当前站点可用缓存货架数量为" + agvBasDevpList.size() + ",少于需要盘点出库库位数量,请重新选择盘点库位");
        }
        if (!locDetlDtos.isEmpty()) {
            // 启动出库开始 107.盘点出库
            stockOut(staNo, locDetlDtos, IoWorkType.CHECK_OUT, userId);
        } else {
            throw new CoolException("库位物料不存在");
        }
        param.getLocDetls().forEach(locDetl -> {
            AgvLocMast agvLocMast = agvLocMastService.selectById(locDetl.getLocNo());
            AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", locDetl.getLocNo()));
            AgvBasDevp agvBasDevp = agvBasDevpService.selectOne(new EntityWrapper<AgvBasDevp>()
                    .eq("station_code", station)
                    .eq("loc_sts","O"));
            Date now = new Date();
            //生成工作党
            AgvWrkMast wrkMast = createWrkMast(107, 21L, locDetl.getLocNo(), agvBasDevp.getDevNo(), agvLocDetl.getSuppCode(), now, userId);
            //生成工作明细档
            createWrkDetlReWrite(locDetl.getMatnr(),wrkMast.getWrkNo(),null,locDetl.getBatch(),locDetl.getCount(),wrkMast.getBarcode(),now,userId,agvLocDetl.getThreeCode(),agvLocDetl.getDeadTime());
            //修改库位信息
            updateAgvLocMast(agvLocMast,"P");
            //修改站点信息
            updateAgvBasDevp(agvBasDevp,"S");
        });
    }
    @Override
    /*
    库位移转
     */
    @Transactional
    public void locMove(String sourceLocNo, String locNo, Long userId) {
        LocMast sourceLoc = locMastService.selectById(sourceLocNo);
        List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", sourceLocNo));
        if (Cools.isEmpty(sourceLoc)){
            throw new CoolException("未找到库位");
    public void locMove(String sourceLocNo, String targetLocNo, Long userId) {
        AgvLocMast sourceLocMast = agvLocMastService.selectById(sourceLocNo);
        AgvLocMast targetLocMast = agvLocMastService.selectById(targetLocNo);
        AgvLocDetl sourceLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", sourceLocMast.getLocNo()));
        if(!sourceLocMast.getLocSts().equals("F")){
            throw new CoolException(sourceLocMast.getLocNo() + "源库位出库失败,状态:"+sourceLocMast.getLocSts$());
        }
        LocMast loc = locMastService.selectById(locNo);
        if (Cools.isEmpty(loc)){
            throw new CoolException("未找到库位");
        if(!targetLocMast.getLocSts().equals("O")){
            throw new CoolException("移转失败,目标库位状态:"+targetLocMast.getLocSts$());
        }
        if (!sourceLoc.getCrnNo().equals(loc.getCrnNo())) {
//            throw new CoolException("移转库位属于不同堆垛机");   todo:luxiaotao
        }
        Date now = new Date();
        // 获取工作号
        int workNo = commonService.getWorkNo(WorkNoType.PICK.type);
        // 保存工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(now);
        wrkMast.setWrkSts(21L); // 工作状态:21.生成出库任务
        wrkMast.setIoType(11); // 入出库状态: 11.库格移载
        wrkMast.setIoPri(10D);
        wrkMast.setOutMost(locMastService.isOutMost(locNo, false)?1:0);;
        wrkMast.setCrnNo(sourceLoc.getCrnNo());
        wrkMast.setSourceLocNo(sourceLocNo); // 源库位
        wrkMast.setLocNo(locNo); // 目标库位
        wrkMast.setFullPlt(Cools.isEmpty(locDetls)?"N":"Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk(sourceLoc.getLocSts().equals("D")?"Y":"N"); // 空板
        wrkMast.setBarcode(sourceLoc.getBarcode()); // 托盘码
        wrkMast.setLinkMis("N");
        wrkMast.setAppeUser(userId);
        wrkMast.setAppeTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(now);
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            throw new CoolException("保存工作档失败");
        }
        // 工作档明细保存
        for (LocDetl locDetl : locDetls) {
            WrkDetl wrkDetl = new WrkDetl();
            wrkDetl.sync(locDetl);
            wrkDetl.setWrkNo(workNo);
            wrkDetl.setIoTime(now);
            wrkDetl.setAnfme(locDetl.getAnfme());
            wrkDetl.setAppeTime(now);
            wrkDetl.setAppeUser(userId);
            wrkDetl.setModiTime(now);
            wrkDetl.setModiUser(userId);
            if (!wrkDetlService.insert(wrkDetl)) {
                throw new CoolException("保存工作档明细失败");
            }
        }
        // 修改源库位状态
        if (sourceLoc.getLocSts().equals("D") || sourceLoc.getLocSts().equals("F")) {
            sourceLoc.setLocSts("R"); // R.出库预约
            sourceLoc.setModiUser(userId);
            sourceLoc.setModiTime(now);
            if (!locMastService.updateById(sourceLoc)){
                throw new CoolException("更新源库位状态失败");
            }
        } else {
            throw new CoolException(sourceLoc.getLocNo() + "源库位出库失败,状态:"+sourceLoc.getLocSts$());
        }
        // 修改目标库位状态
        if (loc.getLocSts().equals("O")) {
            loc.setLocSts("S"); // S.入库预约
            loc.setModiTime(now);
            loc.setModiUser(userId);
            if (!locMastService.updateById(loc)) {
                throw new CoolException("更新目标库位状态失败");
            }
        } else {
            throw new CoolException("移转失败,目标库位状态:"+loc.getLocSts$());
        }
        //生成移库工作档
        AgvWrkMast wrkMast = createWrkMast(11, 21L, sourceLocNo, targetLocNo, sourceLocDetl.getSuppCode(), now, userId);
        //生成工作党明细
        createWrkDetlReWrite(sourceLocDetl.getMatnr(),wrkMast.getWrkNo(),null,sourceLocDetl.getBatch(),sourceLocDetl.getAnfme(),sourceLocDetl.getZpallet(),now,userId,sourceLocDetl.getThreeCode(),sourceLocDetl.getDeadTime());
        //修改目标库位状态
        updateAgvLocMast(targetLocMast,"S");
        //修改原库位状态
        updateAgvLocMast(sourceLocMast,"R");
    }
    @Override
    /*
    空板入库
     */
    @Transactional
    public void completeWrkMast(String workNo, Long userId) {
        WrkMast wrkMast = wrkMastService.selectById(workNo);
        if (Cools.isEmpty(wrkMast)){
            throw new CoolException(workNo+"工作档不存在");
        }
        if (wrkMast.getWrkSts() == 9 || wrkMast.getWrkSts() == 17) {
            throw new CoolException("当前工作档已完成");
        }
        // 入库 + 库位转移
        if (wrkMast.getWrkSts() < 9 || (wrkMast.getWrkSts() > 10 && wrkMast.getIoType()==11)) {
            wrkMast.setWrkSts(9L);
            // 出库
        } else if (wrkMast.getWrkSts() > 10) {
            wrkMast.setWrkSts(17L);
        }
    public String emptyPlateIn(String sourceStaion, Long userId) {
        Date now = new Date();
        wrkMast.setCrnStrTime(DateUtils.calculate(now, 1L, TimeUnit.SECONDS, true));
        wrkMast.setCrnEndTime(now);
        wrkMast.setModiTime(now);
        wrkMast.setModiUser(userId);
        // 完成操作人员记录
        wrkMast.setManuType("手动完成");
        if (!wrkMastService.updateById(wrkMast)) {
            throw new CoolException("修改工作档失败");
        // 源站点状态检测
        AgvBasDevp agvBasDevp = agvBasDevpService.selectById(sourceStaion);
        if(!agvBasDevp.getLocSts().equals("O")){
            throw new CoolException("当前工作位状态为" + agvBasDevp.getLocSts()+",无法进行空板入库");
        }
        // 检索库位
        AgvLocMast locMast = agvCommonService.getLocNo(null, agvBasDevp.getFloor());
        // 生成工作档 10.空板入库
        createWrkMast(10,201L,agvBasDevp.getDevNo(),locMast.getLocNo(),null,now,userId);
        //更新源站点状态
        updateAgvBasDevp(agvBasDevp,"R");
        //更新目标库位状态
        updateAgvLocMast(locMast,"S");
        return locMast.getLocNo();
    }
    @Override
    /*
    空板出库
     */
    @Transactional
    public void emptyPlateOut(EmptyPlateOutParam param, Long userId) {
        Date now = new Date();
        //判断所选工作站空余工作位数量是否满足出库数量
        List<AgvBasDevp> agvBasDevpList = agvBasDevpService.selectList(new EntityWrapper<AgvBasDevp>()
                .eq("station_code", param.getStationCode())
                .eq("loc_sts","O"));
        if(agvBasDevpList.size() < param.getLocNos().size()){
            throw new CoolException("当前工作站可出库工作位数量为"+ agvBasDevpList.size() + ",小于要出库的库位数量,请重新选择出库库位");
        }
        param.getLocNos().forEach(locNo -> {
            AgvLocMast agvLocMast = agvLocMastService.selectById(locNo);
            if(!agvLocMast.getLocSts().equals("D")){
                throw new CoolException(agvLocMast.getLocNo() + "库位状态已经不为D.空桶/空栈板,请重新选择库位进行空板出库");
            }
            //检索工作位
            AgvBasDevp agvBasDevp = agvBasDevpService.selectOne(new EntityWrapper<AgvBasDevp>()
                    .eq("station_code", param.getStationCode())
                    .eq("loc_sts", "O"));
            //生成工作档
            createWrkMast(110,21L,locNo,agvBasDevp.getDevNo(),null,now,userId);
            //修改源库位状态
            updateAgvLocMast(agvLocMast,"R");
            //修改目标工作位状态
            updateAgvBasDevp(agvBasDevp,"S");
        });
    }
    @Transactional
    public void adjustLocDetl(LocDetlAdjustParam param, Long userId) {
        param.integrate();
        LocMast locMast = locMastService.selectById(param.getLocNo());
        AgvLocMast locMast = agvLocMastService.selectById(param.getLocNo());
        if (Cools.isEmpty(locMast)) {
            throw new CoolException("库位不存在");
        }
@@ -777,14 +316,14 @@
        }
        Date now = new Date();
        List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", param.getLocNo()));
        List<AgvLocDetl> locDetls = agvLocDetlService.selectList(new EntityWrapper<AgvLocDetl>().eq("loc_no", param.getLocNo()));
        List<LocDetlAdjustParam.LocDetlAdjust> list = param.getList();
        // 修改数量
        Iterator<LocDetl> iterator = locDetls.iterator();
        Iterator<AgvLocDetl> iterator = locDetls.iterator();
        while (iterator.hasNext()) {
            LocDetl locDetl = iterator.next();
            AgvLocDetl locDetl = iterator.next();
            Iterator<LocDetlAdjustParam.LocDetlAdjust> iterator1 = list.iterator();
            while (iterator1.hasNext()) {
@@ -794,7 +333,7 @@
                    if (!locDetl.getAnfme().equals(adjust.getCount())) {
                        // todo 盘点记录
                        // 修改库存
                        if (!locDetlService.updateAnfme(adjust.getCount(), locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getBatch())) {
                        if (!agvLocDetlService.updateAnfme(adjust.getCount(), locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getBatch())) {
                            throw new CoolException(locDetl.getLocNo() + "库位," + locDetl.getMatnr() + "商品," + locDetl.getBatch() + "序列码修改数量失败");
                        }
                        // 保存调整记录
@@ -808,6 +347,12 @@
                        adjDetl.setModiUser(userId);
                        adjDetl.setAppeTime(now);
                        adjDetl.setAppeUser(userId);
                        UUID uuid = UUID.randomUUID();
                        adjDetl.setOrderNo(uuid.toString());
                        adjDetl.setCsocode(locDetl.getThreeCode());
                        adjDetl.setIsoseq(locDetl.getDeadTime());
                        adjDetlService.save(adjDetl, userId);
                    }
                    iterator.remove();
@@ -817,9 +362,9 @@
        }
        // 删除库存
        for (LocDetl locDetl : locDetls) {
        for (AgvLocDetl locDetl : locDetls) {
            // todo 盘点记录
            if (!locDetlService.updateAnfme(-1.0D, locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getBatch())) {
            if (!agvLocDetlService.updateAnfme(-1.0D, locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getBatch())) {
                throw new CoolException("删除" + locDetl.getLocNo() + "库位," + locDetl.getMatnr() + "商品," + locDetl.getBatch() + "序列码库存明细失败");
            }
            // 保存调整记录
@@ -833,6 +378,7 @@
            adjDetl.setModiUser(userId);
            adjDetl.setAppeTime(now);
            adjDetl.setAppeUser(userId);
            adjDetlService.save(adjDetl, userId);
        }
@@ -840,7 +386,7 @@
        for (LocDetlAdjustParam.LocDetlAdjust adjust : list) {
            if (adjust.getCount() == 0.0D) { continue; }
            Mat mat = matService.selectByMatnr(adjust.getMatnr());
            LocDetl locDetl = new LocDetl();
            AgvLocDetl locDetl = new AgvLocDetl();
            locDetl.sync(mat);
            locDetl.setBatch(adjust.getBatch());
            locDetl.setLocNo(locMast.getLocNo());
@@ -849,7 +395,9 @@
            locDetl.setModiTime(now);
            locDetl.setAppeUser(userId);
            locDetl.setAppeTime(now);
            if (!locDetlService.insert(locDetl)) {
            locDetl.setThreeCode(adjust.getThreeCode());
            locDetl.setDeadTime(adjust.getDeadTime());
            if (!agvLocDetlService.insert(locDetl)) {
                throw new CoolException("添加" + locDetl.getLocNo() + "库位," + locDetl.getMatnr() + "商品," + locDetl.getBatch() + "序列码库存明细失败");
            }
            // 保存调整记录
@@ -863,10 +411,16 @@
            adjDetl.setModiUser(userId);
            adjDetl.setAppeTime(now);
            adjDetl.setAppeUser(userId);
            UUID uuid = UUID.randomUUID();
            adjDetl.setOrderNo(uuid.toString());
            adjDetl.setCsocode(locDetl.getThreeCode());
            adjDetl.setIsoseq(locDetl.getDeadTime());
            adjDetlService.save(adjDetl, userId);
        }
        // 修改库位状态
        int count = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("loc_no", locMast.getLocNo()));
        int count = agvLocDetlService.selectCount(new EntityWrapper<AgvLocDetl>().eq("loc_no", locMast.getLocNo()));
        if (locMast.getLocSts().equals("F")) {
            if (count == 0) {
                locMast.setLocSts("D");
@@ -879,311 +433,302 @@
        }
        locMast.setModiUser(userId);
        locMast.setModiTime(new Date());
        if (!locMastService.updateById(locMast)) {
        if (!agvLocMastService.updateById(locMast)) {
            throw new CoolException("更新库位状态失败");
        }
    }
    @Override
    @Transactional
    public void completeWrkMast(String workNo, Long userId) {
        AgvWrkMast wrkMast = agvWrkMastService.selectById(workNo);
        if (Cools.isEmpty(wrkMast)){
            throw new CoolException(workNo+"工作档不存在");
        }
        if(wrkMast.getWrkSts() > 202){
            //修改AGV工作档的工作状态为205.工作完成
            agvWrkMastService.updateWrkStsByWrkNo(wrkMast.getWrkNo(),205);
            //出库任务 101.出库 || 103.拣料出库 || 107.盘点出库
            if(wrkMast.getIoType() == 101 || wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107){
                //修改出库站点状态
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(wrkMast.getLocNo(),"F",wrkMast.getBarcode());
            }
            //出库任务 110.空板出库
            if(wrkMast.getIoType() == 110){
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(wrkMast.getLocNo(),"F",wrkMast.getBarcode());
            }
        }
    }
    @Transactional
    public void cancelWrkMast(String workNo, Long userId) {
        WrkMast wrkMast = wrkMastService.selectById(workNo);
        AgvWrkMast wrkMast = agvWrkMastService.selectById(workNo);
        if (Cools.isEmpty(wrkMast)){
            throw new CoolException(workNo+"工作档不存在");
        }
        String locNo = ""; // 待修改目标库位
        String locSts = ""; // 待修改目标库位状态
        // 入库取消(修改目标库位)
        if (wrkMast.getWrkSts() < 9) {
            locNo = wrkMast.getLocNo();
            locSts = "O";
            // 库位转移
            if (wrkMast.getIoType() == 11) {
                // 库位转移:源库位
                LocMast locMast = locMastService.selectById(wrkMast.getSourceLocNo());
                if (Cools.isEmpty(locMast)) {
                    throw new CoolException("取消库位转移失败,源库位不存在:"+ wrkMast.getSourceLocNo());
                }
                locMast.setLocSts("F");
                locMast.setModiTime(new Date());
                locMast.setModiUser(userId);
                locMastService.updateById(locMast);
            }
        // 出库取消(修改源库位)
        } else if (wrkMast.getWrkSts() > 10 && wrkMast.getWrkSts() != 19) {
            locNo = wrkMast.getSourceLocNo();
            // 出库 ===>> F.在库
            if (wrkMast.getIoType() > 100 && wrkMast.getIoType() != 110) {
                locSts = "F";
            // 空板出库 ===>> D.空桶/空栈板
            } else if (wrkMast.getIoType() == 110) {
                locSts = "D";
            // 库位转移 ===>> D.空桶/空栈板
            } else if (wrkMast.getIoType() == 11) {
                locSts = wrkMast.getFullPlt().equalsIgnoreCase("N")?"D":"F";
                // 库位转移:目标库位
                LocMast locMast = locMastService.selectById(wrkMast.getLocNo());
                if (Cools.isEmpty(locMast)) {
                    throw new CoolException("取消库位转移失败,目标库位不存在:"+ wrkMast.getSourceLocNo());
                }
                locMast.setLocSts("O");
                locMast.setModiTime(new Date());
                locMast.setModiUser(userId);
                locMastService.updateById(locMast);
            }
        } else {
            throw new CoolException("当前工作状态无法取消");
        }
        // 订单关联
        List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(wrkMast.getWrkNo());
        for (WrkDetl wrkDetl : wrkDetls) {
            if (!Cools.isEmpty(wrkDetl.getOrderNo())) {
                if (!BaseController.isJSON(wrkDetl.getOrderNo())) {
                    if (!orderDetlService.decrease(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getAnfme())) {
                        throw new CoolException("订单数据回滚失败");
                    }
                } else {
                    // 订单合并出库
                    List<OrderDto> orderDtoList = JSON.parseArray(wrkDetl.getOrderNo(), OrderDto.class);
                    for (OrderDto orderDto : orderDtoList) {
                        if (!orderDetlService.decrease(orderDto.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), orderDto.getAnfme())) {
                            throw new CoolException("订单数据回滚失败");
                        }
                    }
                }
            }
        }
        // 取消操作人员记录
        wrkMast.setManuType("手动取消");
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(new Date());
        if (!wrkMastService.updateById(wrkMast)) {
            throw new CoolException("取消工作档失败");
        }
        // 保存工作主档历史档
        if (!wrkMastLogService.save(wrkMast.getWrkNo())) {
            throw new CoolException("保存工作历史档失败, workNo = " + wrkMast.getWrkNo());
        }
        // 删除工作主档
        boolean wrkMastRes = wrkMastService.deleteById(wrkMast);
        if (wrkMast.getIoType() != 10 && wrkMast.getIoType() != 110) {
            // 保存工作明细档历史档
            if (!wrkDetlLogService.save(wrkMast.getWrkNo())) {
//                throw new CoolException("保存工作明细历史档失败, workNo = " + wrkMast.getWrkNo());
            }
            // 删除工作档明细
            boolean wrkDetlRes = wrkDetlService.delete(new EntityWrapper<WrkDetl>().eq("wrk_no", workNo));
        //拣料入库 盘点入库不可取消
        if(wrkMast.getIoType() == 53 || wrkMast.getIoType() == 57){
            throw new CoolException("当前任务不可取消");
        }
        // 修改库位状态
        LocMast locMast = locMastService.selectById(locNo);
        if (Cools.isEmpty(locMast)) {
            throw new CoolException("取消工作档失败,库位不存在:"+ locNo);
        //AGV机器人未取货前取消
        if(wrkMast.getWrkSts() < 203){
            //入库取消
            if(wrkMast.getIoType() == 1 || wrkMast.getIoType() == 10){
                //源站点
                String devNo = wrkMast.getSourceLocNo();
                //目标库位
                String locNo = wrkMast.getLocNo();
                agvLocMastService.updateLocStsByLocNo(locNo,"O");
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(devNo,"F",wrkMast.getBarcode());
                //出库取消
            }else {
                //源库位
                String locNo = wrkMast.getSourceLocNo();
                //目标站点
                String devNo = wrkMast.getLocNo();
                agvLocMastService.updateLocStsByLocNo(locNo,"F");
                agvBasDevpService.updateLocStsAndBarcodeByDevNo(devNo,"O","");
            }
        }
        //订单回滚
        AgvWrkDetl agvWrkDetl = agvWrkDetlService.selectByWrkNo(wrkMast.getWrkNo()).get(0);
        if(!Cools.isEmpty(agvWrkDetl.getOrderNo())){
            OrderDetl orderDetl = orderDetlService.selectByOrderNoAndMatnr(agvWrkDetl.getOrderNo(),agvWrkDetl.getMatnr(),agvWrkDetl.getThreeCode(),agvWrkDetl.getDeadTime());
            orderDetl.setQty(orderDetl.getQty() - agvWrkDetl.getAnfme());
            orderDetlService.updateById(orderDetl);
        }
        //保存工作档以及明细
        agvWrkMastLogService.save(wrkMast);
        agvWrkDetlLogService.save(wrkMast.getWrkNo());
        //删除工作档以及明细
        if(!agvWrkMastService.deleteByWrkNo(wrkMast.getWrkNo()) || !agvWrkDetlService.deleteByWrkNo(wrkMast.getWrkNo())){
            throw new CoolException("删除失败,请联系管理员");
        }
    }
    /*
    更新目标库位信息
     */
    private void updateAgvLocMast(AgvLocMast locMast, String locSts){
        locMast.setLocSts(locSts);
        locMast.setModiTime(new Date());
        locMast.setModiUser(userId);
        boolean locMastRes = locMastService.updateById(locMast);
        if (!wrkMastRes || !locMastRes) {
            throw new CoolException("保存数据失败");
        agvLocMastService.updateById(locMast);
    }
    /*
    更新源站点信息
     */
    private void updateAgvBasDevp(AgvBasDevp agvBasDevp, String locSts){
        agvBasDevp.setLocSts(locSts);
        agvBasDevpService.updateById(agvBasDevp);
    }
    /*
    生成工作档明细
     */
    private void createWrkDetlReWrite(String matnr, int wrkNo, String orderNo,String batch, double anfme, String zpallet, Date now, Long userId, String csocode, String isoseq){
        Mat mat = matService.selectByMatnr(matnr);
        if (Cools.isEmpty(mat)) {
            throw new CoolException(matnr + "商品维护失败");
        }
        AgvWrkDetl wrkDetl = new AgvWrkDetl();
        wrkDetl.sync(mat);
        wrkDetl.setWrkNo(wrkNo);
        wrkDetl.setOrderNo(orderNo);
        wrkDetl.setIoTime(now);
        wrkDetl.setBatch(batch);
        wrkDetl.setAnfme(anfme); // 数量
        wrkDetl.setSuppCode(zpallet); // 托盘条码
        wrkDetl.setAppeUser(userId);
        wrkDetl.setAppeTime(now);
        wrkDetl.setModiUser(userId);
        wrkDetl.setModiTime(now);
        wrkDetl.setThreeCode(csocode);
        wrkDetl.setDeadTime(isoseq);
        if (!agvWrkDetlService.insert(wrkDetl)) {
            throw new CoolException("保存工作明细失败");
        }
    }
    @Override
    @Transactional
    public void pickWrkMast(String workNo, Long userId) {
        WrkMast wrkMast = wrkMastService.selectById(workNo);
        if (Cools.isEmpty(wrkMast)){
            throw new CoolException(workNo+"工作档不存在");
        }
        // 入出库类型判断
        if (wrkMast.getIoType() != 103 && wrkMast.getIoType() != 104 && wrkMast.getIoType() != 107) {
            throw new CoolException("当前入出库类型无法进行操作");
        }
        // 工作状态判断
        if (wrkMast.getWrkSts() < 11 || wrkMast.getWrkSts() == 15) {
            throw new CoolException("当前工作状态无法进行操作");
        }
        // 保存工作明细档历史档
//        if (!wrkDetlLogService.save(wrkMast.getWrkNo())) {
//            throw new CoolException("保存工作明细档历史档失败");
//        }
        // 保存工作主档历史档
        if (!wrkMastLogService.save(wrkMast.getWrkNo())) {
            throw new CoolException("保存工作主档历史档失败");
        }
        // 获取目标站
        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                .eq("type_no", wrkMast.getIoType() - 50)
                .eq("stn_no", wrkMast.getStaNo()) // 作业站点 = 拣料出库的目标站
                .eq("crn_no", wrkMast.getCrnNo()); // 堆垛机号
        StaDesc staDesc = staDescService.selectOne(wrapper);
        if (Cools.isEmpty(staDesc)) {
            throw new CoolException("入库路径不存在");
        }
        // 堆垛机站点(目标站)
        Integer staNo = staDesc.getCrnStn();
        // 更新工作档数据状态
        wrkMast.setIoType(wrkMast.getIoType() - 50); // 入出库类型: 103->53,104->54,107->57
        wrkMast.setWrkSts(2L); // 工作状态: 2.设备上走
        wrkMast.setSourceStaNo(wrkMast.getStaNo()); // 源站
        wrkMast.setStaNo(staNo); // 目标站
        wrkMast.setLocNo(wrkMast.getSourceLocNo()); // 目标库位 = 出库时的源库位
        wrkMast.setSourceLocNo(""); // 源库位清空
        wrkMast.setModiTime(new Date());
        wrkMast.setModiUser(userId);
        if (!wrkMastService.updateById(wrkMast)) {
            throw new CoolException("更新工作档数据状态失败");
        }
        // 修改库位状态 Q.拣料/盘点/并板再入库
        LocMast locMast = locMastService.selectById(wrkMast.getLocNo());
        locMast.setLocSts("Q");
        locMast.setModiTime(new Date());
        locMast.setModiUser(userId);
        if (!locMastService.updateById(locMast)) {
            throw new CoolException("修改库位状态失败");
        }
    }
    @Override
    public StartupDto createWaitPainWrkMastStart(List<AgvWaitPakin> list, Long userId) {
        return null;
    }
    @Override
    @Transactional
    public String dealPreHaveStart(Integer wrkNo, Long userId) {
        if (true) {
            throw new CoolException("功能停用");
        }
        return "";
    }
    @Override
    @Transactional
    public void shuttleTransfer(List<String> locNos) {
        if (Cools.isEmpty(locNos)) {
            return;
        }
        if (true && !Cools.isEmpty(locNos)) {
            throw new CoolException("暂不支持移库任务");    // todo:luxiaotao 移库开关
        }
        LocMast one = locMastService.selectById(locNos.get(0));
        List<Integer> rows = Utils.getGroupLoc(Integer.parseInt(locNos.get(0).substring(0, 2)));
        List<LocMast> locMasts = locMastService.queryFreeLocMast(rows, rows.size(), one.getLocType1());
        if (Cools.isEmpty(locMasts)) {
            throw new CoolException("库位移转失败,已无空库位");
        }
        // 入库排序 深库位 ==> 浅库位
        switch (locMasts.get(0).getRow1()) {
            case 4:
            case 5:
            case 6:
            case 7:
            case 12:
            case 13:
            case 14:
            case 19:
            case 20:
            case 21:
                Collections.reverse(locMasts);
                break;
            default:
                break;
        }
        if (locNos.size() > locMasts.size()) {
            throw new CoolException("服务器错误");
        }
    /*
    生成工作档明细
     */
    @Deprecated
    private void createWrkDetlReWrite(List<AgvWaitPakin> agvWaitPakinList, AgvWrkMast wrkMast, Long userId){
        Date now = new Date();
        // 生成移库工作档
        Iterator<LocMast> iterator = locMasts.iterator();
        for (String sourceLocNo : locNos) {
        agvWaitPakinList.stream().forEach(agvWaitPakin -> {
            Mat mat = matService.selectByMatnr(agvWaitPakin.getMatnr());
            if (Cools.isEmpty(mat)) {
                throw new CoolException(agvWaitPakin.getMatnr() + "商品维护失败");
            }
            AgvWrkDetl wrkDetl = new AgvWrkDetl();
            wrkDetl.sync(mat);
            wrkDetl.setWrkNo(wrkMast.getWrkNo());
            wrkDetl.setOrderNo(agvWaitPakin.getOrderNo());
            wrkDetl.setIoTime(now);
            wrkDetl.setBatch(agvWaitPakin.getBatch());
            wrkDetl.setAnfme(agvWaitPakin.getAnfme()); // 数量
            wrkDetl.setZpallet(agvWaitPakin.getZpallet()); // 托盘条码
            wrkDetl.setAppeUser(userId);
            wrkDetl.setAppeTime(now);
            wrkDetl.setModiUser(userId);
            wrkDetl.setModiTime(now);
            if (!agvWrkDetlService.insert(wrkDetl)) {
                throw new CoolException("保存工作明细失败");
            }
        });
    }
            while (iterator.hasNext()) {
                LocMast sourceLoc = locMastService.selectById(sourceLocNo);
                List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("loc_no", sourceLocNo));
                if (Cools.isEmpty(sourceLoc)){
                    throw new CoolException("未找到库位");
                }
                LocMast loc = iterator.next();
                if (Cools.isEmpty(loc)){
                    throw new CoolException("未找到库位");
                }
                if (!sourceLoc.getCrnNo().equals(loc.getCrnNo())) {
//                    throw new CoolException("移转库位属于不同堆垛机");   todo:luxiaotao
                }
                // 获取工作号
                int workNo = commonService.getWorkNo(WorkNoType.PICK.type);
                // 保存工作档
                WrkMast wrkMast = new WrkMast();
                wrkMast.setWrkNo(workNo);
                wrkMast.setIoTime(now);
                wrkMast.setWrkSts(21L); // 工作状态:21.生成出库任务
                wrkMast.setIoType(11); // 入出库状态: 11.库格移载
                wrkMast.setIoPri(15D);
                wrkMast.setOutMost(locMastService.isOutMost(loc.getLocNo(), false)?1:0);;
                wrkMast.setCrnNo(sourceLoc.getCrnNo());
                wrkMast.setSourceLocNo(sourceLocNo); // 源库位
                wrkMast.setLocNo(loc.getLocNo()); // 目标库位
                wrkMast.setFullPlt(Cools.isEmpty(locDetls)?"N":"Y"); // 满板:Y
                wrkMast.setPicking("N"); // 拣料
                wrkMast.setExitMk("N"); // 退出
                wrkMast.setEmptyMk(sourceLoc.getLocSts().equals("D")?"Y":"N"); // 空板
                wrkMast.setBarcode(sourceLoc.getBarcode()); // 托盘码
                wrkMast.setLinkMis("N");
                wrkMast.setAppeUser(9527L);
                wrkMast.setAppeTime(now);
                wrkMast.setModiUser(9527L);
                wrkMast.setModiTime(now);
                boolean res = wrkMastService.insert(wrkMast);
                if (!res) {
                    throw new CoolException("保存工作档失败");
                }
                // 工作档明细保存
                for (LocDetl locDetl : locDetls) {
                    WrkDetl wrkDetl = new WrkDetl();
                    wrkDetl.sync(locDetl);
                    wrkDetl.setWrkNo(workNo);
                    wrkDetl.setIoTime(now);
                    wrkDetl.setAnfme(locDetl.getAnfme());
                    wrkDetl.setAppeTime(now);
                    wrkDetl.setAppeUser(9527L);
                    wrkDetl.setModiTime(now);
                    wrkDetl.setModiUser(9527L);
                    if (!wrkDetlService.insert(wrkDetl)) {
                        throw new CoolException("保存工作档明细失败");
                    }
                }
                // 修改源库位状态
                if (sourceLoc.getLocSts().equals("D") || sourceLoc.getLocSts().equals("F")) {
                    sourceLoc.setLocSts("R"); // R.出库预约
                    sourceLoc.setModiUser(9527L);
                    sourceLoc.setModiTime(now);
                    if (!locMastService.updateById(sourceLoc)){
                        throw new CoolException("更新源库位状态失败");
                    }
                } else {
                    throw new CoolException(sourceLoc.getLocNo() + "源库位出库失败,状态:"+sourceLoc.getLocSts$());
                }
                // 修改目标库位状态
                if (loc.getLocSts().equals("O")) {
                    loc.setLocSts("S"); // S.入库预约
                    loc.setModiTime(now);
                    loc.setModiUser(9527L);
                    if (!locMastService.updateById(loc)) {
                        throw new CoolException("更新目标库位状态失败");
                    }
                } else {
                    throw new CoolException("移转失败,目标库位状态:"+loc.getLocSts$());
    /*
    生成工作档
     */
    private AgvWrkMast createWrkMast(int ioType, long wrkSts, String sourceLocNo, String locNo, String barcode,  Date now, Long userId){
        AgvWrkMast wrkMast = new AgvWrkMast();
        //生成工作号
//        int workNo = agvCommonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
//        wrkMast.setWrkNo();
        //工作状态
        wrkMast.setWrkSts(wrkSts);
        //入出库类型
        wrkMast.setIoType(ioType);
        wrkMast.setIoTime(now);
        //优先级
        wrkMast.setIoPri(300.0);
        //源站点
        wrkMast.setSourceLocNo(sourceLocNo);
        //目标站点
        wrkMast.setLocNo(locNo);
        //容器编码
        wrkMast.setBarcode(barcode);
        // 满板:Y
        //wrkMast.setFullPlt("Y");
        // 拣料
        //wrkMast.setPicking("N");
        // 退出
        //wrkMast.setExitMk("N");
        // 空板
        //wrkMast.setEmptyMk("N");
        //wrkMast.setLinkMis("N");
        wrkMast.setAppeUser(userId);
        wrkMast.setAppeTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(now);
        if (!agvWrkMastService.insertByIncrease(wrkMast)) {
            throw new CoolException("保存工作档失败");
        }
        int i = agvWrkMastService.selectCount(new EntityWrapper<AgvWrkMast>());
        log.info(i + "");
        wrkMast = agvWrkMastService.selectOne(new EntityWrapper<AgvWrkMast>().eq("loc_no", locNo).eq("source_loc_no",sourceLocNo));
        return wrkMast;
    }
    /*
    生成工作档
     */
    @Deprecated
    private AgvWrkMast createWrkMast(AgvBasDevp agvBasDevp,AgvLocMast agvLocMast, Date now, Long userId){
        AgvWrkMast wrkMast = new AgvWrkMast();
        //生成工作号
        //int workNo = agvCommonService.getWorkNo(0);
        //wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(new Date());
        // 工作状态:201.生成入库任务ID
        wrkMast.setWrkSts(201L);
        // 入出库状态:1.入库
        wrkMast.setIoType(1);
        //生成优先级
        wrkMast.setIoPri(300.0);
        wrkMast.setSourceLocNo(agvBasDevp.getDevNo());
        wrkMast.setLocNo(agvLocMast.getLocNo());
        wrkMast.setBarcode(agvBasDevp.getBarcode());
        // 满板:Y
        wrkMast.setFullPlt("Y");
        // 拣料
        wrkMast.setPicking("N");
        // 退出
        wrkMast.setExitMk("N");
        // 空板
        wrkMast.setEmptyMk("N");
        wrkMast.setLinkMis("N");
        wrkMast.setAppeUser(userId);
        wrkMast.setAppeTime(now);
        wrkMast.setModiUser(userId);
        wrkMast.setModiTime(now);
        if (!agvWrkMastService.insert(wrkMast)) {
            throw new CoolException("保存工作档失败");
        }
        return wrkMast;
    }
    private boolean isPakOut(String locNo, double anfme){
        AgvLocDetl agvLocDetl = agvLocDetlService.selectOne(new EntityWrapper<AgvLocDetl>().eq("loc_no", locNo));
        if(agvLocDetl.getAnfme() > anfme){
            return false;
        }
        return true;
    }
    /*
    AGV生成出库工作档后修改订单信息
    TODO 与四项库生成出库工作档后修改订单信息整合到一起
     */
    private void modifyOrderDetl(LocDto locDto, Long userId){
        if (!BaseController.isJSON(locDto.getOrderNo())) {
            //非合并出库
            OrderDetl orderDetl = orderDetlService.selectItem(locDto.getOrderNo(), locDto.getMatnr(), locDto.getBatch());
            if (orderDetl == null) {
                orderDetl = orderDetlService.selectItem(locDto.getOrderNo(), locDto.getMatnr(), null);
            }
            if (!orderDetlService.increase(orderDetl.getOrderId(), orderDetl.getMatnr(), orderDetl.getBatch(), locDto.getAnfme())) {
                throw new CoolException("修改订单明细数量失败");
            }
            orderService.updateSettle(orderDetl.getOrderId(), 2L, userId);
        }else {
            //合并出库
            List<OrderDto> orderDtoList = JSON.parseArray(locDto.getOrderNo(), OrderDto.class);
            //实际出库数量
            Double locAnfme = locDto.getAnfme();
            //订单实际出库数量
            Double orderAnfme;
            for (OrderDto orderDto : orderDtoList) {
                OrderDetl orderDetl = orderDetlService.selectItem(orderDto.getOrderNo(), locDto.getMatnr(), locDto.getBatch());
                if (orderDetl == null) {
                    orderDetl = orderDetlService.selectItem(orderDto.getOrderNo(), locDto.getMatnr(), null);
                }
                iterator.remove();
                break;
                if(locAnfme > orderDetl.getAnfme()){
                    orderAnfme = orderDetl.getAnfme();
                    locAnfme -= orderAnfme;
                }else {
                    orderAnfme = locAnfme;
                }
                if (!orderDetlService.increase(orderDetl.getOrderId(), orderDetl.getMatnr(), orderDetl.getBatch(), orderAnfme)) {
                    throw new CoolException("修改订单明细数量失败");
                }
                orderService.updateSettle(orderDetl.getOrderId(), 2L, userId);
            }
        }
    }
}