Commit 2be0d641 zshaohui

功能提交

1 个父辈 9d8a8a35
正在显示 36 个修改的文件 包含 1623 行增加95 行删除
package com.neotel.smfcore.common.utils; package com.neotel.smfcore.common.utils;
public class Constants { public class Constants {
private Constants() { private Constants() {
// hide me // hide me
} }
...@@ -213,4 +214,9 @@ public class Constants { ...@@ -213,4 +214,9 @@ public class Constants {
*/ */
public static final String Cache_AuthDate = "Cache_AuthDate"; public static final String Cache_AuthDate = "Cache_AuthDate";
/**
* 缓存料架信息
*/
public static final String Cache_ShelfInfo = "Cache_ShelfInfo";
} }
...@@ -60,6 +60,30 @@ public enum OP_STATUS { ...@@ -60,6 +60,30 @@ public enum OP_STATUS {
/** /**
* 已放到料仓门口无料盘 * 已放到料仓门口无料盘
*/ */
BOXDOOR_NOREEL BOXDOOR_NOREEL,
;
/**
* 等待取出
*/
WAITING_FOR_RETRIEVAL,
/**
* 正在出库
*/
OUTTING,
/**
* 出库完成
*/
OUTBOX,
/**
* 线体扫码位置
*/
ON_LINE,
/**
* 异常
*/
ABNORMAL;
} }
...@@ -846,7 +846,7 @@ public class DeviceController { ...@@ -846,7 +846,7 @@ public class DeviceController {
// 2024-05-18 16:55:46.593 INFO [DeviceController.java:862] - 查找到锁定的外侧库位为目标库位:20768B_02_B01_008 // 2024-05-18 16:55:46.593 INFO [DeviceController.java:862] - 查找到锁定的外侧库位为目标库位:20768B_02_B01_008
String checkOutPosName = paramMap.get("checkOutPosName"); String checkOutPosName = paramMap.get("checkOutPosName");
String needMovePosName = paramMap.get("needMovePosName"); String needMovePosName = paramMap.get("needMovePosName");
log.info("出库的库位为:"+checkOutPosName+",需要移动的库位为:"+needMovePosName); log.info("出库的库位为:" + checkOutPosName + ",需要移动的库位为:" + needMovePosName);
StoragePos checkOutPos = storagePosManager.getByPosName(checkOutPosName); StoragePos checkOutPos = storagePosManager.getByPosName(checkOutPosName);
if (checkOutPos == null) { if (checkOutPos == null) {
return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"posName", checkOutPosName}); return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"posName", checkOutPosName});
...@@ -859,8 +859,9 @@ public class DeviceController { ...@@ -859,8 +859,9 @@ public class DeviceController {
//如果barcode不为空,则提前锁定目标库位 //如果barcode不为空,则提前锁定目标库位
boolean hasReel = true; boolean hasReel = true;
Barcode barcode = needMovePos.getBarcode(); Barcode barcode = needMovePos.getBarcode();
String posName=""; String posName = "";
if (barcode != null) { if (barcode != null) {
log.info("需要移动的库位"+needMovePosName+",对应的barcode为:"+barcode.getBarcode()+",尺寸为:"+barcode.getPlateSize()+"x"+barcode.getHeight());
// Storage storage = dataCache.getStorageById(checkOutPos.getStorageId()); // Storage storage = dataCache.getStorageById(checkOutPos.getStorageId());
// ReelLockPosInfo reelLocInfo = new ReelLockPosInfo(); // ReelLockPosInfo reelLocInfo = new ReelLockPosInfo();
// reelLocInfo.setBarcode(barcode.getBarcode()); // reelLocInfo.setBarcode(barcode.getBarcode());
...@@ -871,68 +872,139 @@ public class DeviceController { ...@@ -871,68 +872,139 @@ public class DeviceController {
// log.info("提前锁定库位:" + checkOutPos.getPosName() + ",barcode为:" + barcode.getBarcode()); // log.info("提前锁定库位:" + checkOutPos.getPosName() + ",barcode为:" + barcode.getBarcode());
//有料,先查找锁定的lockS库位,有的话返回 //有料,先查找锁定的lockS库位,有的话返回
ReelLockPosInfo lockPosInfo= ReelLockPosUtil.getLockPosInfoByCode(getLockPosSKey(needMovePos.getStorageId())); ReelLockPosInfo lockPosInfo = ReelLockPosUtil.getLockPosInfoByCode(getLockPosSKey(needMovePos.getStorageId()));
if(lockPosInfo!=null&&ObjectUtil.isNotEmpty(lockPosInfo.getLockPosName())){ if (lockPosInfo != null && ObjectUtil.isNotEmpty(lockPosInfo.getLockPosName())) {
posName=lockPosInfo.getLockPosName(); posName = lockPosInfo.getLockPosName();
log.info("查找到锁定的内侧库位为目标库位:"+posName+" "); log.info("查找到锁定的内侧库位为目标库位:" + posName + " ");
} StoragePos pos = storagePosManager.getByPosName(posName);
else{ if (pos != null) {
lockPosInfo=ReelLockPosUtil.getLockPosInfoByCode(getLockPosKey(needMovePos.getStorageId())); if (pos.getW() != needMovePos.getW() || pos.getH() != needMovePos.getH()) {
if(lockPosInfo!=null&&ObjectUtil.isNotEmpty(lockPosInfo.getLockPosName())){ log.info(posName+"对应的w{},h{}与移动的宽{},高{}不一致,重新找",pos.getW(),pos.getH(),needMovePos.getW(),needMovePos.getH());
posName=lockPosInfo.getLockPosName(); posName = "";
log.info("查找到锁定的外侧库位为目标库位:"+posName+" "); }
}else{ } else {
posName = "";
}
}
//不从外侧库位进行查找
/*if (StringUtils.isEmpty(posName)) {
lockPosInfo = ReelLockPosUtil.getLockPosInfoByCode(getLockPosKey(needMovePos.getStorageId()));
if (lockPosInfo != null && ObjectUtil.isNotEmpty(lockPosInfo.getLockPosName())) {
posName = lockPosInfo.getLockPosName();
log.info("查找到锁定的外侧库位为目标库位:" + posName + " ");
StoragePos pos = storagePosManager.getByPosName(posName);
if (pos != null) {
if (pos.getW() != needMovePos.getW() || pos.getH() != needMovePos.getH()) {
log.info(posName+"对应的w{},h{}与移动的宽{},高{}不一致,重新找",pos.getW(),pos.getH(),needMovePos.getW(),needMovePos.getH());
posName = "";
}
} else {
posName = "";
}
}
}*/
if (StringUtils.isEmpty(posName)) {
//查找一个库位号 //查找一个库位号
StoragePos pos = null; StoragePos pos = null;
int loopCount=0; int loopCount = 0;
List<Storage> storageList=new ArrayList<>(); List<Storage> storageList = new ArrayList<>();
Storage storage=dataCache.getStorageById(needMovePos.getStorageId()); Storage storage = dataCache.getStorageById(needMovePos.getStorageId());
storageList.add(storage); storageList.add(storage);
List<String> cidList=new ArrayList<>(); List<String> cidList = new ArrayList<>();
cidList.add(storage.getCid()); cidList.add(storage.getCid());
while (pos == null){ while (pos == null) {
loopCount++; loopCount++;
if(loopCount>=10 ){ if (loopCount >= 10) {
log.info(barcode.getBarcode()+"已循环查找10次 直接跳出循环"); log.info(barcode.getBarcode() + "已循环查找10次 直接跳出循环");
break;
} }
pos = taskService.findEmptyPosForMoveIn(storageList, barcode, "", ""); //优先找B结束的,如果没有再找F的
if (pos == null){ String endStr = "B";
pos = taskService.findEmptyPosForMoveIn(storageList, barcode, "", "", needMovePosName, endStr);
if (pos == null) {
endStr = "F";
pos = taskService.findEmptyPosForMoveIn(storageList, barcode, "", "", needMovePosName, endStr);
}
if (pos == null) {
log.info("需要移动的库位"+needMovePosName+"未找到对应的库位信息");
break; break;
} }
//如果是以S结尾的,则判断不带S的有没有料 //如果是以S结尾的,则判断不带S的有没有料
posName = pos.getPosName(); posName = pos.getPosName();
String wPosName=""; String wPosName = "";
if (posName.endsWith("S") || posName.endsWith("s")){ if (posName.endsWith("B") || posName.endsWith("b")) {
log.info(posName+"以S结尾,需要判断外层有没有物料"); log.info(posName + "以B结尾,需要判断外层有没有物料");
wPosName = posName.substring(0,posName.length()-1); wPosName = posName.substring(0, posName.length() - 1);
wPosName = wPosName + "F";
StoragePos storagePos = storagePosManager.getByPosName(wPosName); StoragePos storagePos = storagePosManager.getByPosName(wPosName);
if (storagePos != null){ if (storagePos != null) {
if (storagePos.getBarcode() != null){ if (storagePos.getBarcode() != null) {
log.info("查找到目标库位:"+pos.getPosName()+" 的外侧库位"+wPosName+"有物料信息,重新查找库位 "); log.info("查找到目标库位:" + pos.getPosName() + " 的外侧库位" + wPosName + "有物料信息,重新查找库位 ");
ReelLockPosInfo reelLocInfo = new ReelLockPosInfo(); ReelLockPosInfo reelLocInfo = new ReelLockPosInfo();
reelLocInfo.setBarcode(pos.getId()); reelLocInfo.setBarcode(pos.getId());
reelLocInfo.setCid(dataCache.getStorageById(pos.getStorageId()).getCid()); reelLocInfo.setCid(dataCache.getStorageById(pos.getStorageId()).getCid());
reelLocInfo.setLockPosName(pos.getPosName()); reelLocInfo.setLockPosName(pos.getPosName());
reelLocInfo.setLockPosId(pos.getId()); reelLocInfo.setLockPosId(pos.getId());
ReelLockPosUtil.addReelLockPosInfo(reelLocInfo,cidList); ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, cidList);
pos = null; pos = null;
posName=""; posName = "";
}else { } else {
log.info("查找到目标库位:"+pos.getPosName()+" 且外侧库位" + wPosName + "无料,锁定两个库位 :" + pos.getPosName() + "=" + log.info("查找到目标库位:" + pos.getPosName() + " 且外侧库位" + wPosName + "无料,锁定两个库位 :" + pos.getPosName() + "=" +
getLockPosSKey(needMovePos.getStorageId()) + ",wPosName=" + getLockPosKey(needMovePos.getStorageId())); getLockPosSKey(needMovePos.getStorageId()) + ",wPosName=" + getLockPosKey(needMovePos.getStorageId()));
//是内侧库位,且外侧库位也无料,锁定两个库位 //是内侧库位,且外侧库位也无料,锁定两个库位
AddLock(pos,getLockPosSKey(needMovePos.getStorageId()),cidList); AddLock(pos, getLockPosSKey(needMovePos.getStorageId()), cidList);
AddLock(storagePos, getLockPosKey(needMovePos.getStorageId()), cidList);
//如果外侧有任务,则改成新库位一样的
DataLog dataLog = null;
for (DataLog queueTask : taskService.getQueueTasks()) {
if (barcode.getBarcode().equals(queueTask)) {
dataLog = queueTask;
break;
}
}
if (dataLog != null) {
log.info("posName:[{}],barcode为[{}]有任务,需要重新设置任务库位:[{}]", dataLog.getPosName(), barcode.getBarcode(), pos.getPosName());
dataLog.setPosName(pos.getPosName());
dataLog.setPosId(pos.getId());
if (dataLog.isExecuting() || dataLog.isWait()) {
dataLog.setStatus(OP_STATUS.WAIT.name());
taskService.updateQueueTask(dataLog);
} else {
taskService.updateFinishedTask(dataLog);
}
}
AddLock(storagePos,getLockPosKey(needMovePos.getStorageId()),cidList);
} }
} }
}else { } else {
//是外侧库位,直接锁定外侧库位 //是外侧库位,直接锁定外侧库位
log.info("查找到外侧库位作为目标库位,锁定库位 :" + pos.getPosName() + "=" + getLockPosKey(needMovePos.getStorageId())); log.info("查找到外侧库位作为目标库位,锁定库位 :" + pos.getPosName() + "=" + getLockPosKey(needMovePos.getStorageId()));
AddLock(pos,getLockPosKey(needMovePos.getStorageId()),cidList); AddLock(pos, getLockPosKey(needMovePos.getStorageId()), cidList);
//如果外侧有任务,则改成新库位一样的
DataLog dataLog = null;
for (DataLog queueTask : taskService.getQueueTasks()) {
if (barcode.getBarcode().equals(queueTask)) {
dataLog = queueTask;
break;
}
}
if (dataLog != null) {
log.info("posName:[{}],barcode为[{}]有任务,需要重新设置任务库位:[{}]", dataLog.getPosName(), barcode.getBarcode(), pos.getPosName());
dataLog.setPosName(pos.getPosName());
dataLog.setPosId(pos.getId());
if (dataLog.isExecuting() || dataLog.isWait()) {
dataLog.setStatus(OP_STATUS.WAIT.name());
taskService.updateQueueTask(dataLog);
} else {
taskService.updateFinishedTask(dataLog);
}
}
} }
} }
} }
...@@ -940,25 +1012,25 @@ public class DeviceController { ...@@ -940,25 +1012,25 @@ public class DeviceController {
//然后找lock库位,有的话返回 //然后找lock库位,有的话返回
//没库位查找一个库位,如果是里面的,判断外面需要没料 //没库位查找一个库位,如果是里面的,判断外面需要没料
//如果是外面的锁定为Lock //如果是外面的锁定为Lock
} else { else {
hasReel = false; hasReel = false;
} }
Map<String, Object> resultMap = new HashMap<>(); Map<String, Object> resultMap = new HashMap<>();
resultMap.put("hasReel", hasReel); resultMap.put("hasReel", hasReel);
if (hasReel){ if (hasReel) {
resultMap.put("barcode", barcode.getBarcode()); resultMap.put("barcode", barcode.getBarcode());
resultMap.put("partNumber",barcode.getPartNumber()); resultMap.put("partNumber", barcode.getPartNumber());
if(ObjectUtil.isEmpty(posName)){ if (ObjectUtil.isEmpty(posName)) {
return ResultBean.newErrorResult(-1, "smfcore.shelf.msg.inError", "未找到适合[{0}]的库位", new String[]{"posName", needMovePosName}); return ResultBean.newErrorResult(-1, "smfcore.shelf.msg.inError", "未找到适合[{0}]的库位", new String[]{needMovePosName});
}else{ } else {
resultMap.put("posName", posName); resultMap.put("posName", posName);
} }
} }
return ResultBean.newOkResult(resultMap); return ResultBean.newOkResult(resultMap);
} }
private void AddLock(StoragePos pos,String key,List<String> cidList) { private void AddLock(StoragePos pos,String key,List<String> cidList) {
ReelLockPosInfo lockS = new ReelLockPosInfo(); ReelLockPosInfo lockS = new ReelLockPosInfo();
lockS.setBarcode(key); lockS.setBarcode(key);
...@@ -977,19 +1049,28 @@ public class DeviceController { ...@@ -977,19 +1049,28 @@ public class DeviceController {
String targetPosName = paramMap.get("targetPosName"); //目标库位 String targetPosName = paramMap.get("targetPosName"); //目标库位
log.info("需要移动的库位为:" + needMovePosName + ",目标库位为:" + targetPosName); log.info("需要移动的库位为:" + needMovePosName + ",目标库位为:" + targetPosName);
//判断目标库位是否存在
StoragePos targetPos = storagePosManager.getByPosName(targetPosName);
if (targetPos == null) {
return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"posName", targetPosName});
}
Barcode targetBarcode = targetPos.getBarcode();
//判断有没有物料 //判断有没有物料
StoragePos needMovePos = storagePosManager.getByPosName(needMovePosName); StoragePos needMovePos = storagePosManager.getByPosName(needMovePosName);
Barcode barcode = needMovePos.getBarcode(); Barcode barcode = needMovePos.getBarcode();
if (barcode == null) {
//如果目标库位不为空,当前库位为空,直接返回ok
if (barcode == null ) {
if (targetBarcode == null) {
return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{needMovePosName, "barcode"}); return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{needMovePosName, "barcode"});
} else {
return ResultBean.newOkResult("");
} }
//判断目标库位是否存在
StoragePos targetPos = storagePosManager.getByPosName(targetPosName);
if (targetPos == null) {
return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"posName", targetPosName});
} }
//把外侧相同的任务给改成内侧的 //把外侧相同的任务给改成内侧的
List<DataLog> allTasks = taskService.getAllTasks(); List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) { for (DataLog dataLog : allTasks) {
...@@ -1020,9 +1101,11 @@ public class DeviceController { ...@@ -1020,9 +1101,11 @@ public class DeviceController {
dataCache.updateInventory(needMovePos, barcode); dataCache.updateInventory(needMovePos, barcode);
//生成一条入库任务 //重新设置barcode的库位
barcode.setPosName(targetPos.getPosName()); barcode.setPosName(targetPos.getPosName());
barcodeManager.save(barcode); barcodeManager.save(barcode);
//生成一条入库任务
DataLog targetPosTask = new DataLog(storage, barcode, targetPos); DataLog targetPosTask = new DataLog(storage, barcode, targetPos);
targetPosTask.setOperator("admin-move"); targetPosTask.setOperator("admin-move");
targetPosTask.setType(OP.PUT_IN); targetPosTask.setType(OP.PUT_IN);
...@@ -1051,12 +1134,12 @@ public class DeviceController { ...@@ -1051,12 +1134,12 @@ public class DeviceController {
if ( lock == null) { if ( lock == null) {
if (needMovePosName.endsWith("S") || needMovePosName.endsWith("s")) { if (needMovePosName.endsWith("F") || needMovePosName.endsWith("f")) {
log.info("需要移动的库位为:" + needMovePosName + "是内侧库位,不需要锁定库位"); log.info("需要移动的库位为:" + needMovePosName + "是内侧库位,不需要锁定库位");
} else { } else {
needMovePosName = needMovePosName.substring(0,needMovePosName.length()-1);
String sPosname = needMovePosName + "S"; String sPosname = needMovePosName + "B";
StoragePos sPos = storagePosManager.getByPosName(sPosname); StoragePos sPos = storagePosManager.getByPosName(sPosname);
if (sPos != null) { if (sPos != null) {
String cid = dataCache.getStorageById(sPos.getStorageId()).getCid(); String cid = dataCache.getStorageById(sPos.getStorageId()).getCid();
......
...@@ -28,6 +28,9 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos; ...@@ -28,6 +28,9 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog; import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.DevicesStatusUtil; import com.neotel.smfcore.core.system.util.DevicesStatusUtil;
import com.neotel.smfcore.core.system.util.TaskService; import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfInfo;
import com.neotel.smfcore.custom.zhongche1568.enums.ZhongCheOrderLoc;
import com.neotel.smfcore.custom.zhongche1568.enums.ZhongCheOrderType;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -475,6 +478,8 @@ public class LiteOrderCache { ...@@ -475,6 +478,8 @@ public class LiteOrderCache {
return checkOutOrder(cacheOrder).getMsgKey(); return checkOutOrder(cacheOrder).getMsgKey();
} }
//缓存料架信息
Map<Integer, ShelfInfo> cacheShelfInfoMap = new HashMap<>();
log.info("开始执行工单[" + orderNo + "] outBom=" + outBom); log.info("开始执行工单[" + orderNo + "] outBom=" + outBom);
cacheOrder.setTaskReelCount(0); cacheOrder.setTaskReelCount(0);
...@@ -494,6 +499,8 @@ public class LiteOrderCache { ...@@ -494,6 +499,8 @@ public class LiteOrderCache {
return "smfcore.order.out.noTask"; return "smfcore.order.out.noTask";
} }
String type = cacheOrder.getType();
List<String> availableStorageIds = dataCache.getAvailableStorageIds(cidList); List<String> availableStorageIds = dataCache.getAvailableStorageIds(cidList);
boolean shortage=false; boolean shortage=false;
...@@ -552,8 +559,62 @@ public class LiteOrderCache { ...@@ -552,8 +559,62 @@ public class LiteOrderCache {
assignReelCount = assignReelCount + 1; assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1; taskReelCount = taskReelCount + 1;
log.info("工单[" + orderNo + "],任务数[" + taskReelCount + "]出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + partNumber + "] num:" + pos.getBarcode().getAmount()); log.info("工单[" + orderNo + "],任务数[" + taskReelCount + "]出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + partNumber + "] num:" + pos.getBarcode().getAmount());
DataLog task = newTask(pos) ;
//首套出到皮带线,补料出到对应的料架
String locInfo = "";
if (ZhongCheOrderType.FIRST.equals(type)){
locInfo = orderNo+"-"+ZhongCheOrderLoc.BELTLINE;
} else if (ZhongCheOrderType.REMAINING.equals(type)) {
//判断是大料盘还是小料盘
Barcode barcode = pos.getBarcode();
boolean bigReel = false;
if (barcode.getPlateSize() > 7) {
bigReel = true;
}
if (cacheShelfInfoMap.isEmpty()) {
cacheShelfInfoMap.put(1, new ShelfInfo());
}
//判断是否有料架信息
int hasCapacityshelf = 0;
for (int shelfNo : cacheShelfInfoMap.keySet()) {
ShelfInfo shelfInfo = cacheShelfInfoMap.get(shelfNo);
if (bigReel) {
if (shelfInfo.hasBigCapacity()) {
hasCapacityshelf = shelfNo;
break;
}
} else {
if (shelfInfo.hasSmallCapacity()) {
hasCapacityshelf = shelfNo;
break;
}
}
}
if (hasCapacityshelf > 0) {
ShelfInfo shelfInfo = cacheShelfInfoMap.get(hasCapacityshelf);
if (bigReel) {
shelfInfo.setBigReelCount(shelfInfo.getBigReelCount() + 1);
} else {
shelfInfo.setSmallReelCount(shelfInfo.getSmallReelCount() + 1);
}
locInfo = orderNo+"-"+hasCapacityshelf;
cacheShelfInfoMap.put(hasCapacityshelf,shelfInfo);
} else {
//新创建一个料架出来
int maxShelfNo = Collections.max(cacheShelfInfoMap.keySet());
maxShelfNo = maxShelfNo + 1;
ShelfInfo shelfInfo = new ShelfInfo();
if (bigReel) {
shelfInfo.setBigReelCount(shelfInfo.getBigReelCount() + 1);
} else {
shelfInfo.setSmallReelCount(shelfInfo.getSmallReelCount() + 1);
}
locInfo = orderNo+"-"+maxShelfNo;
cacheShelfInfoMap.put(maxShelfNo,shelfInfo);
}
}
DataLog task = newTask(pos) ;
task.setSourceId(cacheOrder.getId()); task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo()); task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId()); task.setSubSourceId(orderItem.getId());
...@@ -563,6 +624,9 @@ public class LiteOrderCache { ...@@ -563,6 +624,9 @@ public class LiteOrderCache {
task.setStatus(OP_STATUS.WAIT.name()); task.setStatus(OP_STATUS.WAIT.name());
task.setSingleOut(singleOut); task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine()); task.setLine(cacheOrder.getLine());
task.setLocInfo(locInfo);
task.setSo(cacheOrder.getSo());
task.setSoltNum(orderItem.getSlotNum());
// task = dataLogDao.save(task); // task = dataLogDao.save(task);
taskService.addTaskToExecute(task); taskService.addTaskToExecute(task);
} }
......
...@@ -65,6 +65,14 @@ public class DefaultOrderFileListener implements IOrderFileListener { ...@@ -65,6 +65,14 @@ public class DefaultOrderFileListener implements IOrderFileListener {
LiteOrder liteOrder = new LiteOrder(so, liteOrderItems); LiteOrder liteOrder = new LiteOrder(so, liteOrderItems);
liteOrder.setSource(fileName); liteOrder.setSource(fileName);
liteOrder.setSourceType(sourceType);//0=手动创建,1=共享文件夹 liteOrder.setSourceType(sourceType);//0=手动创建,1=共享文件夹
for (LiteOrderItem item : liteOrderItems) {
if (StringUtils.isNotEmpty(item.getOrderType())){
liteOrder.setType(item.getOrderType());
break;
}
}
LiteOrder dbOrder = liteOrderManager.findByOrderNo(liteOrder.getOrderNo()); LiteOrder dbOrder = liteOrderManager.findByOrderNo(liteOrder.getOrderNo());
if (dbOrder != null) { if (dbOrder != null) {
...@@ -118,6 +126,7 @@ public class DefaultOrderFileListener implements IOrderFileListener { ...@@ -118,6 +126,7 @@ public class DefaultOrderFileListener implements IOrderFileListener {
int soIndex = csvRead.getIndex("SO", orderSetting.getSo()); int soIndex = csvRead.getIndex("SO", orderSetting.getSo());
int numIndex = csvRead.getIndex("NUM", orderSetting.getNum()); int numIndex = csvRead.getIndex("NUM", orderSetting.getNum());
int mpnIndex = csvRead.getIndex("MPN", orderSetting.getMpn()); int mpnIndex = csvRead.getIndex("MPN", orderSetting.getMpn());
int orderTypeIndex = csvRead.getIndex("ORDERTYPE", orderSetting.getOrderType());
//附加字段读取 //附加字段读取
Map<String,Integer> appendIndexMap=new HashMap<>(); Map<String,Integer> appendIndexMap=new HashMap<>();
...@@ -188,6 +197,15 @@ public class DefaultOrderFileListener implements IOrderFileListener { ...@@ -188,6 +197,15 @@ public class DefaultOrderFileListener implements IOrderFileListener {
} }
} }
} }
String orderType = "";
if (orderTypeIndex != -1){
String orderTypeStr = lineValues[orderTypeIndex];
if (StringUtils.isNotEmpty(orderTypeStr)){
orderType = orderTypeStr;
}
}
LiteOrderItem item = new LiteOrderItem(); LiteOrderItem item = new LiteOrderItem();
item.setPn(partNumber); item.setPn(partNumber);
item.setNeedReelCount(count); item.setNeedReelCount(count);
...@@ -199,7 +217,7 @@ public class DefaultOrderFileListener implements IOrderFileListener { ...@@ -199,7 +217,7 @@ public class DefaultOrderFileListener implements IOrderFileListener {
item.setFeederInfo(feeder); item.setFeederInfo(feeder);
item.setRi(ri); item.setRi(ri);
item.setMpn(mpn); item.setMpn(mpn);
item.setOrderType(orderType);
Map<String,String> appendValue=new HashMap<>(); Map<String,String> appendValue=new HashMap<>();
if(appendIndexMap.size()>0){ if(appendIndexMap.size()>0){
for (String key : for (String key :
......
...@@ -22,4 +22,6 @@ public interface ILiteOrderManager extends IBaseManager<LiteOrder> { ...@@ -22,4 +22,6 @@ public interface ILiteOrderManager extends IBaseManager<LiteOrder> {
LiteOrder findBySource(String source); LiteOrder findBySource(String source);
List<String> findAllLines(); List<String> findAllLines();
LiteOrder findOneByOrderNo(String orderNo);
} }
...@@ -123,6 +123,11 @@ public class LiteOrderManagerImpl implements ILiteOrderManager { ...@@ -123,6 +123,11 @@ public class LiteOrderManagerImpl implements ILiteOrderManager {
} }
@Override @Override
public LiteOrder findOneByOrderNo(String orderNo) {
return liteOrderDao.findOne(new Query(Criteria.where("orderNo").is(orderNo)));
}
@Override
public PageData<LiteOrder> findByPage(Query query, Pageable pageable) { public PageData<LiteOrder> findByPage(Query query, Pageable pageable) {
int totalCount = liteOrderDao.countByQuery(query); int totalCount = liteOrderDao.countByQuery(query);
List<LiteOrder> list = liteOrderDao.findByQuery(query, pageable); List<LiteOrder> list = liteOrderDao.findByQuery(query, pageable);
......
...@@ -94,6 +94,11 @@ public class LiteOrder extends BasePo implements Serializable { ...@@ -94,6 +94,11 @@ public class LiteOrder extends BasePo implements Serializable {
private float orderTimes = 1f; private float orderTimes = 1f;
/** /**
* 类型
*/
private String type;
/**
* 订单的详细信息 * 订单的详细信息
*/ */
@Transient @Transient
......
...@@ -98,6 +98,8 @@ public class LiteOrderItem extends BasePo implements Serializable ,Comparable<Li ...@@ -98,6 +98,8 @@ public class LiteOrderItem extends BasePo implements Serializable ,Comparable<Li
*/ */
private String barcodeStr = ""; private String barcodeStr = "";
private String orderType = "";
/** /**
* 自定义的附加字段,key=字段名,value=值 * 自定义的附加字段,key=字段名,value=值
*/ */
......
...@@ -47,6 +47,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> { ...@@ -47,6 +47,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
StoragePos getEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String lastPosId) throws ValidateException; StoragePos getEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String lastPosId) throws ValidateException;
StoragePos getEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String lastPosId, String needMovePosName, String endStr) throws ValidateException;
StoragePos getEmptyPosByStorage(Storage storage, int size, int height, Collection<String> excludePosIds) throws ValidateException; StoragePos getEmptyPosByStorage(Storage storage, int size, int height, Collection<String> excludePosIds) throws ValidateException;
List<StoragePos> findNotEmpty(); List<StoragePos> findNotEmpty();
...@@ -96,4 +98,6 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> { ...@@ -96,4 +98,6 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
StoragePos findOne(Query query); StoragePos findOne(Query query);
Sort getSortByCheckOutType(CHECKOUT_TYPE checkoutType); Sort getSortByCheckOutType(CHECKOUT_TYPE checkoutType);
int getRemainPosCountByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String s, String f);
} }
...@@ -9,6 +9,7 @@ import com.neotel.smfcore.common.bean.PageData; ...@@ -9,6 +9,7 @@ import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.exception.ValidateException; import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.DateUtil; import com.neotel.smfcore.common.utils.DateUtil;
import com.neotel.smfcore.common.utils.PointUtil; import com.neotel.smfcore.common.utils.PointUtil;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.barcode.bean.PlateSizeBean; import com.neotel.smfcore.core.barcode.bean.PlateSizeBean;
import com.neotel.smfcore.core.barcode.service.po.Barcode; import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.storage.bean.InventoryItem; import com.neotel.smfcore.core.storage.bean.InventoryItem;
...@@ -360,6 +361,38 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -360,6 +361,38 @@ public class StoragePosManagerImpl implements IStoragePosManager {
} }
@Override @Override
public int getRemainPosCountByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String s, String endStr) {
Criteria c = Criteria.where("storageId").is(storage.getId());
COMPATIBLE_TYPE compatibleType = storage.getCompatibleType();
if (compatibleType == COMPATIBLE_TYPE.EXACT_MATCH) {//完全匹配
c = c.and("w").is(barcode.getPlateSize()).and("h").is(barcode.getHeight());
} else if (compatibleType == COMPATIBLE_TYPE.FULLY_COMPATIBLE) {//同厚度兼容
c = c.and("w").gte(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//除7寸外,完全兼容
} else if (compatibleType == COMPATIBLE_TYPE.SIZE_COMPATIBLE) {//同尺寸兼容
c = c.and("w").is(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//宽度等于料盘宽度,高度大于等于料盘高度
}
c = c.and("enabled").is(true)//可用
.and("used").is(false);//未使用
//去除的仓位
if (excludePosIds != null && !excludePosIds.isEmpty()) {
c = c.and("id").nin(excludePosIds);
}
if (StringUtils.isNotEmpty(endStr)) {
String regex = "" + endStr + "$";
c.and("posName").regex(Pattern.compile(regex));
}
Query query = new Query(c);
query.with(Sort.by(Sort.Direction.ASC, "w").and(Sort.by(Sort.Direction.ASC, "h")).and(Sort.by(Sort.Direction.DESC, "priority")));
return storagePosDao.countByQuery(query);
}
@Override
public PageData<StoragePos> findByPage(Query query, Pageable pageable) { public PageData<StoragePos> findByPage(Query query, Pageable pageable) {
int totalCount = storagePosDao.countByQuery(query); int totalCount = storagePosDao.countByQuery(query);
List<StoragePos> list = storagePosDao.findByQuery(query, pageable); List<StoragePos> list = storagePosDao.findByQuery(query, pageable);
...@@ -496,6 +529,57 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -496,6 +529,57 @@ public class StoragePosManagerImpl implements IStoragePosManager {
return pos; return pos;
} }
@Override
public StoragePos getEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String lastPosId, String needMovePosName, String endStr) throws ValidateException {
Criteria c = Criteria.where("storageId").is(storage.getId());
COMPATIBLE_TYPE compatibleType = storage.getCompatibleType();
if (compatibleType == COMPATIBLE_TYPE.EXACT_MATCH) {//完全匹配
c = c.and("w").is(barcode.getPlateSize()).and("h").is(barcode.getHeight());
} else if (compatibleType == COMPATIBLE_TYPE.FULLY_COMPATIBLE) {//同厚度兼容
c = c.and("w").gte(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//除7寸外,完全兼容
} else if (compatibleType == COMPATIBLE_TYPE.SIZE_COMPATIBLE) {//同尺寸兼容
c = c.and("w").is(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//宽度等于料盘宽度,高度大于等于料盘高度
}
c = c.and("enabled").is(true)//可用
.and("used").is(false);//未使用
//去除的仓位
if (excludePosIds != null && !excludePosIds.isEmpty()) {
c = c.and("id").nin(excludePosIds);
}
if (StringUtils.isNotEmpty(needMovePosName) && StringUtils.isNotEmpty(endStr)) {
Criteria posNameCriteria = new Criteria();
String regex = ""+endStr+"$";
posNameCriteria.andOperator(Criteria.where("posName").ne(needMovePosName), Criteria.where("posName").regex(Pattern.compile(regex)));
c.andOperator(posNameCriteria);
}
Query query = new Query(c);
String msg = "";
// if (lastPosId == null || lastPosId.equals("")) {
//优先放入最合适的位置(根据尺寸),相同尺寸按优先级排序
query.with(Sort.by(Sort.Direction.ASC, "w").and(Sort.by(Sort.Direction.ASC, "h")).and(Sort.by(Sort.Direction.DESC, "priority")));
// } else {
// Point point = PointUtil.getPosPoint(lastPosId, false);
// query.addCriteria(Criteria.where("coordinate").nearSphere(point));
// msg += "getEmptyPosByStorage 根据就近坐标查询[" + lastPosId + "][" + point.getX() + "," + point.getY() + "]";
// }
StoragePos pos = storagePosDao.findOne(query);
if ((!ObjectUtil.isNotEmpty(msg) )&& (pos != null)) {
Point targetP = PointUtil.getPosPoint(lastPosId, false);
log.debug(msg + "结果:[" + pos.getPosName() + "][" + targetP.getX() + "," + targetP.getY() + "]");
}
return pos;
}
@Override @Override
public StoragePos getEmptyPosByStorage(Storage storage, int size,int height, Collection<String> excludePosIds ) throws ValidateException { public StoragePos getEmptyPosByStorage(Storage storage, int size,int height, Collection<String> excludePosIds ) throws ValidateException {
......
...@@ -29,6 +29,8 @@ public class OrderSetting implements Serializable { ...@@ -29,6 +29,8 @@ public class OrderSetting implements Serializable {
public String mpn="MPN"; public String mpn="MPN";
public String orderType = "ORDERTYPE";
/** /**
* 自定义的附加字段,key=字段名,value=表头名称 * 自定义的附加字段,key=字段名,value=表头名称
*/ */
......
...@@ -238,6 +238,7 @@ public class SettingsController { ...@@ -238,6 +238,7 @@ public class SettingsController {
titles.add(orderSetting.getSo()); titles.add(orderSetting.getSo());
titles.add(orderSetting.getNum()); titles.add(orderSetting.getNum());
titles.add(orderSetting.getMpn()); titles.add(orderSetting.getMpn());
titles.add(orderSetting.getOrderType());
for(int i=1;i<=10;i++) { for(int i=1;i<=10;i++) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
...@@ -249,6 +250,7 @@ public class SettingsController { ...@@ -249,6 +250,7 @@ public class SettingsController {
map.put(orderSetting.getSo(),"WO1001" ); map.put(orderSetting.getSo(),"WO1001" );
map.put(orderSetting.getNum(),i); map.put(orderSetting.getNum(),i);
map.put(orderSetting.getMpn(),"MPN"+i); map.put(orderSetting.getMpn(),"MPN"+i);
map.put(orderSetting.getOrderType(),"First/Remaining");
} }
else{ else{
map.put(orderSetting.getPn(),"PN2"+i); map.put(orderSetting.getPn(),"PN2"+i);
...@@ -258,6 +260,7 @@ public class SettingsController { ...@@ -258,6 +260,7 @@ public class SettingsController {
map.put(orderSetting.getSo(),"WO1002" ); map.put(orderSetting.getSo(),"WO1002" );
map.put(orderSetting.getNum(),i); map.put(orderSetting.getNum(),i);
map.put(orderSetting.getMpn(),"MPN"+i); map.put(orderSetting.getMpn(),"MPN"+i);
map.put(orderSetting.getOrderType(),"First/Remaining");
} }
maps.add(map); maps.add(map);
} }
......
...@@ -10,6 +10,7 @@ import com.neotel.smfcore.core.device.enums.OP_STATUS; ...@@ -10,6 +10,7 @@ import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.storage.service.po.Storage; import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos; import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.bean.MSDAppendInfo; import com.neotel.smfcore.core.system.bean.MSDAppendInfo;
import io.swagger.models.auth.In;
import lombok.Data; import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Document;
...@@ -252,6 +253,11 @@ public class DataLog extends BasePo implements Serializable ,Comparable<DataLog> ...@@ -252,6 +253,11 @@ public class DataLog extends BasePo implements Serializable ,Comparable<DataLog>
//是否关闭 //是否关闭
private boolean closed = false; private boolean closed = false;
private boolean outFromPos = false;
private Integer soltNum;
private String so;
public String getBarcode() { public String getBarcode() {
if(barcode == null){ if(barcode == null){
......
...@@ -809,7 +809,7 @@ public class TaskService { ...@@ -809,7 +809,7 @@ public class TaskService {
* @param barcode * @param barcode
* @return * @return
*/ */
public StoragePos findEmptyPosForMoveIn(List<Storage> storageList, Barcode barcode, String inRFID, String lastPosId) throws ValidateException { public StoragePos findEmptyPosForMoveIn(List<Storage> storageList, Barcode barcode, String inRFID, String lastPosId,String needMovePosName,String endStr) throws ValidateException {
Collection<DataLog> queueTasks = getQueueTasks(); Collection<DataLog> queueTasks = getQueueTasks();
List<DataLog> allTasksa = getFinishedTasks(); List<DataLog> allTasksa = getFinishedTasks();
if (!queueTasks.isEmpty()) { if (!queueTasks.isEmpty()) {
...@@ -842,11 +842,11 @@ public class TaskService { ...@@ -842,11 +842,11 @@ public class TaskService {
//如果有正在执行的任务,把库位发过去 //如果有正在执行的任务,把库位发过去
Collection<DataLog> allTasks = taskMap.values(); Collection<DataLog> allTasks = taskMap.values();
for (DataLog task : allTasks) { for (DataLog task : allTasks) {
if (barcode.getBarcode().equals(task.getBarcode())) { /*if (barcode.getBarcode().equals(task.getBarcode())) {
String posId = task.getPosId(); String posId = task.getPosId();
log.info(barcode.getBarcode() + " 已有任务,返回任务中的库位:" + task.getPosName()); log.info(barcode.getBarcode() + " 已有任务,返回任务中的库位:" + task.getPosName());
return storagePosManager.get(posId); return storagePosManager.get(posId);
} }*/
String storageId = task.getStorageId(); String storageId = task.getStorageId();
if (!Strings.isNullOrEmpty(storageId)) { if (!Strings.isNullOrEmpty(storageId)) {
...@@ -915,12 +915,15 @@ public class TaskService { ...@@ -915,12 +915,15 @@ public class TaskService {
} }
}); });
return findEmptyPosInStorages(barcode, availbleStorageList, hasOutTaskStorageIds, lastPosId); return findEmptyPosInStorages(barcode, availbleStorageList, hasOutTaskStorageIds, lastPosId,needMovePosName,endStr);
}
private synchronized StoragePos findEmptyPosInStorages(Barcode barcode, List<Storage> availbleStorageList, final Set<String> hasOutTaskStorageIds, String lastPosId){
return findEmptyPosInStorages(barcode,availbleStorageList,hasOutTaskStorageIds,lastPosId,"","");
} }
private synchronized StoragePos findEmptyPosInStorages(Barcode barcode, List<Storage> availbleStorageList, final Set<String> hasOutTaskStorageIds, String lastPosId) { private synchronized StoragePos findEmptyPosInStorages(Barcode barcode, List<Storage> availbleStorageList, final Set<String> hasOutTaskStorageIds, String lastPosId,String needMovePosName,String endStr) {
StoragePos findPos=null;
//第一遍查找,先不查找有出库任务的料仓 //第一遍查找,先不查找有出库任务的料仓
for (Storage storage : availbleStorageList) { for (Storage storage : availbleStorageList) {
if(!storage.isSmdDuo()){//DUO料仓无论是否有出库任务,都可以查找空库位 if(!storage.isSmdDuo()){//DUO料仓无论是否有出库任务,都可以查找空库位
...@@ -931,19 +934,9 @@ public class TaskService { ...@@ -931,19 +934,9 @@ public class TaskService {
try { try {
Collection<String> operatingPosIds = excludePosIds(); Collection<String> operatingPosIds = excludePosIds();
log.debug("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位"); log.debug("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位");
StoragePos pos = storagePosManager.getEmptyPosByStorage(storage, barcode, operatingPosIds, lastPosId); StoragePos pos = storagePosManager.getEmptyPosByStorage(storage, barcode, operatingPosIds, lastPosId,needMovePosName,endStr);
if (pos != null) { if (pos != null) {
//判断尺寸是否一致
if(isSameSize(barcode,pos)){
log.info("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找到空位["+pos.getPosName()+"],尺寸与条码一致,直接返回");
return pos; return pos;
}else if(findPos==null){
log.info("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找到空位["+pos.getPosName()+"],尺寸不一致,先暂存库位");
findPos=pos;
}else if(findPos.getW()> pos.getW()||findPos.getH()>pos.getH()){
log.info("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找到空位["+pos.getPosName()+"],比暂存库位["+findPos.getPosName()+"]跟匹配,替换为暂存库位");
findPos=pos;
}
} }
} catch (Exception e) { } catch (Exception e) {
log.error("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位失败:" + e.getMessage()); log.error("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位失败:" + e.getMessage());
...@@ -954,27 +947,14 @@ public class TaskService { ...@@ -954,27 +947,14 @@ public class TaskService {
try { try {
Collection<String> operatingPosIds = excludePosIds(); Collection<String> operatingPosIds = excludePosIds();
log.debug("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位"); log.debug("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位");
StoragePos pos = storagePosManager.getEmptyPosByStorage(storage, barcode, operatingPosIds, lastPosId); StoragePos pos = storagePosManager.getEmptyPosByStorage(storage, barcode, operatingPosIds, lastPosId,needMovePosName,endStr);
if (pos != null) { if (pos != null) {
if(isSameSize(barcode,pos)){
log.info("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找到空位["+pos.getPosName()+"],尺寸与条码一致,直接返回");
return pos; return pos;
}else if(findPos==null){
log.info("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找到空位["+pos.getPosName()+"],尺寸不一致,先暂存库位");
findPos=pos;
}else if(findPos.getW()> pos.getW()||findPos.getH()>pos.getH()){
log.info("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找到空位["+pos.getPosName()+"],比暂存库位["+findPos.getPosName()+"]跟匹配,替换为暂存库位");
findPos=pos;
}
} }
} catch (Exception e) { } catch (Exception e) {
log.error("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位失败:" + e.getMessage()); log.error("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位失败:" + e.getMessage());
} }
} }
if(findPos!=null){
log.info("为[" + barcode.getBarcode() + "]未查找到尺寸一直的库位,返回暂存的库位["+findPos.getPosName()+"]");
return findPos;
}
try { try {
String cids = ""; String cids = "";
for (Storage storage : availbleStorageList) { for (Storage storage : availbleStorageList) {
......
package com.neotel.smfcore.custom.zhongche1568;
import com.alibaba.fastjson.JSONObject;
import com.neotel.smfcore.common.exception.ApiException;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.HttpHelper;
import com.neotel.smfcore.core.api.listener.BaseSmfApiListener;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.custom.zhongche1568.bean.api.MaterialCountResult;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfInfo;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfLocInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class ZhongcheApi extends BaseSmfApiListener {
@Value("${api.materialCountUrl}")
private String materialCountUrl;
@Value("${api.postCountDataUrl}")
private String postCountDataUrl;
@Value("${api.shelfFullNotificationUrl}")
private String shelfFullNotificationUrl;
@Override
public boolean isForThisApi(String apiName) {
return "1568".equals(apiName);
}
@Override
public LiteOrder fetchOrder(String fetchOrderUrl, String orderNumber, String username) {
return super.fetchOrder(fetchOrderUrl, orderNumber, username);
}
@Override
public void inTaskStatusChange(String inNotifyUrl, DataLog task) {
if (task.isFinished()) {
String barcode = task.getBarcode();
String posName = task.getPosName();
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("reelId", barcode);
paramMap.put("location", posName);
log.info("入库完成,reelId为:" + barcode + ",库位信息为:" + posName + ",地址为:" + inNotifyUrl);
try {
String result = HttpHelper.postJson(inNotifyUrl, paramMap);
log.info(barcode + "入完完成,返回结果为:" + result);
} catch (ApiException e) {
e.printStackTrace();
}
}
}
public MaterialCountResult materialCount(String reelId, String fullCode) {
log.info("判断是否点料,reelId为:" + reelId + ",fullCode为:" + fullCode + ",地址为:" + materialCountUrl);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("reelId", reelId);
paramMap.put("fullCode", fullCode);
try {
String result = HttpHelper.postJson(materialCountUrl, paramMap);
JSONObject resultObj = JSONObject.parseObject(result);
Integer code = resultObj.getInteger("code");
if (code != 0) {
String msg = resultObj.getString("msg");
throw new ValidateException("smfcore.barcode.checkError", "[{0}]", new String[]{msg});
}
return resultObj.getObject("data", MaterialCountResult.class);
} catch (Exception e) {
throw new ValidateException("smfcore.barcode.checkNg", "验证失败:{0}", new String[]{e.getMessage()});
}
}
public void postCountData(String reelId, int countQty) {
log.info("判断是否点料,reelId为:" + reelId + ",数量为:" + countQty + ",地址为:" + postCountDataUrl);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("reelId", reelId);
paramMap.put("countQty", countQty);
String result = "";
try {
result = HttpHelper.postJson(postCountDataUrl, paramMap);
JSONObject resultObj = JSONObject.parseObject(result);
Integer code = resultObj.getInteger("code");
if (code != 0) {
String msg = resultObj.getString("msg");
throw new ValidateException("smfcore.barcode.checkError", "[{0}]", new String[]{msg});
}
} catch (ApiException e) {
throw new ValidateException("smfcore.barcode.checkNg", "验证失败:{0}", new String[]{e.getMessage()});
}
}
public void shelfFullNotification(ShelfInfo shelfInfo, boolean lastShelf) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("hSerial", shelfInfo.getOrderNo());
paramMap.put("containerNo", shelfInfo.getShelfNo());
paramMap.put("lastContainer", lastShelf);
paramMap.put("line", shelfInfo.getLine());
paramMap.put("so", shelfInfo.getSo());
List<Map<String, String>> itemList = new ArrayList<>();
for (ShelfLocInfo info : shelfInfo.getShelfLocInfoMap().values()) {
Map<String, String> itemMap = new HashMap<>();
itemMap.put("slotNum", info.getSlotNum() + "");
itemMap.put("reelId", info.getBarcode());
itemMap.put("location", info.getLoc());
itemList.add(itemMap);
}
paramMap.put("outItems", itemList);
try {
String result = HttpHelper.postJson(shelfFullNotificationUrl, paramMap);
JSONObject resultObj = JSONObject.parseObject(result);
Integer code = resultObj.getInteger("code");
if (code != 0) {
String msg = resultObj.getString("msg");
throw new ValidateException("smfcore.barcode.checkError", "[{0}]", new String[]{msg});
}
} catch (ApiException e) {
throw new ValidateException("smfcore.barcode.checkNg", "验证失败:{0}", new String[]{e.getMessage()});
}
}
}
package com.neotel.smfcore.custom.zhongche1568.bean.api;
import lombok.Data;
@Data
public class CreateOrderItem {
private String reelId;
private int slotNum;
}
package com.neotel.smfcore.custom.zhongche1568.bean.api;
import lombok.Data;
import java.util.List;
@Data
public class CreateOrderRequest {
private String hSerial;
private String type;
private String line;
private String so;
private List<CreateOrderItem> outItems;
}
package com.neotel.smfcore.custom.zhongche1568.bean.api;
import lombok.Data;
@Data
public class MaterialCountResult {
/**
* NOT_COUNT_IN=不需要点料直接入库
* COUNT_IN=点料后入库
* COUNT_NOT_IN=点料不入库
* NOT_COUNT_NOT_IN=不点料且不入库
*/
private String materialType;
private String reelId;
}
package com.neotel.smfcore.custom.zhongche1568.bean.shelf;
import com.google.common.collect.Maps;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 虚拟货架信息
*/
@Data
public class ShelfInfo {
/**
* 13/15寸 容量是5
*/
public static final int Big_Reel_Capacity = 5;
/**
* 7寸 容量是20
*/
public static final int Small_Reel_Capacity = 20;
/**
* 大料盘已放入数量
*/
private int bigReelCount = 0;
/**
* 小料盘已经放入数量
*/
private int smallReelCount = 0;
/**
* 货架编号
*/
private String shelfNo;
/**
* 工单号
*/
private String orderNo;
/**
* 线体
*/
private String line;
/**
* 工单号
*/
private String so;
/**
* 工单状态
*/
private int status;
/**
* key为barcode信息,value为货架具体信息
*/
private Map<String, ShelfLocInfo> shelfLocInfoMap = Maps.newConcurrentMap();
public boolean hasBigCapacity() {
return Big_Reel_Capacity - this.bigReelCount > 0;
}
public boolean hasSmallCapacity() {
return Small_Reel_Capacity - this.smallReelCount > 0;
}
}
package com.neotel.smfcore.custom.zhongche1568.bean.shelf;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ShelfLocInfo {
private String orderNo;
private String barcode;
private String partNumber;
private int amount;
private String loc;
private String shelfNo;
private int slotNum;
}
package com.neotel.smfcore.custom.zhongche1568.controller;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.zhongche1568.ZhongcheApi;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfInfo;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfLocInfo;
import com.neotel.smfcore.custom.zhongche1568.enums.ShelfStatus;
import com.neotel.smfcore.custom.zhongche1568.util.ShelfInfoUtil;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Api(tags = "货架控制类")
@RequestMapping("/shelf")
@Slf4j
@RestController
public class ShelfController {
@Autowired
private CodeResolve codeResolve;
@Autowired
private ShelfInfoUtil shelfInfoUtil;
@Autowired
private TaskService taskService;
@Autowired
private DataCache dataCache;
@Autowired
private ZhongcheApi zhongcheApi;
@ApiOperation("物料放到货架上")
@RequestMapping("/reelToShelf")
@ResponseBody
@AnonymousAccess
public ResultBean reelToShelf(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("code");
String shelfNo = paramMap.get("shelfNo");
String shelfLoc = paramMap.get("shelfLoc");
log.info("物料:" + code + "放到对应的料架:" + shelfNo + "上,库位为:" + shelfLoc);
Barcode barcode = codeResolve.resolveOneValideBarcode(code);
if (barcode == null) {
return ResultBean.newErrorResult(-1, "smfcore.error.barcode.invalid", "未找到有效的条码");
}
//获取到当前执行的任务
DataLog opTask = null;
Collection<DataLog> allTasks = taskService.getAllTasks();
//log.info("所有任务为:"+ JSON.toJSONString(allTasks));
for (DataLog task : allTasks) {
if (task.isCheckOutTask() && task.getBarcode().startsWith(code)) {
if (!task.isCancel() && !task.isFinished()) {
opTask = task;
break;
}
}
}
if (opTask == null) {
return ResultBean.newErrorResult(303, "smfcore.task.notExist", "任务不存在");
}
//判断是否在货架上
ShelfLocInfo shelfLocInfo = shelfInfoUtil.getShelfLocByBarcode(barcode.getBarcode());
if (shelfLocInfo != null) {
log.info(barcode.getBarcode() + ",已经存在料架:" + shelfLocInfo.getShelfNo() + ",库位为:" + shelfLocInfo.getLoc());
return ResultBean.newErrorResult(-1,"smfcore.barcode.inShelf","[{0}]已在料架[{1}],库位[{2}]中",new String[]{barcode.getBarcode(),shelfLocInfo.getShelfNo(),shelfLocInfo.getLoc()});
}
//更新料架信息
shelfInfoUtil.updateShelfInfo(barcode.getPlateSize() > 7,
opTask.getLine(),
opTask.getSourceName(),
opTask.getSo(),
shelfNo,
shelfLoc,
barcode.getBarcode(),
barcode.getPartNumber(),
opTask.getSoltNum(),
opTask.getNum(),
ShelfStatus.reachOutLet
);
return ResultBean.newOkResult("");
}
@ApiOperation("货架拉走")
@RequestMapping("/shelfToLine")
@AnonymousAccess
public ResultBean shelfToLine(@RequestBody Map<String, String> paramMap) {
String shelfNo = paramMap.get("shelfNo");
String lastShelfStr = paramMap.get("lastShelf");
log.info("货架:" + shelfNo + "准备拉走,是否为最后一个货架:"+lastShelfStr);
Boolean lastShelf = Boolean.valueOf(lastShelfStr);
if (StringUtils.isEmpty(shelfNo)) {
return ResultBean.newErrorResult(-1, "smfcore.valueCanotNull", "{0}不能为空", new String[]{"shelfNo"});
}
//判断货架是否存在
boolean exist = shelfInfoUtil.isExistShelf(shelfNo);
if (!exist) {
return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"货架信息", shelfNo});
}
ShelfInfo shelfInfo = shelfInfoUtil.getShelfInfoByShelfNo(shelfNo);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("shelfNo", shelfInfo.getShelfNo());
resultMap.put("orderNo", shelfInfo.getOrderNo());
resultMap.put("line", shelfInfo.getLine());
//查找有没有料架任务
boolean hasShelfTask = false;
if (StringUtils.isNotEmpty(shelfInfo.getOrderNo())) {
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) {
if (dataLog.isCheckOutTask() && !dataLog.isCancel() && !dataLog.isFinished()) {
if (shelfInfo.getOrderNo().equals(dataLog.getSourceName())) {
Storage storage = dataCache.getStorage(dataLog.getCid());
if (storage.isNLShelf() || storage.isNLPShelf() || storage.isNLMShelf() || storage.isShelf()){
hasShelfTask = true;
}
}
}
}
}
resultMap.put("hasShelfTask", hasShelfTask);
//同时更改任务信息
shelfInfoUtil.updateShelfLoc(shelfNo, ShelfStatus.outLetToLine);
ShelfInfo info = shelfInfoUtil.getShelfInfoByShelfNo(shelfNo);
//通知wms
zhongcheApi.shelfFullNotification(info,lastShelf);
return ResultBean.newOkResult(resultMap);
}
@ApiOperation("货架到达线体")
@RequestMapping("/shelfReachLine")
@ResponseBody
@AnonymousAccess
public ResultBean shelfReachLine(@RequestBody Map<String, String> paramMap) {
String shelfNo = paramMap.get("shelfNo");
String shelfLoc = paramMap.get("shelfLoc");
log.info("货架:" + shelfNo + "到达线体位置:"+shelfLoc);
if (StringUtils.isEmpty(shelfNo)) {
return ResultBean.newErrorResult(-1, "smfcore.valueCanotNull", "{0}不能为空", new String[]{"shelfNo"});
}
//判断货架是否存在
boolean exist = shelfInfoUtil.isExistShelf(shelfNo);
if (!exist) {
return ResultBean.newErrorResult(-1, "smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"货架信息", shelfNo});
}
shelfInfoUtil.updateShelfLoc(shelfNo, ShelfStatus.reachLine);
return ResultBean.newOkResult("");
}
}
package com.neotel.smfcore.custom.zhongche1568.controller;
import com.alibaba.fastjson.JSON;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.order.LiteOrderCache;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.custom.zhongche1568.bean.api.CreateOrderItem;
import com.neotel.smfcore.custom.zhongche1568.bean.api.CreateOrderRequest;
import com.neotel.smfcore.custom.zhongche1568.enums.ZhongCheOrderType;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Api(tags = "中车项目")
@Slf4j
@RestController
public class ZhongCheController {
@Autowired
private ILiteOrderManager liteOrderManager;
@Autowired
private LiteOrderCache liteOrderCache;
@ApiOperation("创建需求单")
@AnonymousAccess
@PostMapping("/zhongChe/createOrder")
public ResultBean createOrder(@RequestBody CreateOrderRequest request) {
log.info("创建需求单,请求参数为:" + JSON.toJSONString(request));
String type = request.getType();
if (!ZhongCheOrderType.FIRST.equals(type) && !ZhongCheOrderType.REMAINING.equals(type)) {
return ResultBean.newErrorResult(-1, "smfcore.valueInvalid", "[{0}]不是有效的参数", new String[]{"type"});
}
//判断工单号是否存在
String hSerial = request.getHSerial();
LiteOrder liteOrder = liteOrderManager.findOneByOrderNo(hSerial);
if (liteOrder != null) {
return ResultBean.newErrorResult(-1, "smfcore.valueAlreadyExist", "{0}[{1}]已存在", new String[]{"hSerial", hSerial});
}
//创建工单
liteOrder = new LiteOrder();
liteOrder.setOrderNo(hSerial);
liteOrder.setType(type);
liteOrder.setSo(request.getSo());
liteOrder.setLine(request.getLine());
//开始处理工单详情信息
List<CreateOrderItem> outItems = request.getOutItems();
if (outItems == null || outItems.isEmpty()) {
return ResultBean.newErrorResult(-1, "smfcore.valueCanotNull", "{0}不能为空", new String[]{"outItems"});
}
List<LiteOrderItem> orderItemList = new ArrayList<>();
//按站位编号进行排序
outItems = outItems.stream().sorted(Comparator.comparing(CreateOrderItem::getSlotNum)).collect(Collectors.toList());
for (CreateOrderItem outItem : outItems) {
String reelId = outItem.getReelId();
if (StringUtils.isEmpty(reelId)){
return ResultBean.newErrorResult(-1, "smfcore.valueCanotNull", "{0}不能为空", new String[]{"reelId"});
}
int slotNum = outItem.getSlotNum();
LiteOrderItem orderItem = new LiteOrderItem();
orderItem.setRi(reelId);
orderItem.setSlotNum(slotNum);
orderItem.setNeedReelCount(1);
orderItemList.add(orderItem);
}
liteOrder.setOrderItems(orderItemList);
liteOrder = liteOrderManager.createWithItems(liteOrder);
liteOrderCache.addOrderToMap(liteOrder);
return ResultBean.newOkResult("");
}
@ApiOperation("亮灯接口")
@AnonymousAccess
@PostMapping("/rest/crrc/api/openLed")
public ResultBean openLed(@RequestBody Map<String, String> paramMap) {
String line = paramMap.get("line");
String partNum = paramMap.get("partNum");
log.info("收到亮灯指令,线体为:" + line + ",partNum为:" + partNum);
return ResultBean.newOkResult("");
}
@ApiOperation("灭灯接口")
@AnonymousAccess
@PostMapping("/rest/crrc/api/closeLed")
public ResultBean closeLed(@RequestBody Map<String,String> paramMap) {
String reelId = paramMap.get("reelId");
log.info("收到亮灯指令,reelId为" + reelId);
return ResultBean.newOkResult("");
}
}
package com.neotel.smfcore.custom.zhongche1568.controller;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.bean.ReelLockPosInfo;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.ReelLockPosUtil;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.api.SmfApi;
import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.language.util.MessageUtils;
import com.neotel.smfcore.core.message.util.DeviceMessageUtil;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.dao.IAlarmInfoDao;
import com.neotel.smfcore.core.system.service.po.AlarmInfo;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.zhongche1568.ZhongcheApi;
import com.neotel.smfcore.custom.zhongche1568.bean.api.MaterialCountResult;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfLocInfo;
import com.neotel.smfcore.custom.zhongche1568.enums.ShelfStatus;
import com.neotel.smfcore.custom.zhongche1568.util.ShelfInfoUtil;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
@Api(tags = "中车项目:与设备端进行交互")
@Slf4j
@RestController
public class ZhongCheDeviceController {
@Autowired
private CodeResolve codeResolve;
@Autowired
private TaskService taskService;
@Autowired
private IStoragePosManager storagePosManager;
@Autowired
private IBarcodeManager barcodeManager;
@Autowired
private DataCache dataCache;
@Autowired
private SmfApi smfApi;
@Autowired
private ZhongcheApi zhongcheApi;
@Autowired
private IAlarmInfoDao alarmInfoDao;
private static String lineMsg = "";
/**
* 判断是否点料
*/
@ApiOperation("判断是否点料")
@PostMapping(value = "/zhongche/materialCount")
@ResponseBody
@AnonymousAccess
public ResultBean materialCount(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("code");
log.info("收到物料点料信息:" + code);
Barcode barcode = codeResolve.resolveOneValideBarcode(code);
if (barcode == null) {
return ResultBean.newErrorResult(-1, "smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
}
try {
MaterialCountResult count = zhongcheApi.materialCount(barcode.getBarcode(), barcode.getFullCode());
return ResultBean.newOkResult(count);
} catch (ValidateException e) {
return ResultBean.newErrorResult(-1, e.getMsgKey(), e.getDefaultMsg(), e.getMsgParam());
}
}
/**
* 判断是否点料
*/
@ApiOperation("点料结果上传")
@PostMapping(value = "/zhongche/postCountData")
@ResponseBody
@AnonymousAccess
public ResultBean postCountData(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("code");
String countQtyStr = paramMap.get("countQty");
log.info("收到点料结果上传,code为:" + code + ",数量为:" + countQtyStr);
Barcode barcode = codeResolve.resolveOneValideBarcode(code);
if (barcode == null) {
return ResultBean.newErrorResult(-1, "smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
}
int countQty = Integer.parseInt(countQtyStr);
try {
zhongcheApi.postCountData(barcode.getBarcode(), countQty);
} catch (ValidateException e) {
return ResultBean.newErrorResult(-1, e.getMsgKey(), e.getDefaultMsg(), e.getMsgParam());
}
//同时更新库位的信息
StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
if (pos != null) {
barcode = pos.getBarcode();
}
barcode.setAmount(countQty);
barcodeManager.saveBarcode(barcode);
if (pos != null) {
pos.setBarcode(barcode);
storagePosManager.save(pos);
}
return ResultBean.newOkResult("");
}
/**
* 流水线入库查找空的料格
*/
@ApiOperation("环行线扫码获取库位号")
@PostMapping(value = "/zhongche/service/store/emptyPosForPutin")
@ResponseBody
@AnonymousAccess
public synchronized Map<String, Object> emptyPosForPutin(HttpServletRequest request) {
String code = request.getParameter("code");
String cids = request.getParameter("cids");
String rfid = request.getParameter("rfid");
String rfidLoc = request.getParameter("rfidLoc");
String lastPosId = request.getParameter("lastPosId");
lineMsg = "";
log.info("流水线[" + cids + "]获取[" + rfid + "][" + code + "]的入库库位");
Map<String, Object> resultMap = Maps.newHashMap();
if (dataCache.getCache(Constants.CACHE_StopOut)) {
lineMsg = "系统更新中,暂停出入库";
DeviceMessageUtil.updateLineMsg(lineMsg, code, cids, "", "smfcore.linemsg.update", null);
resultMap.put("result", "100");
resultMap.put("msg", lineMsg);
return resultMap;
}
String okMsg = "";
String errorMsg = "";
// List<String> needRemoveReelLockPosIdList = new ArrayList<>();
if (Strings.isNullOrEmpty(cids)) {
resultMap.put("result", "101");
resultMap.put("msg", "未指定料仓 cids ");
} else {
List<Storage> storageList = Lists.newArrayList();
List<String> cidList = Lists.newArrayList();
for (String cid : cids.split(",")) {
String notIntoCids = dataCache.getSettings().getNotIntoCids();
if (notIntoCids != null) {
if (notIntoCids.contains(cid)) {
log.info("料仓[" + cid + "]已被屏蔽入库");
continue;
}
}
Storage storage = dataCache.getStorage(cid);
if (storage != null) {
storageList.add(storage);
cidList.add(cid);
}
}
if (storageList.isEmpty()) {
resultMap.put("result", "99");
errorMsg = "无可用的料仓";
resultMap.put("msg", errorMsg);
} else {
try {
CodeValidateParam params = new CodeValidateParam("", "", "", code, "");
params.setStorageList(storageList);
Barcode barcode = resolveBarcodeFromApi(params);
if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "未找到有效的条码");
}
//判断对应的尺寸,外侧的库位,是否保留5个
List<String> findCidList = new ArrayList<>();
List<Storage> findNewStorageList = new ArrayList<>();
for (Storage storage : storageList) {
int count = storagePosManager.getRemainPosCountByStorage(storage, barcode, taskService.excludePosIds(), "", "_F");
if (count > 5) {
findCidList.add(storage.getCid());
findNewStorageList.add(storage);
} else {
log.info(storage.getCid()+"对应的尺寸:"+barcode.getPlateSize()+"x"+barcode.getHeight()+"外侧库位数量小于等于5个,忽略不入库");
}
}
if (findNewStorageList == null || findNewStorageList.isEmpty()){
throw new ValidateException("smfcore.noValidStorage", "[{0}]料仓列表中未找到可用的料仓",new String[]{barcode.getBarcode()});
}
for (DataLog dataLog : taskService.getQueueTasks()) {
// if(!dataLog.isPackageReel()){
//已经在任务当中,返回对应的信息
if (dataLog.getBarcode().equals(barcode.getBarcode()) && !dataLog.isCancel() && !dataLog.isFinished()) {
if (dataLog.isPutInTask()) {
//已有入库任务
errorMsg = "物料[" + dataLog.getBarcode() + "]已有入库任务,需继续执行入库动作";
resultMap.put("pos", dataLog.getPosName());
resultMap.put("barcode", barcode.getBarcode());
resultMap.put("cid", dataLog.getCid());
return resultMap;
} else {
//已有出库任务
errorMsg = "物料[" + dataLog.getBarcode() + "]已有出库任务,需继续执行出库动作";
resultMap.put("result", "98");
resultMap.put("msg", errorMsg);
resultMap.put("posId", dataLog.getPosName());
resultMap.put("plateW", barcode.getPlateSize());
resultMap.put("plateH", barcode.getHeight());
resultMap.put("singleOut", dataLog.isSingleOut() + "");
//紧急料
resultMap.put("urgentReel", dataLog.isUrgentReel() + "");
//需要分盘,进入分盘料
resultMap.put("cutReel", dataLog.isCutReel() + "");
resultMap.put("rfid", "");
resultMap.put("realRfid", "");
resultMap.put("rfidLoc", "");
// resultMap.put("rfid", dataLog.getTempRfid());
// resultMap.put("realRfid",dataLog.getAppendInfo().getRfid());
// resultMap.put("rfidLoc", dataLog.getAppendInfo().getRfidLoc() + "");
resultMap.put("barcode", dataLog.getBarcode());
boolean smallReel = barcode.isSmallReel();
resultMap.put("smallReel", smallReel + "");
return resultMap;
}
// }
}
}
//先移除被锁定的库位
ReelLockPosUtil.removeReelLockPosInfo(barcode.getBarcode());
log.info(barcode.getBarcode() + "料盘重新入库,先移除被锁定的库位");
StoragePos pos = null;
int loopCount = 0;
while (pos == null) {
loopCount++;
if (loopCount >= 10) {
log.info(barcode.getBarcode() + "已循环查找10次 直接跳出循环");
}
pos = taskService.findEmptyPosForPutIn(findNewStorageList, barcode, rfid, lastPosId);
if (pos == null) {
break;
}
//如果是以S结尾的,则判断不带S的有没有料
String posName = pos.getPosName();
if (posName.endsWith("B") || posName.endsWith("b")) {
log.info(posName + "以B结尾,需要判断外层有没有物料");
posName = posName.substring(0, posName.length() - 1);
posName = posName + "F";
StoragePos storagePos = storagePosManager.getByPosName(posName);
if (storagePos != null) {
if (storagePos.getBarcode() != null) {
log.info(posName + "有物料信息,重新查找库位,清除条码[" + barcode.getBarcode() + "]锁定库位");
ReelLockPosUtil.removeReelLockPosInfo(barcode.getBarcode());
ReelLockPosInfo reelLocInfo = new ReelLockPosInfo();
reelLocInfo.setBarcode(pos.getId());
reelLocInfo.setCid(dataCache.getStorageById(pos.getStorageId()).getCid());
reelLocInfo.setLockPosName(pos.getPosName());
reelLocInfo.setLockPosId(pos.getId());
ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, findCidList);
// needRemoveReelLockPosIdList.add(pos.getId());
pos = null;
}
}
}
}
if (pos != null) {
Storage theStorage = dataCache.getStorageById(pos.getStorageId());
resultMap.put("result", "0");
resultMap.put("msg", "");
okMsg = "[" + rfid + "][" + barcode.getBarcode() + "]锁定库位[" + pos.getPosName() + "]优先级[" + pos.getPriority() + "] 上个库位号[" + lastPosId + "]";
ReelLockPosInfo oldLockInfo = ReelLockPosUtil.getLockPosInfoByCode(barcode.getBarcode());
if (oldLockInfo != null) {
if (!oldLockInfo.getLockPosId().equals(pos.getId())) {
String result = "-1";
okMsg = rfid + "[" + rfidLoc + "][" + barcode.getBarcode() + "]锁定库位[" + pos.getPosName() + "],清理旧有锁定信息";
resultMap.put("result", result);
resultMap.put("msg", okMsg);
//已经锁定过库位,但不是同一个条码,需要把对应位置的锁定信息清理掉
ReelLockPosUtil.removeReelLockPosInfo(oldLockInfo.getBarcode());
log.info("清理锁定库位:库位号[" + oldLockInfo.getLockPosName() + "]上物料[" + oldLockInfo.getBarcode() + "]锁定的库位");
}
}
log.info(okMsg + oldLockInfo);
ReelLockPosInfo reelLocInfo = new ReelLockPosInfo();
reelLocInfo.setBarcode(barcode.getBarcode());
reelLocInfo.setCid(theStorage.getCid());
reelLocInfo.setLockPosName(pos.getPosName());
reelLocInfo.setLockPosId(pos.getId());
reelLocInfo = ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, findCidList);
if (reelLocInfo == null) {
errorMsg = "[" + barcode.getBarcode() + "]库位[" + reelLocInfo.getLockPosName() + "]已被锁定,暂停入库";
lineMsg = errorMsg;
DeviceMessageUtil.updateLineMsg(lineMsg, code, cids, reelLocInfo.getLockPosName(), "smfcore.linemsg.posLock", new String[]{barcode.getBarcode(), reelLocInfo.getLockPosName()});
resultMap.put("result", "99");
resultMap.put("msg", errorMsg);
return resultMap;
} else {
resultMap.put("pos", pos.getPosName());
resultMap.put("barcode", barcode.getBarcode());
resultMap.put("cid", theStorage.getCid());
}
} else {
resultMap.put("result", "104");
errorMsg = "[" + barcode.getBarcode() + "]未找到可用的[" + barcode.getPlateSize() + "x" + barcode.getHeight() + "]仓位";
resultMap.put("msg", errorMsg);
}
} catch (ValidateException ve) {
errorMsg = ve.getMessage();
log.info("查找空库位失败:" + errorMsg);
resultMap.put("result", "105");
resultMap.put("msg", MessageUtils.getText(ve.getMsgKey(), ve.getMsgParam(), request.getLocale(), ve.getDefaultMsg()));
} catch (Exception e) {
errorMsg = e.getMessage();
log.info("查找空库位失败,", e);
resultMap.put("result", "105");
resultMap.put("msg", errorMsg);
}
}
}
//没入成功
if (!errorMsg.isEmpty()) {
//有错误,记录日志
AlarmInfo alarmInfo = new AlarmInfo();
alarmInfo.setBoxId("0");
alarmInfo.setStorageName("流水线");
alarmInfo.setInOutStatus("1");
alarmInfo.setAlarmType("入库");
Date date = new Date();
alarmInfo.setStartTime(date);
alarmInfo.setEndTime(date);
String msg = "[" + code + "]" + errorMsg;
alarmInfo.setAlarmMsg(msg);
alarmInfoDao.save(alarmInfo);
lineMsg = errorMsg;
DeviceMessageUtil.updateLineMsg(lineMsg, code, cids, "", "", null);
} else {
lineMsg = okMsg;
DeviceMessageUtil.lastLineMsg = null;
}
return resultMap;
}
@ApiOperation("根据条码获取目的地信息")
@RequestMapping("/service/store/innerBox/getLine")
@AnonymousAccess
public Map<String, Object> getLineByBarcode(@RequestBody Map<String, String> paramMap) {
Map<String, Object> resultMap = new HashMap<>();
String barcodeStr = paramMap.get("barcode");
log.info(barcodeStr + "获取目的地信息");
Barcode barcode = codeResolve.resolveOneValideBarcode(barcodeStr);
if (barcode != null) {
log.info("解析到的条码信息为:" + barcode.getBarcode());
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) {
if (dataLog.isCheckOutTask() && !dataLog.isFinished() && !dataLog.isCancel()) {
//log.info("任务barcode为:"+dataLog.getBarcode()+",当前传入的barcode为:"+barcode.getBarcode());
if (!dataLog.getBarcode().equals(barcode.getBarcode())) {
continue;
}
resultMap.put("cid", dataLog.getCid());
String locInfo = dataLog.getLocInfo();
if (StringUtils.isEmpty(locInfo)) {
resultMap.put("locInfo", "ng");
} else {
resultMap.put("locInfo", locInfo);
}
resultMap.put("height", barcode.getHeight());
resultMap.put("plateSize", barcode.getPlateSize());
resultMap.put("barcode", barcode.getBarcode());
resultMap.put("orderNo",dataLog.getSourceName());
}
}
}
log.info(barcodeStr + "获取目的地,返回的内容为:" + JSON.toJSONString(resultMap));
return resultMap;
}
@ApiOperation("根据工单号,获取剩余数量")
@RequestMapping("/service/store/getOrderRemainNum")
@AnonymousAccess
public ResultBean getOrderRemainNum(@RequestBody Map<String, String> paramMap) {
String orderNo = paramMap.get("orderNo");
if (StringUtils.isEmpty(orderNo)){
return ResultBean.newErrorResult(-1,"smfcore.valueCanotNull","{0}不能为空",new String[]{"orderNo"} );
}
int count = 0;
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) {
if (dataLog.isCheckOutTask() && !dataLog.isFinished() && !dataLog.isCancel()) {
if (orderNo.equals(dataLog.getSourceName())) {
log.info(dataLog.getBarcode() + ",对应的工单为:" + orderNo + ",状态为:" + dataLog.getStatus());
count++;
}
}
}
return ResultBean.newOkResult(count);
}
@ApiOperation("IA 出库更新任务状态")
@RequestMapping("/service/store/innerBox/updateLocInfo")
@AnonymousAccess
public ResultBean updateLocInfo(HttpServletRequest request) {
String code = request.getParameter("barcode");
String status = request.getParameter("status");
String loc = request.getParameter("loc");
String cid = request.getParameter("cid");
String hSerial = request.getParameter("hSerial"); //工单序号
String outlet = request.getParameter("outlet"); //出口位置
String boxSide = request.getParameter("boxSide"); //料箱隔口
String x = request.getParameter("x");
String y = request.getParameter("y");
log.info("IA 出库更新任务状态--barcode:{},status:{},loc:{},hSerial:{},outlet:{},boxSide:{},cid:{},outlet:{},x:{},y:{}", code, status, loc, hSerial, outlet, boxSide, cid, outlet, x, y);
Barcode barcode = codeResolve.resolveOneValideBarcode(code);
if (barcode == null) {
return ResultBean.newErrorResult(-1, "smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
}
code = barcode.getBarcode();
log.info("解析到的料盘信息为:[" + code + "]");
//获取到当前执行的任务
DataLog opTask = null;
Collection<DataLog> allTasks = taskService.getAllTasks();
//log.info("所有任务为:"+ JSON.toJSONString(allTasks));
for (DataLog task : allTasks) {
if (task.isCheckOutTask() && task.getBarcode().equals(code)) {
if (!task.isCancel() && !task.isFinished()) {
opTask = task;
break;
}
}
}
if (opTask == null) {
return ResultBean.newErrorResult(303, "smfcore.task.notExist", "任务不存在");
}
if (opTask.isFinished()) {
return ResultBean.newErrorResult(304, "smfcore.task.hasEnd", "任务已完成");
}
status = status.toUpperCase();
opTask.setStatus(status);
if (status.equals(OP_STATUS.EXECUTING.name())) {
taskService.updateQueueTask(opTask);
} else {
if (!opTask.isOutFromPos()) {
outFromPos(opTask);
opTask.setOutFromPos(true);
}
taskService.moveTaskToFinished(opTask);
taskService.updateFinishedTask(opTask);
}
return ResultBean.newOkResult("");
}
/**
* 物料取出
*/
private void outFromPos(DataLog opTask) {
//从队列里面移除操作
taskService.removeQueueTask(opTask);
StoragePos storagePos = storagePosManager.get(opTask.getPosId());
Barcode barcode = storagePos.getBarcode();
if (barcode == null) {
log.warn("任务:" + opTask.getId() + " 仓位:" + opTask.getPosId() + " 的 Barcode 为null, 之前可能处理过,结束任务后直接返回");
return;
}
barcode = barcodeManager.get(barcode.getId());
if (barcode != null) {
//二维码状态
barcode.setUsed(true);
barcode.setUsedDate(new Date());
//仓位状态
barcode.setCheckOutDate(new Date(), "");
barcode.setPosName("");
barcodeManager.save(barcode);
}
storagePos.setBarcode(null);
storagePos.setUsed(false);
storagePosManager.save(storagePos);
log.info("出库完成,清空仓位: " + storagePos.getId() + "[" + storagePos.getPosName() + "]");
//更新缓存中的库存信息
dataCache.updateInventory(storagePos, barcode);
}
public Barcode resolveBarcodeFromApi(CodeValidateParam params) {
Barcode barcodeSave = smfApi.canPutInBeforeResolve(params);
if (barcodeSave == null) {
barcodeSave = codeResolve.resolveOneValideBarcode(params.getCode());
}
//从API验证
Barcode barcodeFromApi = smfApi.canPutInAfterResolve(params, barcodeSave);
if (barcodeFromApi != null) {
barcodeSave = barcodeFromApi;
}
return barcodeSave;
}
}
package com.neotel.smfcore.custom.zhongche1568.enums;
public class ShelfStatus {
//到达出料口
public static final int reachOutLet = 0;
//从出料口到线体
public static final int outLetToLine = 1;
//到达线体位置
public static final int reachLine = 2;
}
package com.neotel.smfcore.custom.zhongche1568.enums;
public class ZhongCheOrderLoc {
public static final String BELTLINE = "Line";
}
package com.neotel.smfcore.custom.zhongche1568.enums;
public class ZhongCheOrderType {
//首套料
public static final String FIRST = "First";
//补料
public static final String REMAINING = "Remaining";
}
package com.neotel.smfcore.custom.zhongche1568.util;
import com.google.common.collect.Maps;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfInfo;
import com.neotel.smfcore.custom.zhongche1568.bean.shelf.ShelfLocInfo;
import com.neotel.smfcore.custom.zhongche1568.enums.ShelfStatus;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.Map;
@Api(tags = "虚拟货架工具类")
@Slf4j
@Service
public class ShelfInfoUtil {
@Autowired
private DataCache dataCache;
Map<String, ShelfInfo> shelfInfoMap = Maps.newConcurrentMap();
@PostConstruct
private void initMap() {
Map<String, ShelfInfo> cacheMap = dataCache.getCache(Constants.Cache_ShelfInfo);
if (cacheMap == null){
cacheMap = Maps.newConcurrentMap();
}
shelfInfoMap.putAll(cacheMap);
}
public void updateShelfInfo(boolean bigReel,
String line,
String orderNo,
String so,
String shelfNo,
String shelfLoc,
String barcode,
String partNumber,
int soltNum,
int amount,
int shelfStatus) {
ShelfInfo shelfInfo = shelfInfoMap.get(shelfNo);
if (shelfInfo == null) {
shelfInfo = new ShelfInfo();
}
shelfInfo.setShelfNo(shelfNo);
shelfInfo.setOrderNo(orderNo);
if (bigReel) {
shelfInfo.setBigReelCount(shelfInfo.getBigReelCount() + 1);
} else {
shelfInfo.setSmallReelCount(shelfInfo.getSmallReelCount() + 1);
}
shelfInfo.setLine(line);
shelfInfo.setStatus(shelfStatus);
shelfInfo.setSo(so);
//更改料架信息
Map<String, ShelfLocInfo> shelfLocInfoMap = shelfInfo.getShelfLocInfoMap();
ShelfLocInfo shelfLocInfo = new ShelfLocInfo(orderNo, barcode, partNumber, amount, shelfLoc, shelfNo, soltNum);
shelfLocInfoMap.put(shelfLocInfo.getBarcode(), shelfLocInfo);
shelfInfo.setShelfLocInfoMap(shelfLocInfoMap);
//更新缓存信息
shelfInfoMap.put(shelfInfo.getShelfNo(), shelfInfo);
dataCache.updateCache(Constants.Cache_ShelfInfo, shelfInfoMap);
}
public ShelfLocInfo getShelfLocByBarcode(String barcode) {
if (shelfInfoMap != null && !shelfInfoMap.isEmpty()) {
for (ShelfInfo info : shelfInfoMap.values()) {
Map<String, ShelfLocInfo> shelfLocInfoMap = info.getShelfLocInfoMap();
if (shelfLocInfoMap != null && !shelfLocInfoMap.isEmpty()) {
ShelfLocInfo shelfLocInfo = shelfLocInfoMap.get(barcode);
if (shelfLocInfo != null){
return shelfLocInfo;
}
}
}
}
return null;
}
public boolean isExistShelf(String shelfNo) {
if (shelfInfoMap != null && !shelfInfoMap.isEmpty()){
return shelfInfoMap.containsKey(shelfNo);
}
return false;
}
public void updateShelfLoc(String shelfNo, int status) {
if (shelfInfoMap != null && !shelfInfoMap.isEmpty()) {
ShelfInfo shelfInfo = shelfInfoMap.get(shelfNo);
if (shelfInfo != null) {
shelfInfo.setStatus(status);
shelfInfoMap.put(shelfNo,shelfInfo);
dataCache.updateCache(Constants.Cache_ShelfInfo, shelfInfoMap);
}
}
}
public ShelfInfo getShelfInfoByShelfNo(String shelfNo) {
return shelfInfoMap.get(shelfNo);
}
}
...@@ -2,10 +2,15 @@ server: ...@@ -2,10 +2,15 @@ server:
port: 8800 port: 8800
api: api:
name: name: 1568
inCheckUrl: inCheckUrl: #入库验证
outNotifyUrl: outNotifyUrl: #出库通知
inNotifyUrl: inNotifyUrl: #入库通知
fetchOrderUrl: #获取工单
materialCountUrl: #是否点料
postCountDataUrl: #点料结果上传
shelfFullNotificationUrl: #货架放满通知
...@@ -47,7 +52,7 @@ app: ...@@ -47,7 +52,7 @@ app:
type: "" type: ""
menu: menu:
show: show: message
hide: hide:
smd: smd:
......
...@@ -424,3 +424,6 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -424,3 +424,6 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=\u65E5\u5FD7\u76D1\u63A7 smfcore.logMonitor=\u65E5\u5FD7\u76D1\u63A7
smfcore.materialTrace=\u7269\u6599\u8FFD\u6EAF smfcore.materialTrace=\u7269\u6599\u8FFD\u6EAF
smfcore.message.critical=\u4E25\u91CD\u9519\u8BEF smfcore.message.critical=\u4E25\u91CD\u9519\u8BEF
smfcore.barcode.inShelf=[{0}]\u5DF2\u5728\u6599\u67B6[{1}],\u5E93\u4F4D[{2}]\u4E2D
smfcore.barcode.checkNg=\u9A8C\u8BC1\u5931\u8D25:{0}
smfcore.barcode.checkError=[{0}]
\ No newline at end of file \ No newline at end of file
...@@ -414,3 +414,4 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -414,3 +414,4 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=Log-\u00DCberwachung smfcore.logMonitor=Log-\u00DCberwachung
smfcore.materialTrace=Materialverfolgung smfcore.materialTrace=Materialverfolgung
smfcore.message.critical=Kritischer Fehler smfcore.message.critical=Kritischer Fehler
smfcore.barcode.inShelf=[{0}] befindet sich bereits im Regal [{1}], Lagerplatz [{2}]
\ No newline at end of file \ No newline at end of file
...@@ -415,3 +415,4 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -415,3 +415,4 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=Log Monitoring smfcore.logMonitor=Log Monitoring
smfcore.materialTrace=Material Trace smfcore.materialTrace=Material Trace
smfcore.message.critical=Critical smfcore.message.critical=Critical
smfcore.barcode.inShelf=[{0}] is already on shelf [{1}], location [{2}]
\ No newline at end of file \ No newline at end of file
...@@ -414,3 +414,4 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -414,3 +414,4 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=Surveillance des Journaux smfcore.logMonitor=Surveillance des Journaux
smfcore.materialTrace=Tra\u00E7abilit\u00E9 des mati\u00E8res smfcore.materialTrace=Tra\u00E7abilit\u00E9 des mati\u00E8res
smfcore.message.critical=Erreur Critique smfcore.message.critical=Erreur Critique
smfcore.barcode.inShelf=[{0}] est d\u00E9j\u00E0 sur l'\u00E9tag\u00E8re [{1}], emplacement [{2}]
\ No newline at end of file \ No newline at end of file
...@@ -411,3 +411,4 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -411,3 +411,4 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=\u30ED\u30B0\u76E3\u8996 smfcore.logMonitor=\u30ED\u30B0\u76E3\u8996
smfcore.materialTrace=\u30DE\u30C6\u30EA\u30A2\u30EB\u30C8\u30EC\u30FC\u30B9 smfcore.materialTrace=\u30DE\u30C6\u30EA\u30A2\u30EB\u30C8\u30EC\u30FC\u30B9
smfcore.message.critical=\u91CD\u5927\u30A8\u30E9\u30FC smfcore.message.critical=\u91CD\u5927\u30A8\u30E9\u30FC
smfcore.barcode.inShelf=[{0}]\u306F\u3059\u3067\u306B\u30E9\u30C3\u30AF[{1}]\u3001\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3[{2}]\u306B\u3042\u308A\u307E\u3059
\ No newline at end of file \ No newline at end of file
...@@ -411,3 +411,4 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -411,3 +411,4 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=\u65E5\u5FD7\u76D1\u63A7 smfcore.logMonitor=\u65E5\u5FD7\u76D1\u63A7
smfcore.materialTrace=\u7269\u6599\u8FFD\u6EAF smfcore.materialTrace=\u7269\u6599\u8FFD\u6EAF
smfcore.message.critical=\u4E25\u91CD\u9519\u8BEF smfcore.message.critical=\u4E25\u91CD\u9519\u8BEF
smfcore.barcode.inShelf=[{0}]\u5DF2\u5728\u6599\u67B6[{1}],\u5E93\u4F4D[{2}]\u4E2D
\ No newline at end of file \ No newline at end of file
...@@ -411,3 +411,4 @@ smfcore.language.displayLanName.de-DE=Deutsch ...@@ -411,3 +411,4 @@ smfcore.language.displayLanName.de-DE=Deutsch
smfcore.logMonitor=\u65E5\u8A8C\u76E3\u63A7 smfcore.logMonitor=\u65E5\u8A8C\u76E3\u63A7
smfcore.materialTrace=\u7269\u6599\u8FFD\u6EAF smfcore.materialTrace=\u7269\u6599\u8FFD\u6EAF
smfcore.message.critical=\u56B4\u91CD\u932F\u8AA4 smfcore.message.critical=\u56B4\u91CD\u932F\u8AA4
smfcore.barcode.inShelf=[{0}]\u5DF2\u5728\u6599\u67B6[{1}]\uFF0C\u5EAB\u4F4D[{2}]\u4E2D
\ No newline at end of file \ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!