package com.zy.common.service; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; import com.core.common.Arith; import com.core.common.Cools; import com.core.exception.CoolException; import com.zy.asrs.entity.*; import com.zy.asrs.mapper.LocMastMapper; import com.zy.asrs.service.*; import com.zy.asrs.utils.Utils; import com.zy.asrs.utils.VersionUtils; import com.zy.common.model.LocTypeDto; import com.zy.common.model.Shelves; import com.zy.common.model.StartupDto; import com.zy.common.properties.SlaveProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * 货架核心功能 * Created by vincent on 2020/6/11 */ @Slf4j @Service public class CommonService { @Autowired private WrkMastService wrkMastService; @Autowired private WrkLastnoService wrkLastnoService; @Autowired private RowLastnoService rowLastnoService; @Autowired private BasCrnpService basCrnpService; @Autowired private StaDescService staDescService; @Autowired private BasDevpService basDevpService; @Autowired private LocMastService locMastService; @Autowired private LocDetlService locDetlService; @Autowired private SlaveProperties slaveProperties; @Autowired private LocMastMapper locMastMapper; /** * 生成工作号 * @param wrkMk 0:入库 ; 1:出库;2拣选 * @return workNo(工作号) */ public int getWorkNo(Integer wrkMk) { WrkLastno wrkLastno = wrkLastnoService.selectById(wrkMk); if (Cools.isEmpty(wrkLastno)) { throw new CoolException("数据异常,请联系管理员"); } int workNo = 0; // 入出库类型 if (wrkLastno.getWrkMk() == 0 || wrkLastno.getWrkMk() == 1 || wrkLastno.getWrkMk() == 2) { workNo = wrkLastno.getWrkNo(); int sNo = wrkLastno.getSNo(); int eNo = wrkLastno.getENo(); workNo = workNo>=eNo ? sNo : workNo+1; while (true) { WrkMast wrkMast = wrkMastService.selectById(workNo); if (null != wrkMast) { workNo = workNo>=eNo ? sNo : workNo+1; } else { break; } } if (workNo > 0){ wrkLastno.setWrkNo(workNo); wrkLastnoService.updateById(wrkLastno); } } if (workNo == 0) { throw new CoolException("生成工作号失败,请联系管理员"); } else { if (wrkMastService.selectById(workNo)!=null) { throw new CoolException("生成工作号" + workNo + "在工作档中已存在"); } } return workNo; } public StartupDto getLocNo(Integer whsType, Integer staDescId, Integer sourceStaNo, boolean emptyMk, List matNos, LocTypeDto locTypeDto, int times) { LocTypeDto oldLocType = locTypeDto.clone(); return getLocNo(whsType, staDescId, sourceStaNo, emptyMk, matNos, locTypeDto, oldLocType, times); } /** * 检索库位号 * @param whsType 类型 1:双深式货架 * @param staDescId 路径ID * @param sourceStaNo 源站 * @param matNos 物料号集合 * @return locNo 检索到的库位号 */ public StartupDto getLocNo(Integer whsType, Integer staDescId, Integer sourceStaNo, boolean emptyMk, List matNos, LocTypeDto locTypeDto, LocTypeDto oldLocType, int times) { StartupDto startupDto = new StartupDto(); // 生成工作号 int crnNo = 0; if (sourceStaNo < 200) { whsType = 1; crnNo=1; } else if (sourceStaNo < 300) { whsType = 2; crnNo=2; }else { whsType = 3; crnNo=3; } int workNo = getWorkNo(0); RowLastno rowLastno = rowLastnoService.selectById(whsType); if (Cools.isEmpty(rowLastno)) { throw new CoolException("数据异常,请联系管理员"); } int curRow = rowLastno.getCurrentRow(); // 当前列 int sRow = rowLastno.getsRow(); // 起始列 int eRow = rowLastno.geteRow(); // 终止列 int crn_qty = rowLastno.getCrnQty(); // 堆垛机数量(巷道数量) int rowCount = eRow - sRow + 1; // 库排总数 // 目标堆垛机号 // int crnNo = 0; // 目标库位 LocMast locMast = null; // 靠近摆放规则 --- 同天同规格物料 if (!Cools.isEmpty(matNos) && sourceStaNo < 200) { List locNos = locDetlService.getSameDetlToday(matNos.get(0), sRow, eRow); for (String locNo : locNos) { if (Utils.isShallowLoc(slaveProperties, locNo)) { continue; } String shallowLocNo = Utils.getShallowLoc(slaveProperties, locNo); LocMast shallowLoc = locMastService.selectById(shallowLocNo); // 检测目标库位是否为空库位 if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) { // 浅库位符合尺寸检测 if (VersionUtils.locMoveCheckLocType(shallowLoc, locTypeDto)) { // 因库位移转、需预留空库位 if (locMastService.checkEmptyCount(shallowLoc)) { // 浅库位对应堆垛机必须可用且无异常 if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) { locMast = shallowLoc; crnNo = locMast.getCrnNo(); break; } } } } } } // 靠近摆放规则 --- 空托 if (emptyMk) { // List locMasts = locMastService.selectList(new EntityWrapper().eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow)); List locMasts = null; if(crnNo==1) { locMasts = locMastService.selectList(new EntityWrapper().eq("loc_sts", "D").eq("row1", 1)); } else { locMasts = locMastService.selectList(new EntityWrapper().eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow)); } if (locMasts.size() > 0) { for (LocMast loc : locMasts) { if (Utils.isShallowLoc(slaveProperties, loc.getLocNo())) { continue; } String shallowLocNo = Utils.getShallowLoc(slaveProperties, loc.getLocNo()); // 检测目标库位是否为空库位 LocMast shallowLoc = locMastService.selectById(shallowLocNo); if (shallowLoc != null && shallowLoc.getLocSts().equals("O")) { // 因库位移转、需预留空库位 if (locMastService.checkEmptyCount(shallowLoc)) { // 浅库位对应堆垛机必须可用且无异常 if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) { locMast = shallowLoc; crnNo = locMast.getCrnNo(); break; } } } } } } // 如果没有相近物料,则按规则轮询货架 if (null == locMast) { Shelves shelves = new Shelves(rowCount, crn_qty); if (whsType == 1) { curRow = curRow + 1; if (curRow > eRow) { curRow = sRow; } crnNo = whsType; basCrnpService.checkSiteStatus(crnNo, true); // for (int i = 0; i < shelves.group; i ++) { // curRow = shelves.start(curRow); // if (curRow < 0) { // throw new CoolException("检索库位失败,请联系管理员"); // } // Integer crnNo1 = shelves.getCrnNo(curRow); // if (basCrnpService.checkSiteError(crnNo1, true)) { // crnNo = crnNo1; // if (curRow == 3 || curRow == 4) { // curRow = 3; // } // break; // } // } } else if (whsType == 2) { if (curRow == sRow) { curRow = eRow; } else { curRow = sRow; } basCrnpService.checkSiteStatus(crnNo, true); }else { if (curRow == sRow) { curRow = eRow; } else { curRow = sRow; } basCrnpService.checkSiteStatus(crnNo, true); } } if (crnNo == 0) { throw new CoolException("没有可用的堆垛机"); } // 获取目标站 Wrapper wrapper = new EntityWrapper() .eq("type_no", staDescId) .eq("stn_no", sourceStaNo) .eq("crn_no", crnNo); StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { log.error("入库路径不存在, staDescId={}, sourceStaNo={}, crnNo={}", staDescId, sourceStaNo, crnNo); throw new CoolException("入库路径不存在"); } // 检测目标站 BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn()); if (!staNo.getAutoing().equals("Y")) { throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); } // 更新库位排号 rowLastno.setCurrentRow(curRow); rowLastnoService.updateById(rowLastno); // 开始查找库位 ==============================>> // 1.当检索库排为浅库位排时,优先寻找当前库排的深库位排 if (locMast == null) { if (Utils.isShallowLoc(slaveProperties, curRow)) { Integer deepRow = 0; if(curRow == 2) { deepRow = Utils.getDeepRow(slaveProperties, curRow); } else { deepRow = curRow; } if(emptyMk){ locMast = locMastService.queryFreeLocMastIncludeFirst(deepRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); if (Cools.isEmpty(locMast)){ locMast = locMastService.queryFreeLocMast(deepRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); } } else { locMast = locMastService.queryFreeLocMastExceptFirst(deepRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); } // locMast = locMastService.queryFreeLocMast(deepRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); // 因库位移转、需预留空库位 if (!locMastService.checkEmptyCount(locMast)) { locMast = null; } } if (Cools.isEmpty(locMast)) { if(emptyMk){ locMast = locMastService.queryFreeLocMastIncludeFirst(curRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); if (Cools.isEmpty(locMast)){ locMast = locMastService.queryFreeLocMast(curRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); } } else { locMast = locMastService.queryFreeLocMastExceptFirst(curRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); } // locMast = locMastService.queryFreeLocMast(curRow, locTypeDto.getLocType1(), locTypeDto.getLocType2(), locTypeDto.getLocType3()); // 因库位移转、需预留空库位 if (!locMastService.checkEmptyCount(locMast)) { locMast = null; } // 目标库位 ===>> 浅库位, 则校验其深库位是否为 F D X if (null != locMast && Utils.isShallowLoc(slaveProperties, locMast.getLocNo())) { LocMast deepLoc = locMastService.selectById(Utils.getDeepLoc(slaveProperties, locMast.getLocNo())); if (!deepLoc.getLocSts().equals("F") && !deepLoc.getLocSts().equals("D") && !deepLoc.getLocSts().equals("X")) { locMast = null; } } // 目标库位 ===>> 深库位, 则校验其浅库位是否为 O if (null != locMast && Utils.isDeepLoc(slaveProperties, locMast.getLocNo())) { LocMast shallowLoc = locMastService.selectById(Utils.getShallowLoc(slaveProperties, locMast.getLocNo())); if (!shallowLoc.getLocSts().equals("O")) { locMast = null; } } } } // 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位 if (Cools.isEmpty(locMast)) { // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 if (times < rowCount) { times = times + 1; return getLocNo(1, staDescId, sourceStaNo, emptyMk, matNos, locTypeDto, oldLocType, times); } else { times = 0; } // 货物检索低库位仓失败,兼容高库位仓后继续执行 if (locTypeDto.getLocType1() == 1) { locTypeDto.setLocType1((short) 2); return getLocNo(1, staDescId, sourceStaNo, emptyMk, matNos, locTypeDto, oldLocType, times); } // // 货物检索窄库位仓失败,兼容宽库位仓后继续执行 // if (locTypeDto.getLocType2() == 1) { // locTypeDto.setLocType2((short) 2); // if (oldLocType.getLocType1() == 1) { // locTypeDto.setLocType1((short) 1); // } // return getLocNo(null, staDescId, sourceStaNo, emptyMk, matNos, locTypeDto, oldLocType, times); // } // // 货物检索轻库位仓失败,兼容重库位仓后继续执行 // if (locTypeDto.getLocType3() == 1) { // locTypeDto.setLocType3((short) 2); // if (oldLocType.getLocType1() == 1) { // locTypeDto.setLocType1((short) 1); // } // if (oldLocType.getLocType2() == 1) { // locTypeDto.setLocType2((short) 1); // } // return getLocNo(null, staDescId, sourceStaNo, emptyMk, matNos, locTypeDto, oldLocType, times); // } log.error("系统没有空库位!!! 尺寸规格: {}, 轮询次数:{}", JSON.toJSONString(locTypeDto), times); throw new CoolException("没有空库位"); } String locNo = locMast.getLocNo(); // 返回dto startupDto.setWorkNo(workNo); startupDto.setCrnNo(crnNo); startupDto.setSourceStaNo(sourceStaNo); startupDto.setStaNo(staNo.getDevNo()); startupDto.setLocNo(locNo); return startupDto; } // /** // * 检索库位号 // * @param whsType 类型 1:双深式货架 // * @param staDescId 路径ID // * @param sourceStaNo 源站 // * @param matNos 产品号集合 // * @return locNo 检索到的库位号 // */ // public StartupDto getLocNo(Integer whsType, Integer staDescId, Integer sourceStaNo, List matNos, int times) { //// if (sourceStaNo == 3) { //// whsType = 1; //// } else if (sourceStaNo == 7) { //// whsType = 2; //// } else if (sourceStaNo == 19) { //// whsType = 3; //// } else { //// throw new CoolException("无效入库站"); //// } // StartupDto startupDto = new StartupDto(); // RowLastno rowLastno = rowLastnoService.selectById(whsType); // if (Cools.isEmpty(rowLastno)) { // throw new CoolException("数据异常,请联系管理员"); // } // int curRow = rowLastno.getCurrentRow(); // int sRow = rowLastno.getsRow(); // int eRow = rowLastno.geteRow(); // int crn_qty = rowLastno.getCrnQty(); // int rowCount = eRow - sRow + 1; // // 目标堆垛机号 // int crnNo = 0; // // 目标库位 // LocMast locMast = null; // // // // 按规则轮询货架 // if (whsType == 1 || whsType == 2) { // if (curRow == sRow) { // curRow = eRow; // } else { // curRow = sRow; // } // crnNo = whsType; // basCrnpService.checkSiteStatus(crnNo, true); // } else { // Shelves shelves = new Shelves(rowCount, crn_qty); // curRow = curRow - 4; // for (int i = 0; i < shelves.group; i ++) { // curRow = shelves.start(curRow); // if (curRow < 0) { // throw new CoolException("检索库位失败,请联系管理员"); // } // Integer crnNo1 = shelves.getCrnNo(curRow); // if (basCrnpService.checkSiteError(crnNo1 + 2, true)) { // // 偏移量补偿 // curRow = curRow + 4; // crnNo = crnNo1 + 2; // break; // } // } // } // // if (crnNo == 0) { // throw new CoolException("没有可用的堆垛机"); // } // // // 获取目标站 // Wrapper wrapper = new EntityWrapper() // .eq("type_no", staDescId) // .eq("stn_no", sourceStaNo) // .eq("crn_no", crnNo); // StaDesc staDesc = staDescService.selectOne(wrapper); // if (Cools.isEmpty(staDesc)) { // log.error("入库路径不存在, staDescId={}, sourceStaNo={}, crnNo={}", staDescId, sourceStaNo, crnNo); // throw new CoolException("入库路径不存在"); // } // // 检测目标站 // BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn()); // if (!staNo.getAutoing().equals("Y")) { // throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); // } // // // 更新库位排号 // rowLastno.setCurrentRow(curRow); // rowLastnoService.updateById(rowLastno); // // // 开始查找库位 ==============================>> // // // 查找库位 // locMast = locMastService.queryFreeLocMast(curRow); // // if (Cools.isEmpty(locMast)) { // // 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归 // if (times >= rowCount) { // log.error("系统没有空库位!!!"); // throw new CoolException("没有空库位"); // } // times = times + 1; // return getLocNo(1, staDescId, sourceStaNo, matNos, times); // } // String locNo = locMast.getLocNo(); // // // 返回dto // startupDto.setCrnNo(crnNo); // startupDto.setSourceStaNo(sourceStaNo); // startupDto.setStaNo(staNo.getDevNo()); // startupDto.setLocNo(locNo); // return startupDto; // } //出深库位托盘 public static void main(String[] args) { System.out.println(Arith.remainder(1, 4)); System.out.println("0200201".substring(0, 2)); String locNo = "0800201"; int row = Integer.parseInt(locNo.substring(0, 2)); double remainder = Arith.remainder(row, 4); int targetRow; if (remainder == 1) { // 得到当前库位的外围库位 targetRow = row + 1; } else if (remainder == 0) { // 得到当前库位的内围库位 targetRow = row - 1; } else { return; } String zerofill = zerofill(String.valueOf(targetRow), 2)+locNo.substring(2); System.out.println(zerofill); } public static String zerofill(String msg, Integer count) { if (msg.length() == count) { return msg; } else if (msg.length() > count) { return msg.substring(0, 16); } else { StringBuilder msgBuilder = new StringBuilder(msg); for(int i = 0; i < count - msg.length(); ++i) { msgBuilder.insert(0, "0"); } return msgBuilder.toString(); } } public StartupDto emptyIngetLocNo(Integer devpNo) { int crnNo = 0; if (devpNo == 304) { crnNo = 3; } else if(devpNo == 204) { crnNo = 2; } else if(devpNo == 104) { crnNo = 1; }else if(devpNo == 311) { crnNo = 4; } // 目标库位 LocMast locMast = locMastMapper.queryEmptyLocNoByStaNo(crnNo); if (locMast == null) { throw new CoolException("没有空库位"); } // 获取目标站 Wrapper wrapper = new EntityWrapper() .eq("type_no", 10) .eq("stn_no", devpNo) .eq("crn_no", crnNo); StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { log.error("入库路径不存在, staDescId={}, sourceStaNo={}, crnNo={}", 10, devpNo, crnNo); throw new CoolException("入库路径不存在"); } // 检测目标站 BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn()); if (!staNo.getAutoing().equals("Y")) { throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); } basCrnpService.checkSiteStatus(crnNo, true); // 返回dto StartupDto startupDto = new StartupDto(); startupDto.setWorkNo(getWorkNo(0)); startupDto.setCrnNo(crnNo); startupDto.setSourceStaNo(devpNo); startupDto.setStaNo(devpNo); startupDto.setLocNo(locMast.getLocNo()); return startupDto; } public StartupDto getLocNoBy304(String type) { int row; int devpNo = 304; int crnNo = 3; if (type.equals("1")) { row = 7; } else if (type.equals("2")) { row = 6; } else { throw new CoolException("304物料类别识别错误:" + type); } // 目标库位 LocMast locMast = locMastMapper.queryLocByBarCode(row); //第六排成品可以放第七排原材料 if (locMast == null && type.equals("2")){ locMast = locMastMapper.queryLocByBarCode(7); } if (locMast == null) { throw new CoolException("304入库没有空库位"); } // 获取目标站 Wrapper wrapper = new EntityWrapper() .eq("type_no", 1) .eq("stn_no", devpNo) .eq("crn_no", crnNo); StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { log.error("入库路径不存在, staDescId={}, sourceStaNo={}, crnNo={}", 1, devpNo, crnNo); throw new CoolException("入库路径不存在"); } // 检测目标站 BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn()); if (!staNo.getAutoing().equals("Y")) { throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); } basCrnpService.checkSiteStatus(crnNo, true); // 返回dto StartupDto startupDto = new StartupDto(); startupDto.setWorkNo(getWorkNo(0)); startupDto.setCrnNo(crnNo); startupDto.setSourceStaNo(devpNo); startupDto.setStaNo(devpNo); startupDto.setLocNo(locMast.getLocNo()); return startupDto; } public StartupDto getLocNoBy311(String type) { int row; int devpNo = 311; int crnNo = 4; // if (type.equals("1")) { // row = 7; // } else if (type.equals("2")) { // row = 6; // } else { // throw new CoolException("304物料类别识别错误:" + type); // } // 目标库位 List locMasts = locMastMapper.selectOneByCrnNo(4); LocMast locMast = locMasts.get(0); if (locMast == null) { throw new CoolException("311入库没有空库位"); } // 获取目标站 Wrapper wrapper = new EntityWrapper() .eq("type_no", 1) .eq("stn_no", devpNo) .eq("crn_no", crnNo); StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { log.error("入库路径不存在, staDescId={}, sourceStaNo={}, crnNo={}", 1, devpNo, crnNo); throw new CoolException("入库路径不存在"); } // 检测目标站 BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn()); if (!staNo.getAutoing().equals("Y")) { throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); } basCrnpService.checkSiteStatus(crnNo, true); // 返回dto StartupDto startupDto = new StartupDto(); startupDto.setWorkNo(getWorkNo(0)); startupDto.setCrnNo(crnNo); startupDto.setSourceStaNo(devpNo); startupDto.setStaNo(devpNo); startupDto.setLocNo(locMast.getLocNo()); return startupDto; } /** * 一期寻找库位 * 1-6层 条码1或者2开头 * 7-11层 条码8开头 * @param ioType 1.入库 * @param devpNo 入库站点 * @param barcode 条码 * @return 库位信息 */ public StartupDto getLocNoNew(int ioType, Integer devpNo, String barcode) { char type = barcode.charAt(0); int flag = 0; if (type == '1' || type == '2') { flag = 1; } else if( type == '8') { flag = 2; } if (flag == 0) { throw new CoolException("条码有误:" + barcode); } // 目标库位 LocMast locMast = locMastMapper.queryLocByBarCodeNew(devpNo,flag); if (locMast == null) { throw new CoolException("入库没有空库位"); } // 堆垛机号 Integer crnNo = locMast.getCrnNo(); // 获取目标站 Wrapper wrapper = new EntityWrapper() .eq("type_no", ioType) .eq("stn_no", devpNo) .eq("crn_no", crnNo); StaDesc staDesc = staDescService.selectOne(wrapper); if (Cools.isEmpty(staDesc)) { log.error("入库路径不存在, staDescId={}, sourceStaNo={}, crnNo={}", 1, devpNo, crnNo); throw new CoolException("入库路径不存在"); } // 检测目标站 BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn()); if (!staNo.getAutoing().equals("Y")) { throw new CoolException("目标站"+staDesc.getCrnStn()+"不可用"); } basCrnpService.checkSiteStatus(crnNo, true); // 返回dto StartupDto startupDto = new StartupDto(); startupDto.setWorkNo(getWorkNo(0)); startupDto.setCrnNo(crnNo); startupDto.setSourceStaNo(devpNo); startupDto.setStaNo(devpNo); startupDto.setLocNo(locMast.getLocNo()); return startupDto; } }