package com.vincent.rsf.server.api.utils;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.vincent.rsf.framework.common.Arith;
|
import com.vincent.rsf.framework.common.Cools;
|
import com.vincent.rsf.framework.common.SpringUtils;
|
import com.vincent.rsf.framework.exception.CoolException;
|
import com.vincent.rsf.server.api.controller.params.TaskInParam;
|
import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto;
|
import com.vincent.rsf.server.api.entity.dto.LocTypeDto;
|
import com.vincent.rsf.server.manager.entity.*;
|
import com.vincent.rsf.server.manager.enums.LocStsType;
|
import com.vincent.rsf.server.manager.enums.TaskStsType;
|
import com.vincent.rsf.server.manager.enums.TaskType;
|
import com.vincent.rsf.server.manager.service.*;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
|
import javax.annotation.PostConstruct;
|
import javax.annotation.RegEx;
|
import javax.annotation.Resource;
|
import java.util.List;
|
|
@Component
|
public class LocUtils {
|
|
public static final Logger logger = LoggerFactory.getLogger(LocUtils.class);
|
|
private static List<Integer> doubleLocs;
|
|
private static Boolean isDoubleDeep;
|
|
@Autowired
|
private SlaveProperties slavePropertie;
|
|
@PostConstruct
|
public void init() {
|
doubleLocs = slavePropertie.getDoubleLocs();
|
isDoubleDeep = slavePropertie.isDoubleDeep();
|
}
|
|
|
/**
|
* 获取 浅库位对应的深库位号
|
*/
|
public static String getDeepLoc(String shallowLoc) {
|
LocService locService = SpringUtils.getBean(LocService.class);
|
Loc shaLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, shallowLoc));
|
int row = shaLoc.getRow()-1;
|
boolean contains = doubleLocs.contains(row);
|
Loc deepLoc = null;
|
if (contains) {
|
deepLoc = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getAreaId, shaLoc.getAreaId())
|
.eq(Loc::getRow, row)
|
.eq(Loc::getCol, shaLoc.getCol())
|
.eq(Loc::getLev, shaLoc.getLev())
|
);
|
}else {
|
deepLoc = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getAreaId, shaLoc.getAreaId())
|
.eq(Loc::getRow, shaLoc.getRow()+1)
|
.eq(Loc::getCol, shaLoc.getCol())
|
.eq(Loc::getLev, shaLoc.getLev())
|
);
|
}
|
return deepLoc.getCode();
|
}
|
|
/**
|
* 获取 深库位对应的浅库位号
|
*/
|
public static String getShallowLoc(String deepLoc) {
|
LocService locService = SpringUtils.getBean(LocService.class);
|
Loc depLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, deepLoc));
|
int row;
|
if (depLoc.getRow() != 1) {
|
row = depLoc.getRow()-1;
|
} else {
|
row = depLoc.getRow();
|
}
|
boolean contains = doubleLocs.contains(row);
|
Loc shallowLoc = null;
|
if (!contains) {
|
shallowLoc = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getAreaId, depLoc.getAreaId())
|
.eq(Loc::getRow, row)
|
.eq(Loc::getCol, depLoc.getCol())
|
.eq(Loc::getLev, depLoc.getLev())
|
);
|
}else {
|
shallowLoc = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getAreaId, depLoc.getAreaId())
|
.eq(Loc::getRow, depLoc.getRow()+1)
|
.eq(Loc::getCol, depLoc.getCol())
|
.eq(Loc::getLev, depLoc.getLev())
|
);
|
}
|
return shallowLoc.getCode();
|
}
|
|
/**
|
* 判断是否为浅库位
|
*/
|
public static boolean isShallowLoc(String locNo) {
|
if (isDoubleDeep) {
|
int row = getRow(locNo);
|
return !doubleLocs.contains(row);
|
} else {
|
return false;
|
}
|
}
|
|
//获取站点对应的库类型
|
public static Long getAreaType(Integer sourceStaNo) {
|
DeviceBindService rowLastnoService = SpringUtils.getBean(DeviceBindService.class);
|
List<DeviceBind> deviceBinds = rowLastnoService.list(new LambdaQueryWrapper<DeviceBind>());
|
for (DeviceBind deviceBind : deviceBinds) {
|
String[] staNoList = deviceBind.getStaList().split(";");
|
for (String staNo : staNoList) {
|
if (staNo.equals(sourceStaNo.toString())) {
|
return deviceBind.getId();
|
}
|
}
|
}
|
return 0L;
|
}
|
|
//库位排号分配
|
public static int[] LocNecessaryParameters(DeviceBind deviceBind, Integer curRow, Integer crnNumber) {
|
return LocNecessaryParametersDoubleExtension(curRow, crnNumber); //已完善
|
}
|
|
//经典双伸库位, 获取双深排
|
public static int[] LocNecessaryParametersDoubleExtension( Integer curRow, Integer crnNumber) {
|
int[] necessaryParameters = new int[]{0, 0, 0, 0};
|
|
necessaryParameters[0] = crnNumber; // 轮询次数
|
//满板正常入库
|
if (curRow.equals(crnNumber * 4)) {
|
necessaryParameters[1] = 1; //curRow 最深库位排
|
necessaryParameters[2] = 1; //crnNo 堆垛机号
|
necessaryParameters[3] = 2; //nearRow 最浅库位排
|
} else if (curRow.equals(crnNumber * 4 - 3)) {
|
necessaryParameters[1] = 4; //curRow 最深库位排
|
necessaryParameters[2] = 1; //crnNo 堆垛机号
|
necessaryParameters[3] = 3; //nearRow 最浅库位排
|
} else {
|
curRow = curRow + 4;
|
if (curRow < 1 || curRow > (crnNumber * 4)) {
|
throw new CoolException("库位排号异常:排号:" + curRow);
|
}
|
if ((curRow - 1) % 4 == 0) {
|
necessaryParameters[1] = curRow; //curRow 最深库位排
|
necessaryParameters[2] = (curRow + 3) / 4; //crnNo 堆垛机号
|
necessaryParameters[3] = curRow + 1; //nearRow 最浅库位排
|
} else if (curRow % 4 == 0) {
|
necessaryParameters[1] = curRow; //curRow 最深库位排
|
necessaryParameters[2] = curRow / 4; //crnNo 堆垛机号
|
necessaryParameters[3] = curRow - 1; //nearRow 最浅库位排
|
} else {
|
throw new CoolException("库位排号异常:排号:" + curRow);
|
}
|
}
|
|
return necessaryParameters;
|
}
|
|
/**
|
* 通过库位号获取 排
|
*/
|
public static int getRow(String locNo) {
|
if (!Cools.isEmpty(locNo)) {
|
LocService locService = SpringUtils.getBean(LocService.class);
|
Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, locNo));
|
if (null == loc) {
|
throw new RuntimeException("库位解析异常");
|
}
|
return loc.getRow();
|
}
|
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("库位解析异常");
|
}
|
|
/**
|
* 类型检测
|
* 完全检测
|
**/
|
public static boolean locMoveCheckLocTypeComplete(Loc loc, LocTypeDto dto) {
|
// 如果源库位是高库位,目标库位是低库位
|
return dto.getLocType1().equals(Integer.parseInt(loc.getType()));
|
}
|
|
public static String getCrnLoc() {
|
// SlaveProperties bean = SpringUtils.getBean(SlaveProperties.class);
|
System.out.println(doubleLocs);
|
|
return null;
|
}
|
|
|
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();
|
}
|
}
|
|
/**
|
* 获取堆垛机库位信息
|
* @param deviceBind
|
* @param area
|
* @param sourceStaNo
|
* @param matnr
|
* @param batch
|
* @param locTypeDto
|
* @param times
|
* @param ioType 作业类型(*必传参数)
|
* @return
|
*/
|
public static InTaskMsgDto getLocNoCrn(DeviceBind deviceBind, Long area, Integer sourceStaNo, String matnr, String batch, LocTypeDto locTypeDto, int times, Integer ioType) {
|
DeviceBindService deviceBindService = SpringUtils.getBean(DeviceBindService.class);
|
DeviceSiteService deviceSiteService = SpringUtils.getBean(DeviceSiteService.class);
|
LocService locService = SpringUtils.getBean(LocService.class);
|
LocItemService locItemService = SpringUtils.getBean(LocItemService.class);
|
|
if (Cools.isEmpty(matnr)) { //物料号
|
matnr = "";
|
}
|
if (Cools.isEmpty(batch)) { //批次
|
batch = "";
|
}
|
// 初始化参数
|
int channel = 0; //堆垛机号
|
int nearRow = 0; //最浅库位排
|
int curRow = 0; //最深库位排
|
int rowCount = 0; //轮询轮次
|
Loc loc = null; // 目标库位
|
|
InTaskMsgDto inTaskMsgDto = new InTaskMsgDto();
|
|
int sRow = deviceBind.getStartRow();
|
int eRow = deviceBind.getEndRow();
|
int deviceQty = deviceBind.getDeviceQty();
|
|
|
// ===============>>>> 开始执行
|
curRow = deviceBind.getCurrentRow();
|
|
//此程序用于优化堆垛机异常时的运行时间
|
for (int i = times; i <= deviceQty * 2; i++) {
|
int[] locNecessaryParameters = LocUtils.LocNecessaryParameters(deviceBind, curRow, deviceQty);
|
curRow = locNecessaryParameters[1];
|
channel = locNecessaryParameters[2];
|
rowCount = locNecessaryParameters[0];
|
nearRow = locNecessaryParameters[3];
|
break;
|
}
|
if (nearRow == 0) {
|
throw new CoolException("无可用堆垛机");
|
}
|
//入库靠近摆放
|
if (ioType == 1 && deviceBind.getBeSimilar().equals("1") && !Cools.isEmpty(matnr)) {
|
if (nearRow != curRow) {
|
List<LocItem> locItems = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getMatnrCode, matnr));
|
for (LocItem locItem : locItems) {
|
Loc loc1 = locService.getById(locItem.getLocId());
|
if (LocUtils.isShallowLoc(loc1.getCode())) {
|
continue;
|
}
|
String shallowLocNo = LocUtils.getShallowLoc(loc1.getCode());
|
// 检测目标库位是否为空库位
|
Loc shallowLoc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, shallowLocNo));
|
if (shallowLoc != null && shallowLoc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) {
|
if (LocUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
|
loc = shallowLoc;
|
channel = shallowLoc.getChannel();
|
break;
|
}
|
}
|
}
|
}
|
}
|
|
// // 靠近摆放规则 --- 空托 //互通版
|
// if (ioType == 10 && deviceBind.getEmptySimilar().equals("1")) {
|
// List<LocMast> locMasts = locMastService.selectList(new EntityWrapper<LocMast>()
|
// .eq("loc_sts", "D").ge("row1", sRow).le("row1", eRow).eq("whs_type", rowLastnoType.getType().longValue()));
|
// if (!locMasts.isEmpty()) {
|
// 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 (VersionUtils.locMoveCheckLocTypeComplete(shallowLoc, locTypeDto)) {
|
// if (basCrnpService.checkSiteError(shallowLoc.getCrnNo(), true)) {
|
// locMast = shallowLoc;
|
// crnNo = locMast.getCrnNo();
|
// break;
|
// }
|
// }
|
// }
|
// }
|
// }
|
// }
|
//查找路径
|
DeviceSite deviceSite = deviceSiteService.getOne(new LambdaQueryWrapper<DeviceSite>()
|
.eq(DeviceSite::getType, ioType)
|
.eq(DeviceSite::getSite, sourceStaNo)
|
.eq(DeviceSite::getChannel, channel)
|
);
|
if (Cools.isEmpty(deviceSite)) {
|
channel = 0;
|
} else {
|
inTaskMsgDto.setStaNo(Integer.parseInt(deviceSite.getDeviceSite()));
|
}
|
|
//更新当前排
|
deviceBind.setCurrentRow(curRow);
|
deviceBindService.updateById(deviceBind);
|
|
// 开始查找库位 ==============================>>
|
|
// 1.按规则查找库位
|
if (Cools.isEmpty(loc) && channel != 0) {
|
List<Loc> locMasts = null;
|
locMasts = locService.list(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getRow, nearRow)
|
.eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
|
.eq(Loc::getType, locTypeDto.getLocType1())
|
.eq(Loc::getAreaId, area)
|
.orderByAsc(Loc::getLev)
|
.orderByAsc(Loc::getCol)
|
);
|
for (Loc locMast1 : locMasts) {
|
if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) {
|
continue;
|
}
|
String shallowLoc = LocUtils.getDeepLoc(locMast1.getCode());
|
if ((ioType == TaskStsType.GENERATE_IN.id && deviceBind.getBeSimilar().equals("1"))) {
|
//相似物料打开,判断深库位有没有货,没货就放深库位,有货就不操作
|
Loc locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getCode, shallowLoc)
|
.eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
|
.eq(Loc::getAreaId, area)
|
);
|
if (!Cools.isEmpty(locMast2)) {
|
loc = locMast2;
|
break;
|
}
|
} else {
|
//相似物料关闭,判断深库位有没有货,有货就放浅库位,无货就不操作
|
Loc locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getCode, shallowLoc)
|
.in(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type, LocStsType.LOC_STS_TYPE_F.type)
|
.eq(Loc::getAreaId, area)
|
);
|
if (!Cools.isEmpty(locMast2)) {
|
loc = locMast1;
|
break;
|
} else {
|
locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getCode, shallowLoc)
|
.eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
|
.eq(Loc::getAreaId, area)
|
);
|
if (!Cools.isEmpty(locMast2)) {
|
loc = locMast2;
|
break;
|
}
|
}
|
}
|
}
|
if (Cools.isEmpty(loc) && deviceBind.getBeSimilar().equals("1")) {
|
for (Loc locMast1 : locMasts) {
|
if (!LocUtils.locMoveCheckLocTypeComplete(locMast1, locTypeDto)) {
|
continue;
|
}
|
if (deviceBind.getBeSimilar().equals("1")) {
|
String shallowLoc = LocUtils.getDeepLoc(locMast1.getCode());
|
Loc locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getCode, shallowLoc)
|
.eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
|
.eq(Loc::getAreaId, area)
|
);
|
if (!Cools.isEmpty(locMast2)) {
|
loc = locMast2;
|
break;
|
} else {
|
locMast2 = locService.getOne(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getCode, shallowLoc)
|
.in(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_D.type, LocStsType.LOC_STS_TYPE_D.type)
|
.eq(Loc::getAreaId, area)
|
);
|
if (!Cools.isEmpty(locMast2)) {
|
loc = locMast1;
|
break;
|
}
|
}
|
} else {
|
if (!Cools.isEmpty(locMast1)) {
|
loc = locMast1;
|
break;
|
}
|
}
|
}
|
}
|
}
|
//查询当前库位类型空库位 小于5个则locmast = null
|
List<Loc> locTypeLocMasts = locService.list(new LambdaQueryWrapper<Loc>()
|
.eq(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_O.type)
|
.eq(Loc::getChannel, channel)
|
.eq(Loc::getType, locTypeDto.getLocType1())
|
.eq(Loc::getAreaId, area)
|
);
|
if (null != locTypeLocMasts && locTypeLocMasts.size() <= 5) {
|
loc = null;
|
}
|
// 递归查询
|
if (Cools.isEmpty(loc) || !loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) {
|
// 当前巷道无空库位时,递归调整至下一巷道,检索全部巷道无果后,跳出递归
|
if (times < rowCount * 2) {
|
times = times + 1;
|
return getLocNoCrn(deviceBind, area, sourceStaNo, matnr, batch, locTypeDto, times, ioType);
|
|
}
|
// 2.库位当前所属尺寸无空库位时,调整尺寸参数,向上兼容检索库位
|
if (locTypeDto.getLocType1() < 3) {
|
int i = locTypeDto.getLocType1() + 1;
|
locTypeDto.setLocType1(i);
|
return getLocNoCrn(deviceBind, area, sourceStaNo, matnr, batch, locTypeDto, 0, ioType);
|
}
|
throw new CoolException("没有空库位");
|
}
|
String locNo = loc.getCode();
|
|
// 返回dto
|
inTaskMsgDto.setDeviceNo(channel);
|
inTaskMsgDto.setSourceStaNo(sourceStaNo);
|
// inTaskMsgDto.setStaNo();
|
inTaskMsgDto.setLocNo(locNo);
|
return inTaskMsgDto;
|
}
|
|
|
}
|