Commit 102bc5b0 zshaohui

1.增加虚拟仓功能

2.nexim增加用户名和密码配置
1 个父辈 47f1f5dd
正在显示 32 个修改的文件 包含 1116 行增加461 行删除
...@@ -6,4 +6,6 @@ public class BARCODE_SOURCE { ...@@ -6,4 +6,6 @@ public class BARCODE_SOURCE {
//虚拟仓 //虚拟仓
public static final String VIRTUAL = "virtual"; public static final String VIRTUAL = "virtual";
public static final String ALL = "ALL";
} }
...@@ -208,8 +208,8 @@ public class BarcodeDto implements Serializable { ...@@ -208,8 +208,8 @@ public class BarcodeDto implements Serializable {
private Date openTime; private Date openTime;
@ApiModelProperty("描述") //@ApiModelProperty("描述")
private String describe; //private String describe;
@ApiModelProperty("器件厚度") @ApiModelProperty("器件厚度")
private String thickness=""; private String thickness="";
......
...@@ -217,7 +217,7 @@ public class Barcode extends BasePo implements Serializable { ...@@ -217,7 +217,7 @@ public class Barcode extends BasePo implements Serializable {
/** /**
* 描述 * 描述
*/ */
private String describe; //private String describe;
/** /**
* 厚度 * 厚度
* 请选择 * 请选择
...@@ -237,6 +237,11 @@ public class Barcode extends BasePo implements Serializable { ...@@ -237,6 +237,11 @@ public class Barcode extends BasePo implements Serializable {
private Map<String,Object> appendData = new HashMap<>(); private Map<String,Object> appendData = new HashMap<>();
/** /**
* 是否自动创建
*/
private boolean autoCreate = false;
/**
* 添加或更新自定义附加信息 * 添加或更新自定义附加信息
* @param appendKey * @param appendKey
* @param appendValue * @param appendValue
...@@ -493,6 +498,32 @@ public class Barcode extends BasePo implements Serializable { ...@@ -493,6 +498,32 @@ public class Barcode extends BasePo implements Serializable {
return null; return null;
} }
public Barcode getSubCodeByMpn(String mpn) {
if (subCodeList == null) {
return null;
}
for (Barcode barcode : subCodeList
) {
if (mpn.equals(barcode.getMpn())) {
return barcode;
}
}
return null;
}
public Barcode getSubCodeByBarcodeId(String id) {
if (subCodeList == null) {
return null;
}
for (Barcode barcode : subCodeList
) {
if (barcode.getId().equals(id)) {
return barcode;
}
}
return null;
}
public void UpdateSubCode(Barcode barcode) { public void UpdateSubCode(Barcode barcode) {
if (subCodeList == null) { if (subCodeList == null) {
......
...@@ -5,6 +5,8 @@ import lombok.Data; ...@@ -5,6 +5,8 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
...@@ -51,4 +53,9 @@ public class MsgInfo implements Serializable { ...@@ -51,4 +53,9 @@ public class MsgInfo implements Serializable {
* 模块 * 模块
*/ */
private String moudle=""; private String moudle="";
/**
* 当前收到时间
*/
private long lastReceiveTime = System.currentTimeMillis();
} }
...@@ -771,7 +771,7 @@ public class StatusBean { ...@@ -771,7 +771,7 @@ public class StatusBean {
} }
if (msgArray.length == 1) { if (msgArray.length == 1) {
msgList.add(new MsgInfo(msg, msgType, msgEn, msgJp, msgCode, msgParam, "", "","")); msgList.add(new MsgInfo(msg, msgType, msgEn, msgJp, msgCode, msgParam, "", "","",System.currentTimeMillis()));
} else { } else {
msgList.add(new MsgInfo(msg, msgType)); msgList.add(new MsgInfo(msg, msgType));
} }
......
...@@ -123,7 +123,7 @@ public class XLCBoxHandler extends BaseDeviceHandler { ...@@ -123,7 +123,7 @@ public class XLCBoxHandler extends BaseDeviceHandler {
dto.setBarcode(barcode.getBarcode()); dto.setBarcode(barcode.getBarcode());
dto.setPartNumber(barcode.getPartNumber()); dto.setPartNumber(barcode.getPartNumber());
dto.setId(barcode.getId()); dto.setId(barcode.getId());
dto.setDescribe(barcode.getDescribe()); dto.setMemo(barcode.getMemo());
return dto; return dto;
} }
......
...@@ -22,7 +22,7 @@ public class XLCPosBarcodeDto implements Serializable { ...@@ -22,7 +22,7 @@ public class XLCPosBarcodeDto implements Serializable {
private int amount; private int amount;
@ApiModelProperty("描述") @ApiModelProperty("描述")
private String describe; private String memo;
/** /**
* 料箱中的物料信息 * 料箱中的物料信息
*/ */
......
...@@ -476,7 +476,7 @@ public class DataCache { ...@@ -476,7 +476,7 @@ public class DataCache {
/** /**
* 入库时增加使用库位列表 * 入库时增加使用库位列表
*/ */
private void addUsedPosList(String cid, StoragePos pos) { public void addUsedPosList(String cid, StoragePos pos) {
Map<String,StoragePos> usedPosList = getUsedPosList(cid); Map<String,StoragePos> usedPosList = getUsedPosList(cid);
usedPosList.put(pos.getPosName(),pos); usedPosList.put(pos.getPosName(),pos);
usedPosMap.put(cid, usedPosList); usedPosMap.put(cid, usedPosList);
......
...@@ -448,39 +448,35 @@ public class LiteOrderCache { ...@@ -448,39 +448,35 @@ public class LiteOrderCache {
/** /**
* 执行工单出库 * 执行工单出库
*/ */
public synchronized String checkOutLiteOrder(String orderNo, boolean outBom,boolean singleOut,boolean needCheck,List<String> cidList) { public synchronized String checkOutLiteOrder(String orderNo, boolean outBom, boolean singleOut, boolean needCheck, List<String> cidList) {
//判断工单是否存在
LiteOrder cacheOrder = liteOrderMap.get(orderNo); LiteOrder cacheOrder = liteOrderMap.get(orderNo);
if (cacheOrder == null) { if (cacheOrder == null) {
cacheOrder = liteOrderManager.findByOrderNo(orderNo); cacheOrder = liteOrderManager.findByOrderNo(orderNo);
} }
if (cacheOrder == null) { if (cacheOrder == null) {
return "smfcore.order.out.notFound"; return "smfcore.order.out.notFound";
} }
//判断工单状态是否可执行
if ( !cacheOrder.isTaskFinished() && !cacheOrder.isNew()) { if (!cacheOrder.isTaskFinished() && !cacheOrder.isNew()) {
log.info("工单[" + orderNo + "]正在执行"); log.info("工单[" + orderNo + "]正在执行");
return "smfcore.order.out.executing"; return "smfcore.order.out.executing";
} }
if(cacheOrder.isClosed()) { if (cacheOrder.isClosed()) {
log.info("工单[" + orderNo + "]已关闭,无法出库"); log.info("工单[" + orderNo + "]已关闭,无法出库");
return "smfcore.order.hasClose"; return "smfcore.order.hasClose";
} }
//判断是否达到可执行的最大数量
ORDER_COLOR nextColor = getNextColor(); ORDER_COLOR nextColor = getNextColor();
if (nextColor == null) { if (nextColor == null) {
log.info("执行工单[" + orderNo + "] outBom=" + outBom + "时,已达最大可执行工单数"); log.info("执行工单[" + orderNo + "] outBom=" + outBom + "时,已达最大可执行工单数");
return "smfcore.order.out.maxOrder"; return "smfcore.order.out.maxOrder";
} }
//先查找是否已经锁定过库位,如果已经锁定过,出锁定的库位 //先查找是否已经锁定过库位,如果已经锁定过,出锁定的库位
List<StoragePos> lockPosList = storagePosManager.findLockPos(cacheOrder.getOrderNo()); List<StoragePos> lockPosList = storagePosManager.findLockPos(cacheOrder.getOrderNo());
if(lockPosList!=null&& lockPosList.size()>0){ if (lockPosList != null && lockPosList.size() > 0) {
return checkOutOrder(cacheOrder).getMsgKey(); return checkOutOrder(cacheOrder).getMsgKey();
} }
log.info("开始执行工单[" + orderNo + "] outBom=" + outBom); log.info("开始执行工单[" + orderNo + "] outBom=" + outBom);
cacheOrder.setTaskReelCount(0); cacheOrder.setTaskReelCount(0);
cacheOrder.setTaskFinishedTime(-1); cacheOrder.setTaskFinishedTime(-1);
...@@ -490,35 +486,26 @@ public class LiteOrderCache { ...@@ -490,35 +486,26 @@ public class LiteOrderCache {
} else { } else {
cacheOrder.setStatus(LITEORDER_STATUS.TAILS); cacheOrder.setStatus(LITEORDER_STATUS.TAILS);
} }
//liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder); //缺料检查
int taskReelCount = 0; if (needCheck && (shortageCheck(cacheOrder, outBom, cidList))) {
CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType();
if(needCheck&&(shortageCheck(cacheOrder,outBom,cidList))) {
return "smfcore.order.out.noTask"; return "smfcore.order.out.noTask";
} }
int taskReelCount = 0;
CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType();
List<String> availableStorageIds = dataCache.getAvailableStorageIds(cidList); List<String> availableStorageIds = dataCache.getAvailableStorageIds(cidList);
boolean shortage = false;
//需要出库的料箱信息
List<String> needOutPosId = new ArrayList<>(); List<String> needOutPosId = new ArrayList<>();
//开始循环处理数据
boolean shortage=false;
//其他出库模式一次性全部生成任务
for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) { for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
//当前已出数量置为空
orderItem.setOutNum(0); orderItem.setOutNum(0);
orderItem.setOutReelCount(0); orderItem.setOutReelCount(0);
liteOrderItemManager.save(orderItem); liteOrderItemManager.save(orderItem);
//剩余未出数量 //剩余未出数量
Float totalNum = orderItem.getNeedNum() * cacheOrder.getOrderTimes(); Float totalNum = orderItem.getNeedNum() * cacheOrder.getOrderTimes();
int remainNum = totalNum.intValue() - orderItem.getTotalOutNum(); int remainNum = totalNum.intValue() - orderItem.getTotalOutNum();
//剩余未出盘数 //剩余未出盘数
int remainReelCount = orderItem.getNeedReelCount() - orderItem.getTotalOutReelCount(); int remainReelCount = orderItem.getNeedReelCount() - orderItem.getTotalOutReelCount();
//此PN未完成
if (remainNum > 0 || remainReelCount > 0) { if (remainNum > 0 || remainReelCount > 0) {
if (outBom) { if (outBom) {
//套料出库,设置剩余数量为1,这样就只会出一盘 //套料出库,设置剩余数量为1,这样就只会出一盘
...@@ -528,130 +515,165 @@ public class LiteOrderCache { ...@@ -528,130 +515,165 @@ public class LiteOrderCache {
int assignNum = 0; int assignNum = 0;
int assignReelCount = 0; int assignReelCount = 0;
while (assignNum < remainNum || assignReelCount < remainReelCount) { while (assignNum < remainNum || assignReelCount < remainReelCount) {
Collection<String> excludePosIds = excludeOutPosIds(); //判断是否ri出库
String partNumber = orderItem.getPn(); String ri = orderItem.getRi();
String reelId = orderItem.getRi(); String pn = orderItem.getPn();
String mpn = orderItem.getMpn(); String mpn = orderItem.getMpn();
StoragePos pos = null; if (StringUtils.isNotEmpty(ri)) {
if(!Strings.isNullOrEmpty(reelId)){ StoragePos pos = findPosByRi(ri, excludeOutPosIds(), orderNo, taskReelCount);
//RI if (pos == null) {
pos=storagePosManager.getByBarcode(reelId); shortage = true;
if(pos != null){ log.info("工单[" + orderNo + "]RI出库时,库存中未找到料盘[" + ri + "]");
if(excludePosIds.contains(pos.getId())) { break;
log.info("工单[" + orderNo + "]RI出库,任务数[" + taskReelCount + "]出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "]已在操作队列中,跳过不处理"); } else {
break; //判断是在料箱,还是在物料中
Barcode barcode = pos.getBarcode();
if (barcode != null) {
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) {
Barcode subCode = barcode.getSubCodeByBarcode(ri);
if (subCode != null) {
log.info(subCode.getBarcode() + "对应的料箱为:" + barcode.getBarcode() + ",需要进行标记,进行出库,工单为:" + orderNo);
subCode = updateSubCodeAppendData(cacheOrder, orderItem, subCode);
//同时更新barcode和库位信息
barcode.UpdateSubCode(subCode);
barcodeManager.save(subCode);
barcodeManager.save(barcode);
pos.setBarcode(barcode);
storagePosManager.save(pos);
needOutPosId.add(pos.getId());
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
assignNum = assignNum + subCode.getAmount();
}
} else {
log.info(barcode.getBarcode() + "对应的库位为:" + barcode.getPosName() + ",需要进行标记,进行出库,工单为:" + orderNo);
assignNum = assignNum + pos.getBarcode().getAmount();
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
generateOrderTask(pos, cacheOrder, orderItem, nextColor, singleOut);
}
} }
}else{
shortage=true;
log.info("工单[" + orderNo + "]RI出库时,库存中未找到料盘["+reelId+"]");
} }
}else if (Strings.isNullOrEmpty(reelId) && !Strings.isNullOrEmpty(partNumber)){ } else if (StringUtils.isEmpty(ri) && StringUtils.isNotEmpty(pn)) {
//PN List<Barcode> barcodeList = findPosByPartNumberAndSort(availableStorageIds, pn, excludeOutPosIds(), checkoutType, orderItem.getAppendData());
pos=storagePosManager.findPartNumberInStorages(availableStorageIds,"", partNumber, excludePosIds, checkoutType,orderItem.getAppendData()); if (barcodeList == null || barcodeList.isEmpty()) {
} else if (Strings.isNullOrEmpty(reelId) && Strings.isNullOrEmpty(partNumber) && !Strings.isNullOrEmpty(mpn)){ break;
pos=storagePosManager.findMpnInStorages(availableStorageIds, mpn, excludePosIds, checkoutType,orderItem.getAppendData()); }
} for (Barcode barcode : barcodeList) {
if (pos == null) { //判断库位是否存在
// log.error("未找到可以出库的物料[" + partNumber + "]"); if (assignNum >= remainNum && assignReelCount >= remainReelCount) {
shortage=true; break;
break;
} else {
//判断是属于料箱还是料盘
Barcode posBarcode = pos.getBarcode();
List<Barcode> subCodeList = posBarcode.getSubCodeList();
if (subCodeList == null || subCodeList.isEmpty()) {
assignNum = assignNum + pos.getBarcode().getAmount();
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
log.info("工单[" + orderNo + "],任务数[" + taskReelCount + "]出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + partNumber + "] num:" + pos.getBarcode().getAmount());
DataLog task = newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
task.setType(OP.CHECKOUT);
task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine());
// task = dataLogDao.save(task);
taskService.addTaskToExecute(task);
} else {
Barcode subCode = null;
if (!Strings.isNullOrEmpty(reelId)) {
subCode = posBarcode.getSubCodeByBarcode(reelId);
} else if (Strings.isNullOrEmpty(reelId) && !Strings.isNullOrEmpty(partNumber)) {
subCode = posBarcode.getSubCode(partNumber);
} }
if (subCode != null) { if (StringUtils.isEmpty(barcode.getPosName())) {
//设置出库数量 continue;
int amount = subCode.getAmount(); }
int awaitingNum = remainNum - assignNum; if (StringUtils.isEmpty(barcode.getHostBarcodeId())) {
if (awaitingNum - amount >= 0) { log.info(barcode.getBarcode() + "对应的库位为:" + barcode.getPosName() + ",需要进行标记,进行出库,工单为:" + orderNo);
assignNum = assignNum + amount; StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
subCode.updateAppendData("awaiting", amount); generateOrderTask(pos, cacheOrder, orderItem, nextColor, singleOut);
} else { assignNum = assignNum + pos.getBarcode().getAmount();
subCode.updateAppendData("awaiting", amount - awaitingNum); assignReelCount = assignReelCount + 1;
assignNum = assignNum + amount - awaitingNum; taskReelCount = taskReelCount + 1;
} else {
StoragePos pos = storagePosManager.getByBarcodeId(barcode.getHostBarcodeId());
Barcode posBarcode = pos.getBarcode();
if (posBarcode != null) {
Barcode subCode = posBarcode.getSubCodeByBarcode(barcode.getBarcode());
if (subCode != null) {
log.info(subCode.getBarcode() + "对应的料箱为:" + posBarcode.getBarcode() + ",需要进行标记,进行出库,工单为:" + orderNo);
subCode = updateSubCodeAppendData(cacheOrder, orderItem, subCode);
//同时更新barcode和库位信息
posBarcode.UpdateSubCode(subCode);
barcodeManager.save(subCode);
barcodeManager.save(posBarcode);
pos.setBarcode(posBarcode);
storagePosManager.save(pos);
needOutPosId.add(pos.getId());
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
assignNum = assignNum + subCode.getAmount();
}
} }
}
}
} else if (StringUtils.isEmpty(ri) && StringUtils.isEmpty(pn) && StringUtils.isNotEmpty(mpn)) {
List<Barcode> barcodeList = findPosByMpnAndSort(availableStorageIds, mpn, excludeOutPosIds(), checkoutType, orderItem.appendData);
if (barcodeList == null || barcodeList.isEmpty()) {
break;
}
for (Barcode barcode : barcodeList) {
//判断库位是否存在
if (assignNum >= remainNum && assignReelCount >= remainReelCount) {
break;
}
if (StringUtils.isEmpty(barcode.getPosName())) {
continue;
}
if (StringUtils.isEmpty(barcode.getHostBarcodeId())) {
log.info(barcode.getBarcode() + "对应的库位为:" + barcode.getPosName() + ",需要进行标记,进行出库,工单为:" + orderNo);
StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
generateOrderTask(pos, cacheOrder, orderItem, nextColor, singleOut);
assignNum = assignNum + pos.getBarcode().getAmount();
assignReelCount = assignReelCount + 1; assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1; taskReelCount = taskReelCount + 1;
subCode.updateAppendData("orderItemId", orderItem.getId()); } else {
subCode.updateAppendData("orderNo", cacheOrder.getOrderNo()); StoragePos pos = storagePosManager.getByBarcodeId(barcode.getHostBarcodeId());
subCode.updateAppendData("orderId", cacheOrder.getId()); Barcode posBarcode = pos.getBarcode();
posBarcode.UpdateSubCode(subCode); if (posBarcode != null) {
barcodeManager.save(subCode); Barcode subCode = posBarcode.getSubCodeByMpn(barcode.getMpn());
barcodeManager.save(posBarcode); if (subCode != null) {
pos.setBarcode(posBarcode); log.info(subCode.getBarcode() + "对应的料箱为:" + posBarcode.getBarcode() + ",需要进行标记,进行出库,工单为:" + orderNo);
storagePosManager.save(pos); subCode = updateSubCodeAppendData(cacheOrder, orderItem, subCode);
needOutPosId.add(pos.getId()); //同时更新barcode和库位信息
posBarcode.UpdateSubCode(subCode);
barcodeManager.save(subCode);
barcodeManager.save(posBarcode);
pos.setBarcode(posBarcode);
storagePosManager.save(pos);
needOutPosId.add(pos.getId());
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
assignNum = assignNum + subCode.getAmount();
}
}
} }
} }
} }
//如果是RI出库,只有一盘,出完就结束 if (assignNum < remainNum || assignReelCount < remainReelCount) {
if(!Strings.isNullOrEmpty(reelId)){ shortage = true;
break; break;
} }
} }
} }
} }
//判断要出的箱子是否为空
if (needOutPosId != null && !needOutPosId.isEmpty()) { if (needOutPosId != null && !needOutPosId.isEmpty()) {
needOutPosId = needOutPosId.stream().distinct().collect(Collectors.toList()); needOutPosId = needOutPosId.stream().distinct().collect(Collectors.toList());
for (String posId : needOutPosId) { for (String posId : needOutPosId) {
StoragePos pos = storagePosManager.get(posId); StoragePos pos = storagePosManager.get(posId);
DataLog task = newTask(pos); generateOrderTask(pos, cacheOrder, null, nextColor, singleOut);
task.setSourceName(cacheOrder.getOrderNo());
task.setSourceId(cacheOrder.getId());
task.setType(OP.CHECKOUT);
task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine());
taskService.addTaskToExecute(task);
taskReelCount = taskReelCount + 1; taskReelCount = taskReelCount + 1;
} }
} }
//标记工单是否缺料
if (shortage) {
if(shortage){ cacheOrder.addAppendDate("shortage", "true");
cacheOrder.addAppendDate("shortage","true"); } else {
}else{ cacheOrder.addAppendDate("shortage", "false");
cacheOrder.addAppendDate("shortage","false");
} }
cacheOrder.setTaskReelCount(taskReelCount); cacheOrder.setTaskReelCount(taskReelCount);
cacheOrder.setTotalTaskReelCount(cacheOrder.getTotalTaskReelCount()+taskReelCount); cacheOrder.setTotalTaskReelCount(cacheOrder.getTotalTaskReelCount() + taskReelCount);
log.info("工单[" + orderNo + "]任务分配结束,任务数[" + taskReelCount + "]"); log.info("工单[" + orderNo + "]任务分配结束,任务数[" + taskReelCount + "]");
smfApi.onOrderStatusChange(cacheOrder); smfApi.onOrderStatusChange(cacheOrder);
//有需要出库的
if (taskReelCount <= 0) { if (taskReelCount <= 0) {
finishedOrderTasks(cacheOrder); finishedOrderTasks(cacheOrder);
} }
liteOrderManager.save(cacheOrder); liteOrderManager.save(cacheOrder);
liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder); liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder);
if (taskReelCount <= 0) { if (taskReelCount <= 0) {
//return "工单无可执行的任务"; //return "工单无可执行的任务";
...@@ -1069,4 +1091,100 @@ public class LiteOrderCache { ...@@ -1069,4 +1091,100 @@ public class LiteOrderCache {
return ""; return "";
} }
public StoragePos findPosByRi(String reelId, Collection<String> excludeOutPosIds, String orderNo, int taskReelCount) {
StoragePos pos = storagePosManager.getByBarcode(reelId);
if (pos == null) {
return null;
}
if (excludeOutPosIds.contains(pos.getId())) {
log.info("工单[" + orderNo + "]RI出库,任务数[" + taskReelCount + "]出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "]已在操作队列中,跳过不处理");
return null;
}
return pos;
}
public List<Barcode> findPosByPartNumberAndSort(List<String> availableStorageIds, String partNumber, Collection<String> excludePosIds, CHECKOUT_TYPE checkoutType, Map<String, String> appendDate) {
List<Barcode> barcodeList = new ArrayList<>();
List<StoragePos> posList = storagePosManager.findPosListByPartNumber(availableStorageIds, partNumber, excludePosIds, checkoutType, appendDate);
if (posList == null || posList.isEmpty()) {
return barcodeList;
}
//提取出来所有Barcode信息
for (StoragePos pos : posList) {
Barcode barcode = pos.getBarcode();
if (barcode != null) {
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) {
Integer awaiting = subCode.getAppendData("awaiting");
if (awaiting != null){
continue;
}
if (partNumber.equals(subCode.getPartNumber())) {
barcodeList.add(subCode);
}
}
} else {
barcodeList.add(barcode);
}
}
}
barcodeList = taskService.barcodeListByCheckOutType(checkoutType,barcodeList);
return barcodeList;
}
public List<Barcode> findPosByMpnAndSort(List<String> availableStorageIds, String mpn, Collection<String> excludePosIds, CHECKOUT_TYPE checkoutType, Map<String, String> appendDate) {
List<Barcode> barcodeList = new ArrayList<>();
List<StoragePos> posList = storagePosManager.findPosListByMpn(availableStorageIds, mpn, excludePosIds, checkoutType, appendDate);
if (posList == null || posList.isEmpty()) {
return barcodeList;
}
//提取出来所有Barcode信息
for (StoragePos pos : posList) {
Barcode barcode = pos.getBarcode();
if (barcode != null) {
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) {
Integer awaiting = subCode.getAppendData("awaiting");
if (awaiting != null){
continue;
}
if (mpn.equals(subCode.getMpn())) {
barcodeList.add(subCode);
}
}
} else {
barcodeList.add(barcode);
}
}
}
barcodeList = taskService.barcodeListByCheckOutType(checkoutType, barcodeList);
return barcodeList;
}
private Barcode updateSubCodeAppendData(LiteOrder cacheOrder, LiteOrderItem orderItem, Barcode subCode) {
subCode.updateAppendData("orderItemId", orderItem.getId());
subCode.updateAppendData("orderNo", cacheOrder.getOrderNo());
subCode.updateAppendData("orderId", cacheOrder.getId());
subCode.updateAppendData("awaiting", subCode.getAmount());
return subCode;
}
public void generateOrderTask(StoragePos pos,LiteOrder cacheOrder,LiteOrderItem orderItem,ORDER_COLOR nextColor,boolean singleOut){
DataLog task = newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
if (orderItem != null) {
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
}
task.setType(OP.CHECKOUT);
task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine());
taskService.addTaskToExecute(task);
}
} }
...@@ -322,25 +322,24 @@ public class OrderController { ...@@ -322,25 +322,24 @@ public class OrderController {
for (Map<String,StoragePos> list : for (Map<String,StoragePos> list :
allPosLists) { allPosLists) {
for (StoragePos pos : list.values()) { for (StoragePos pos : list.values()) {
boolean isItemPos = false; boolean isItemPos = isItemPos(item, pos.getBarcode());
if (ObjectUtil.isNotEmpty(item.getRi())) {
if (pos.getBarcode().getBarcode().equals(item.getRi())) {
isItemPos = true;
}
} else if (ObjectUtil.isNotEmpty(item.getPn())) {
if (ObjectUtil.isNotEmpty(pos.getBarcode().getPartNumber()) && pos.getBarcode().getPartNumber().startsWith(item.getPn())) {
isItemPos = true;
}
} else if (ObjectUtil.isNotEmpty(item.getMpn())) {
if (ObjectUtil.isNotEmpty(pos.getBarcode().getMpn()) && pos.getBarcode().getMpn().equals(item.getMpn())) {
isItemPos = true;
}
}
if (isItemPos) { if (isItemPos) {
inventoryReelCount += 1; inventoryReelCount += 1;
inventoryQty += pos.getBarcode().getAmount(); inventoryQty += pos.getBarcode().getAmount();
} else {
Barcode barcode = pos.getBarcode();
if (barcode != null){
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()){
for (Barcode subCode : subCodeList) {
boolean isItemBox = isItemPos(item,subCode);
if (isItemBox){
inventoryReelCount += 1;
inventoryQty += subCode.getAmount();
}
}
}
}
} }
} }
} }
...@@ -798,4 +797,22 @@ public class OrderController { ...@@ -798,4 +797,22 @@ public class OrderController {
List<String> allLineList = liteOrderManager.findAllLines(); List<String> allLineList = liteOrderManager.findAllLines();
return allLineList; return allLineList;
} }
private boolean isItemPos(LiteOrderItem item, Barcode barcode) {
boolean isItemPos = false;
if (ObjectUtil.isNotEmpty(item.getRi())) {
if (barcode.getBarcode().equals(item.getRi())) {
isItemPos = true;
}
} else if (ObjectUtil.isNotEmpty(item.getPn())) {
if (ObjectUtil.isNotEmpty(barcode.getPartNumber()) && barcode.getPartNumber().startsWith(item.getPn())) {
isItemPos = true;
}
} else if (ObjectUtil.isNotEmpty(item.getMpn())) {
if (ObjectUtil.isNotEmpty(barcode.getMpn()) && barcode.getMpn().equals(item.getMpn())) {
isItemPos = true;
}
}
return isItemPos;
}
} }
...@@ -109,7 +109,7 @@ public class MaterialBoxController { ...@@ -109,7 +109,7 @@ public class MaterialBoxController {
if(describe==null){ if(describe==null){
throw new ValidateException("smfcore.valueCanotNull","{0}不能为空",new String[]{"describe"} ); throw new ValidateException("smfcore.valueCanotNull","{0}不能为空",new String[]{"describe"} );
} }
barcode.setDescribe(describe); barcode.setMemo(describe);
barcodeManager.saveBarcode(barcode); barcodeManager.saveBarcode(barcode);
log.info("更改料盒[" + code + "]的描述信息为:" + describe); log.info("更改料盒[" + code + "]的描述信息为:" + describe);
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
...@@ -544,7 +544,7 @@ public class MaterialBoxController { ...@@ -544,7 +544,7 @@ public class MaterialBoxController {
* @param opQty 数量 * @param opQty 数量
* @throws ValidateException * @throws ValidateException
*/ */
private void finishTask(Barcode pidBarcode, int opType, DataLog currentTask, Barcode subBarcode, int opQty) throws ValidateException { private synchronized void finishTask(Barcode pidBarcode, int opType, DataLog currentTask, Barcode subBarcode, int opQty) throws ValidateException {
//更新barcode缓存 //更新barcode缓存
...@@ -599,7 +599,7 @@ public class MaterialBoxController { ...@@ -599,7 +599,7 @@ public class MaterialBoxController {
task = dataLogManager.save(task); task = dataLogManager.save(task);
taskService.moveTaskToFinished(task); taskService.moveTaskToFinished(task);
// dataCache.updateInventoryAmount(task.getCid(), subBarcode.getPartNumber(), opQty); // dataCache.updateInventoryAmount(task.getCid(), subBarcode.getPartNumber(), opQty);
} }
} }
...@@ -198,7 +198,10 @@ public class StorageController { ...@@ -198,7 +198,10 @@ public class StorageController {
List<Storage> allStorages = storageManager.findAll(); List<Storage> allStorages = storageManager.findAll();
List<Storage> myStorages = new ArrayList<>(); List<Storage> myStorages = new ArrayList<>();
for (Storage s : allStorages) { for (Storage s : allStorages) {
if (BARCODE_SOURCE.VIRTUAL.equals(type)){ if (BARCODE_SOURCE.ALL.equals(type)){
}
else if (BARCODE_SOURCE.VIRTUAL.equals(type)){
if (!s.isVirtual()){ if (!s.isVirtual()){
continue; continue;
} }
......
...@@ -15,6 +15,7 @@ import com.neotel.smfcore.core.barcode.enums.BARCODE_SOURCE; ...@@ -15,6 +15,7 @@ import com.neotel.smfcore.core.barcode.enums.BARCODE_SOURCE;
import com.neotel.smfcore.core.barcode.rest.bean.dto.BarcodeDto; import com.neotel.smfcore.core.barcode.rest.bean.dto.BarcodeDto;
import com.neotel.smfcore.core.barcode.rest.bean.dto.CodeDto; import com.neotel.smfcore.core.barcode.rest.bean.dto.CodeDto;
import com.neotel.smfcore.core.barcode.rest.bean.mapstruct.CodeMapper; import com.neotel.smfcore.core.barcode.rest.bean.mapstruct.CodeMapper;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
import com.neotel.smfcore.core.barcode.service.po.Barcode; import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve; import com.neotel.smfcore.core.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.device.util.DataCache; import com.neotel.smfcore.core.device.util.DataCache;
...@@ -54,6 +55,7 @@ import java.io.IOException; ...@@ -54,6 +55,7 @@ import java.io.IOException;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
@Slf4j @Slf4j
@RestController @RestController
...@@ -79,6 +81,9 @@ public class StoragePosController { ...@@ -79,6 +81,9 @@ public class StoragePosController {
@Autowired @Autowired
private CodeMapper codeMapper; private CodeMapper codeMapper;
@Autowired
private IBarcodeManager barcodeManager;
@ApiOperation("查询库位") @ApiOperation("查询库位")
@GetMapping @GetMapping
...@@ -568,8 +573,10 @@ public class StoragePosController { ...@@ -568,8 +573,10 @@ public class StoragePosController {
String isSingleOutStr = checkOutDto.getSingleOut(); String isSingleOutStr = checkOutDto.getSingleOut();
boolean isSingleOut = Boolean.valueOf(isSingleOutStr); boolean isSingleOut = Boolean.valueOf(isSingleOutStr);
List<String> needOutPosIdList = new ArrayList<>();
for (String pid : checkOutDto.getPids()) { for (String pid : checkOutDto.getPids()) {
StoragePos pos = storagePosManager.get(pid); StoragePos pos = storagePosManager.getByBarcodeId(pid);
if (pos == null) { if (pos == null) {
//throw new ValidateException("smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"pid", pid}); //throw new ValidateException("smfcore.valueNotExist", "{0}[{1}]不存在", new String[]{"pid", pid});
// throw new ValidateException("位置[" + pid + "]不存在"); // throw new ValidateException("位置[" + pid + "]不存在");
...@@ -591,7 +598,7 @@ public class StoragePosController { ...@@ -591,7 +598,7 @@ public class StoragePosController {
//如果料仓不可用,不能出库 //如果料仓不可用,不能出库
if (!storage.isVirtual()) { if (!storage.isVirtual()) {
if (!dataCache.StorageIsAvailable(storage)) { if (!dataCache.StorageIsAvailable(storage)) {
throw new ValidateException("smfcore.storage.notAvailable", "料仓{0}离线或不可用,无法出库", new String[]{storage.getName()}); //throw new ValidateException("smfcore.storage.notAvailable", "料仓{0}离线或不可用,无法出库", new String[]{storage.getName()});
} }
} }
...@@ -600,11 +607,29 @@ public class StoragePosController { ...@@ -600,11 +607,29 @@ public class StoragePosController {
// if(!result) { // if(!result) {
// throw new ValidateException("smfcore.error.getMaterialLot.out", "条码[{0}]验证失败,无法出库", new String[]{pos.getBarcode().getBarcode()}); // throw new ValidateException("smfcore.error.getMaterialLot.out", "条码[{0}]验证失败,无法出库", new String[]{pos.getBarcode().getBarcode()});
// } // }
//判断是属于料箱还是物料
List<Barcode> subCodeList = posBarcode.getSubCodeList();
if(subCodeList != null && !subCodeList.isEmpty()){
Barcode subCode = posBarcode.getSubCodeByBarcodeId(pid);
if (subCode != null){
subCode.updateAppendData("awaiting", subCode.getAmount());
barcodeManager.save(subCode);
posBarcode.UpdateSubCode(subCode);
barcodeManager.save(posBarcode);
pos.setBarcode(posBarcode);
storagePosManager.save(pos);
}
}
log.info("手动出库:出库料仓【" + storage.getName() + "_" + storage.getCid() + "】位置仓位【" + pos.getPosName() + "】"); log.info("手动出库:出库料仓【" + storage.getName() + "_" + storage.getCid() + "】位置仓位【" + pos.getPosName() + "】");
String outResult = taskService.checkout(storage, pos, isSingleOut,SecurityUtils.getCurrentUsername()); needOutPosIdList.add(pos.getId());
if (!Strings.isNullOrEmpty(outResult)) { }
throw new ValidateException("smfcore.error", outResult); if (needOutPosIdList != null && !needOutPosIdList.isEmpty()){
needOutPosIdList = needOutPosIdList.stream().distinct().collect(Collectors.toList());
for (String posId : needOutPosIdList) {
StoragePos pos = storagePosManager.get(posId);
Storage storage = dataCache.getStorageById(pos.getStorageId());
taskService.checkout(storage, pos, isSingleOut,SecurityUtils.getCurrentUsername());
} }
} }
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
......
...@@ -95,5 +95,9 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> { ...@@ -95,5 +95,9 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
StoragePos findOne(Query query); StoragePos findOne(Query query);
Sort getSortByCheckOutType(CHECKOUT_TYPE checkoutType); Sort getSortByCheckOutType(CHECKOUT_TYPE checkoutType);
List<StoragePos> findPosListByPartNumber(List<String> storageIdList, String pn, Collection<String> excludePosIds, CHECKOUT_TYPE checkOutType,Map<String,String> appendData);
List<StoragePos> findPosListByMpn(List<String> availableStorageIds, String mpn, Collection<String> excludePosIds, CHECKOUT_TYPE checkoutType, Map<String, String> appendDate);
} }
...@@ -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;
...@@ -30,8 +31,10 @@ import org.springframework.data.mongodb.core.query.Query; ...@@ -30,8 +31,10 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.awt.*;
import java.text.ParseException; import java.text.ParseException;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -59,41 +62,87 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -59,41 +62,87 @@ public class StoragePosManagerImpl implements IStoragePosManager {
return getInventory(-1, storageId); return getInventory(-1, storageId);
} }
private List<InventoryItem> inventory(int type,String... storageIds){ private List<InventoryItem> inventory(int type, String... storageIds) {
Criteria c = Criteria.where("barcode").exists(true).and("storageId").in(storageIds); Criteria c = Criteria.where("barcode").exists(true).and("storageId").in(storageIds);
if(type != -1){ if (type != -1) {
c = c.and("barcode.type").is(type); c = c.and("barcode.type").is(type);
} }
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(c), Map<String, InventoryItem> resultMap = new HashMap<>();
Aggregation.group("barcode.partNumber").sum("barcode.amount").as("stockCount").count().as("stockReel"), List<StoragePos> storagePosList = storagePosDao.findByQuery(new Query(c));
Aggregation.project("stockCount", "stockReel").and("partNumber").previousOperation() for (StoragePos pos : storagePosList) {
); Barcode barcode = pos.getBarcode();
AggregationResults<InventoryItem> results = storagePosDao.getMongoTemplate().aggregate(agg, StoragePos.class, InventoryItem.class); if (barcode != null){
return results.getMappedResults(); String partNumber = barcode.getPartNumber();
int amount = barcode.getAmount();
InventoryItem inventoryItem = resultMap.get(partNumber);
if (inventoryItem == null){
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(partNumber);
inventoryItem.setStockCount(inventoryItem.getStockCount()+amount);
inventoryItem.setStockReel(inventoryItem.getStockReel()+1);
resultMap.put(partNumber,inventoryItem);
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()){
for (Barcode subCode : subCodeList) {
String subCodePartNumber = subCode.getPartNumber();
int subCodeAmount = subCode.getAmount();
InventoryItem subCodeInventoryItem = resultMap.get(subCodePartNumber);
if (subCodeInventoryItem == null){
subCodeInventoryItem = new InventoryItem();
}
subCodeInventoryItem.setPartNumber(subCodePartNumber);
subCodeInventoryItem.setStockCount(subCodeInventoryItem.getStockCount()+subCodeAmount);
subCodeInventoryItem.setStockReel(subCodeInventoryItem.getStockReel()+1);
resultMap.put(subCodePartNumber,subCodeInventoryItem);
}
}
}
}
return Lists.newArrayList(resultMap.values());
} }
private List<InventoryItem> lockInventory(int type,String... storageIds){ private List<InventoryItem> lockInventory(int type, String... storageIds) {
//被锁定的仓位 Criteria c = Criteria.where("barcode").exists(true).and("storageId").in(storageIds);
// //TODO:这里还需要去掉被指定批次锁定的,因为出错,暂时不加了.. if (type != -1) {
// Criteria c = Criteria.where("barcode").exists(true).and("storageId").in(storageIds)
// .andOperator(Criteria.where("canCheckOutTime").gt(System.currentTimeMillis()));
Criteria newC = Criteria.where("barcode.lockId").exists(true).ne("");
Criteria c = Criteria.where("barcode").exists(true)
.and("storageId").in(storageIds)
// .andOperator(Criteria.where("canCheckOutTime").gt(System.currentTimeMillis()))
.andOperator(newC);
if(type != -1){
c = c.and("barcode.type").is(type); c = c.and("barcode.type").is(type);
} }
Map<String, InventoryItem> resultMap = new HashMap<>();
Aggregation agg = Aggregation.newAggregation( List<StoragePos> storagePosList = storagePosDao.findByQuery(new Query(c));
Aggregation.match(c), for (StoragePos pos : storagePosList) {
Aggregation.group("barcode.partNumber").count().as("lockReel"), Barcode barcode = pos.getBarcode();
Aggregation.project("lockReel").and("partNumber").previousOperation() if (barcode != null) {
); String lockId = barcode.getLockId();
AggregationResults<InventoryItem> results = storagePosDao.getMongoTemplate().aggregate(agg, StoragePos.class, InventoryItem.class); String partNumber = barcode.getPartNumber();
return results.getMappedResults(); if (StringUtils.isNotEmpty(lockId)) {
InventoryItem inventoryItem = resultMap.get(partNumber);
if (inventoryItem == null) {
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(partNumber);
inventoryItem.setLockReel(inventoryItem.getLockReel() + 1);
resultMap.put(partNumber, inventoryItem);
}
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) {
String subCodeLockId = subCode.getLockId();
if (StringUtils.isNotEmpty(subCodeLockId)){
String subCodePartNumber = subCode.getPartNumber();
InventoryItem inventoryItem = resultMap.get(subCodePartNumber);
if (inventoryItem == null) {
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(subCodePartNumber);
inventoryItem.setLockReel(inventoryItem.getLockReel() + 1);
resultMap.put(subCodePartNumber, inventoryItem);
}
}
}
}
}
return Lists.newArrayList(resultMap.values());
} }
private Map<String, InventoryItem> getInventory(int type,String... storageIds){ private Map<String, InventoryItem> getInventory(int type,String... storageIds){
...@@ -145,29 +194,77 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -145,29 +194,77 @@ public class StoragePosManagerImpl implements IStoragePosManager {
* @param inHours * @param inHours
* @return * @return
*/ */
private List<InventoryItem> expireInventory(int type, int inHours,String[] storageIds){ private List<InventoryItem> expireInventory(int type, int inHours, String[] storageIds) {
//过期的仓位 //过期的仓位
Criteria c = Criteria.where("barcode").exists(true).and("storageId").in(storageIds); Criteria c = Criteria.where("barcode").exists(true).and("storageId").in(storageIds);
if(type != -1){ if (type != -1) {
c = c.and("barcode.type").is(type); c = c.and("barcode.type").is(type);
} }
Map<String, InventoryItem> resultMap = new HashMap<>();
Criteria expireCriteria = Criteria.where("expireTime").gt(System.currentTimeMillis()); List<StoragePos> storagePosList = storagePosDao.findByQuery(new Query(c));
if(inHours > 0){ for (StoragePos pos : storagePosList) {
expireCriteria = Criteria.where("expireTime").gt(System.currentTimeMillis()).lte(System.currentTimeMillis() + inHours * 60 * 60 * 1000); Barcode barcode = pos.getBarcode();
}else{ if (barcode != null) {
expireCriteria = Criteria.where("expireTime").lte(System.currentTimeMillis()); Date expireDate = barcode.getExpireDate();
if (expireDate != null) {
if (inHours > 0) {
if (expireDate.getTime() > System.currentTimeMillis() && expireDate.getTime() < System.currentTimeMillis() + inHours * 60 * 60 * 1000) {
String partNumber = barcode.getPartNumber();
InventoryItem inventoryItem = resultMap.get(partNumber);
if (inventoryItem == null) {
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(partNumber);
inventoryItem.setExpireReel(inventoryItem.getExpireReel() + 1);
resultMap.put(partNumber, inventoryItem);
}
} else {
if (expireDate.getTime() < System.currentTimeMillis()) {
String partNumber = barcode.getPartNumber();
InventoryItem inventoryItem = resultMap.get(partNumber);
if (inventoryItem == null) {
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(partNumber);
inventoryItem.setExpireReel(inventoryItem.getExpireReel() + 1);
resultMap.put(partNumber, inventoryItem);
}
}
}
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) {
Date subCodeExpireDate = subCode.getExpireDate();
if (subCodeExpireDate != null) {
if (inHours > 0) {
if (subCodeExpireDate.getTime() > System.currentTimeMillis() && subCodeExpireDate.getTime() < System.currentTimeMillis() + inHours * 60 * 60 * 1000) {
String partNumber = subCode.getPartNumber();
InventoryItem inventoryItem = resultMap.get(partNumber);
if (inventoryItem == null) {
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(partNumber);
inventoryItem.setExpireReel(inventoryItem.getExpireReel() + 1);
resultMap.put(partNumber, inventoryItem);
}
} else {
if (subCodeExpireDate.getTime() < System.currentTimeMillis()) {
String partNumber = subCode.getPartNumber();
InventoryItem inventoryItem = resultMap.get(partNumber);
if (inventoryItem == null) {
inventoryItem = new InventoryItem();
}
inventoryItem.setPartNumber(partNumber);
inventoryItem.setExpireReel(inventoryItem.getExpireReel() + 1);
resultMap.put(partNumber, inventoryItem);
}
}
}
}
}
}
} }
return Lists.newArrayList(resultMap.values());
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(c),
Aggregation.project("barcode").andExpression("barcode.putInTime + barcode.maxStorageTime * 60 * 60 * 1000").as("expireTime"),
Aggregation.match(expireCriteria),
Aggregation.group("barcode.partNumber").count().as("expireReel"),
Aggregation.project("expireReel").and("partNumber").previousOperation()
);
AggregationResults<InventoryItem> results = storagePosDao.getMongoTemplate().aggregate(agg, StoragePos.class, InventoryItem.class);
return results.getMappedResults();
} }
@Override @Override
...@@ -573,7 +670,11 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -573,7 +670,11 @@ public class StoragePosManagerImpl implements IStoragePosManager {
@Override @Override
public StoragePos getByBarcodeId(String barcodeId) { public StoragePos getByBarcodeId(String barcodeId) {
return storagePosDao.findOneByCondition(new String[]{"barcode.id"}, new String[]{barcodeId}); List<Criteria> orCriterialList = Lists.newArrayList();
orCriterialList.add(Criteria.where("barcode.id").is(barcodeId));
orCriterialList.add(Criteria.where("barcode.subCodeList.id").is(barcodeId));
Criteria c = new Criteria().orOperator(orCriterialList);
return storagePosDao.findOne(new Query(c));
} }
@Override @Override
...@@ -886,4 +987,50 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -886,4 +987,50 @@ public class StoragePosManagerImpl implements IStoragePosManager {
public StoragePos findOne(Query query) { public StoragePos findOne(Query query) {
return storagePosDao.findOne(query); return storagePosDao.findOne(query);
} }
@Override
public List<StoragePos> findPosListByPartNumber(List<String> storageIdList, String pn, Collection<String> excludePosIds, CHECKOUT_TYPE checkOutType,Map<String,String> appendData) {
Criteria c = Criteria.where("id").nin(excludePosIds)
.and("enabled").is(true)//可用
.and("barcode.lockId").is(null);//没有被锁定的仓位;
if (storageIdList != null) {
c = c.and("storageId").in(storageIdList);
}
if (appendData != null) {
c = addAppendData(c, appendData);
}
List<Criteria> orCriterialList = Lists.newArrayList();
orCriterialList.add(Criteria.where("barcode.partNumber").is(pn));
orCriterialList.add(Criteria.where("barcode.subCodeList.partNumber").is(pn));
c.orOperator(orCriterialList);
Query q = new Query(c);
Sort sort = getSortByCheckOutType(checkOutType);
q.with(sort);
return storagePosDao.findByQuery(q);
}
@Override
public List<StoragePos> findPosListByMpn(List<String> storageIdList, String mpn, Collection<String> excludePosIds, CHECKOUT_TYPE checkOutType, Map<String, String> appendData) {
Criteria c = Criteria.where("id").nin(excludePosIds)
.and("enabled").is(true)//可用
.and("barcode.lockId").is(null);//没有被锁定的仓位;
if (storageIdList != null) {
c = c.and("storageId").in(storageIdList);
}
if (appendData != null) {
c = addAppendData(c, appendData);
}
List<Criteria> orCriterialList = Lists.newArrayList();
orCriterialList.add(Criteria.where("barcode.mpn").is(mpn));
orCriterialList.add(Criteria.where("barcode.subCodeList.mpn").is(mpn));
c.orOperator(orCriterialList);
Query q = new Query(c);
Sort sort = getSortByCheckOutType(checkOutType);
q.with(sort);
return storagePosDao.findByQuery(q);
}
} }
...@@ -171,6 +171,9 @@ public class DevicesStatusUtil { ...@@ -171,6 +171,9 @@ public class DevicesStatusUtil {
// return statusBean; // return statusBean;
// } // }
//缓存信息
private static Map<String, List<MsgInfo>> cacheMsgMap = Maps.newConcurrentMap();
/** /**
* 更新客户端发上来的消息(设备故障等消息) * 更新客户端发上来的消息(设备故障等消息)
*/ */
...@@ -195,6 +198,38 @@ public class DevicesStatusUtil { ...@@ -195,6 +198,38 @@ public class DevicesStatusUtil {
} }
} }
if (newMsg) { if (newMsg) {
List<MsgInfo> cacheMsgList = cacheMsgMap.get(cid);
if (cacheMsgList == null || cacheMsgList.isEmpty()) {
cacheMsgList = new ArrayList<>();
}
List<MsgInfo> newCacheList = new ArrayList<>();
for (MsgInfo msgInfo : cacheMsgList) {
if (System.currentTimeMillis() - msgInfo.getLastReceiveTime() > 1000 * 60 * 5) {
continue;
}
String msgKey = msg.getMsgKey();
String msgStr = msg.getMsg();
if (StringUtils.isNotEmpty(msgKey)) {
if (msgKey.equals(msgInfo.getMsgKey())) {
newMsg = false;
msgInfo.setLastReceiveTime(System.currentTimeMillis());
}
}
if (StringUtils.isNotEmpty(msgStr)) {
if (msgStr.equals(msgInfo.getMsg())) {
newMsg = false;
msgInfo.setLastReceiveTime(System.currentTimeMillis());
}
}
newCacheList.add(msgInfo);
}
if (newMsg){
newCacheList.add(msg);
}
cacheMsgMap.put(cid, newCacheList);
}
if (newMsg) {
String msgType= msg.getType(); String msgType= msg.getType();
if(ObjectUtil.isEmpty(msgType)){ if(ObjectUtil.isEmpty(msgType)){
msgType=MessageType.ERROR.name(); msgType=MessageType.ERROR.name();
......
...@@ -272,6 +272,7 @@ public class TaskService { ...@@ -272,6 +272,7 @@ public class TaskService {
task.setUpdateDate(new Date()); task.setUpdateDate(new Date());
updateFinishedTask(task); updateFinishedTask(task);
log.info("任务[" + task.getId() + "] posName[" + task.getPosName() + "] Reel Id[" + task.getBarcode() + "]取消成功"); log.info("任务[" + task.getId() + "] posName[" + task.getPosName() + "] Reel Id[" + task.getBarcode() + "]取消成功");
clearBarcodeAppenddata(task);
return true; return true;
} }
return false; return false;
...@@ -1236,46 +1237,144 @@ public class TaskService { ...@@ -1236,46 +1237,144 @@ public class TaskService {
CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType(); CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType();
List<String> availableStorageIds; List<String> availableStorageIds;
List<String> groupStorageId = SecurityUtils.getUserGroupStorageId(); List<String> groupStorageId = SecurityUtils.getUserGroupStorageId();
if (groupStorageId != null && !groupStorageId.isEmpty()){ if (groupStorageId != null && !groupStorageId.isEmpty()) {
availableStorageIds = groupStorageId; availableStorageIds = groupStorageId;
} else { } else {
availableStorageIds = dataCache.getAvailableStorageIds(); availableStorageIds = dataCache.getAvailableStorageIds();
} }
List<String> needOutPosId = new ArrayList<>();
//其他出库模式一次性全部生成任务 //其他出库模式一次性全部生成任务
for (TacticsOutDto item : tacticsOutDtos) { for (TacticsOutDto item : tacticsOutDtos) {
log.info("开始执行策略出库[" + item.getPartNumber() + "] [" + item.getStorageId() + "] 盘数=" + item.getPlateNumber()+",数量="+item.getNeedNum()); log.info("开始执行策略出库[" + item.getPartNumber() + "] [" + item.getStorageId() + "] 盘数=" + item.getPlateNumber() + ",数量=" + item.getNeedNum());
String partNumber = item.getPartNumber(); String partNumber = item.getPartNumber();
int currNum=0; int currNum = 0;
int reelNum=0; int reelNum = 0;
while (reelNum<item.getPlateNumber()||currNum<item.getNeedNum())
// for (int i = 1; i <= item.getPlateNumber(); i++) { List<StoragePos> posList = null;
{ Collection<String> excludePosIds = excludePosIds(); Collection<String> excludePosIds = excludePosIds();
StoragePos pos = null; if (item.getStorageId() != null) {
if (item.getStorageId() != null) { String[] storageIds = new String[]{item.getStorageId()};
String[] storageIds = new String[]{item.getStorageId()}; posList = storagePosManager.findPosListByPartNumber(Lists.newArrayList(storageIds), partNumber, excludePosIds, checkoutType,null);
pos = storagePosManager.findPartNumberInStorages(Lists.newArrayList(storageIds), partNumber, excludePosIds, checkoutType); } else {
} else { posList = storagePosManager.findPosListByPartNumber(availableStorageIds, partNumber, excludePosIds, checkoutType,null);
pos = storagePosManager.findPartNumberInStorages(availableStorageIds, partNumber, excludePosIds, checkoutType); }
if (posList == null || posList.isEmpty()) {
log.error("策略出库[" + item.getPartNumber() + "] 未找到可以出库的物料[" + partNumber + "]");
} else {
//提取出来所有PartNumber信息
List<Barcode> barcodeList = new ArrayList<>();
for (StoragePos pos : posList) {
Barcode barcode = pos.getBarcode();
if (barcode != null) {
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) {
if (partNumber.equals(subCode.getPartNumber())) {
barcodeList.add(subCode);
}
}
} else {
barcodeList.add(barcode);
}
}
} }
if (pos == null) { barcodeList = barcodeListByCheckOutType(checkoutType, barcodeList);
log.error("策略出库[" + item.getPartNumber() + "] 未找到可以出库的物料[" + partNumber + "]"); //开始循环处理数据
while (reelNum < item.getPlateNumber() || currNum < item.getNeedNum()) {
for (Barcode barcode : barcodeList) {
if (reelNum >= item.getPlateNumber() && currNum >= item.getNeedNum()) {
break;
}
String posName = barcode.getPosName();
if (StringUtils.isEmpty(posName)) {
continue;
}
String hostBarcodeId = barcode.getHostBarcodeId();
if (StringUtils.isEmpty(hostBarcodeId)) {
StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
if (pos != null) {
currNum += pos.getBarcode().getAmount();
reelNum += 1;
log.info("策略出库,PN[" + item.getPartNumber() + "]第[" + reelNum + "]盘, 出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + partNumber + "] num:" + pos.getBarcode().getAmount() + ",累计数量:" + currNum);
DataLog task = newTask(pos);
task.setType(OP.CHECKOUT);
task.setOperator(SecurityUtils.getCurrentUsername());
task.setSingleOut(true);
task.setSourceId(null);
task.setSourceName("PN");
addTaskToExecute(task);
}
} else {
StoragePos pos = storagePosManager.getByBarcodeId(hostBarcodeId);
if (pos != null) {
Barcode posBarcode = pos.getBarcode();
if (posBarcode != null) {
Barcode subCode = posBarcode.getSubCodeByBarcode(barcode.getBarcode());
if (subCode != null) {
subCode.updateAppendData("awaiting", subCode.getAmount());
posBarcode.UpdateSubCode(subCode);
barcodeManager.save(subCode);
barcodeManager.save(posBarcode);
pos.setBarcode(posBarcode);
storagePosManager.save(pos);
needOutPosId.add(pos.getId());
currNum += subCode.getAmount();
reelNum += 1;
}
}
}
}
}
//循环一遍没有找到合适的,直接跳过
break; break;
} else {
currNum+=pos.getBarcode().getAmount();
reelNum+=1;
log.info("策略出库,PN[" + item.getPartNumber() + "]第[" + reelNum + "]盘, 出库位置仓位【" + pos.getPosName() + "】RI=[" + pos.getBarcode().getBarcode() + "] PN=[" + partNumber + "] num:" + pos.getBarcode().getAmount()+",累计数量:"+currNum);
DataLog task = newTask(pos);
task.setType(OP.CHECKOUT);
task.setOperator(SecurityUtils.getCurrentUsername());
task.setSingleOut(true);
task.setSourceId(null);
task.setSourceName("PN");
addTaskToExecute(task);
} }
} }
} }
if (needOutPosId != null && !needOutPosId.isEmpty()) {
needOutPosId = needOutPosId.stream().distinct().collect(Collectors.toList());
for (String posId : needOutPosId) {
StoragePos pos = storagePosManager.get(posId);
DataLog task = newTask(pos);
task.setType(OP.CHECKOUT);
task.setOperator(SecurityUtils.getCurrentUsername());
task.setSingleOut(true);
task.setSourceId(null);
task.setSourceName("PN");
addTaskToExecute(task);
}
}
}
public List<Barcode> barcodeListByCheckOutType(CHECKOUT_TYPE checkoutType, List<Barcode> barcodeList) {
//按时间进行排序
if (CHECKOUT_TYPE.EXPIRE_FIRST.equals(checkoutType)) {//先过期先出
barcodeList = barcodeList.stream().sorted(Comparator.comparing(Barcode::getExpireDate,Comparator.naturalOrder())
.thenComparing(Barcode::getPutInDate,Comparator.naturalOrder())).collect(Collectors.toList());
} else if (CHECKOUT_TYPE.FIFO.equals(checkoutType)) {//严格的先进先出
barcodeList = barcodeList.stream().sorted(Comparator.comparing(Barcode::getPutInDate,Comparator.naturalOrder())
.thenComparing(Barcode::getUsedCount)).collect(Collectors.toList());
} else if (CHECKOUT_TYPE.USED_FIRST.equals(checkoutType)) {//尾料优先
barcodeList = barcodeList.stream().sorted(Comparator.comparing(Barcode::getAmount)
.thenComparing(Barcode::getPutInDate,Comparator.naturalOrder())).collect(Collectors.toList());
} else if (CHECKOUT_TYPE.PRODUCE_DATE.equals(checkoutType)) {
barcodeList = barcodeList.stream().sorted(Comparator.comparing(Barcode::getProduceDate,Comparator.naturalOrder())
.thenComparing(Barcode::getAmount)
.thenComparing(Barcode::getPutInDate,Comparator.naturalOrder())).collect(Collectors.toList());
} else if (CHECKOUT_TYPE.BATCH_FIRST.equals(checkoutType)) {
barcodeList = barcodeList.stream().sorted(Comparator.comparing(Barcode::getBatch,Comparator.naturalOrder())
.thenComparing(Barcode::getProduceDate,Comparator.naturalOrder())
.thenComparing(Barcode::getAmount)
.thenComparing(Barcode::getPutInDate,Comparator.naturalOrder())).collect(Collectors.toList());
} else {//效率优先
barcodeList = barcodeList.stream().sorted(Comparator.comparing(Barcode::getPutInDate,Comparator.naturalOrder())
.thenComparing(Barcode::getCreateDate))
.collect(Collectors.toList());
}
return barcodeList;
} }
public void moveTaskToFinished(DataLog task) { public void moveTaskToFinished(DataLog task) {
...@@ -1303,4 +1402,36 @@ public class TaskService { ...@@ -1303,4 +1402,36 @@ public class TaskService {
} }
} }
} }
private void clearBarcodeAppenddata(DataLog dataLog) {
if (dataLog.isPutInTask()) {
return;
}
String barcodeStr = dataLog.getBarcode();
if (StringUtils.isNotEmpty(barcodeStr)) {
StoragePos pos = storagePosManager.getByBarcode(barcodeStr);
if (pos != null) {
Barcode barcode = pos.getBarcode();
if (barcode != null) {
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()){
for (Barcode subCode : subCodeList) {
Integer awaiting = subCode.getAppendData("awaiting");
if (awaiting != null) {
subCode.updateAppendData("orderItemId", null);
subCode.updateAppendData("orderNo", null);
subCode.updateAppendData("orderId", null);
subCode.updateAppendData("awaiting", null);
barcodeManager.save(subCode);
barcode.UpdateSubCode(subCode);
barcodeManager.save(barcode);
pos.setBarcode(barcode);
storagePosManager.save(pos);
}
}
}
}
}
}
}
} }
...@@ -8,6 +8,7 @@ import com.neotel.smfcore.common.utils.StringUtils; ...@@ -8,6 +8,7 @@ import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.barcode.bean.CodeBean; import com.neotel.smfcore.core.barcode.bean.CodeBean;
import com.neotel.smfcore.core.barcode.enums.BARCODE_SOURCE; import com.neotel.smfcore.core.barcode.enums.BARCODE_SOURCE;
import com.neotel.smfcore.core.barcode.enums.COMPONENT_TYPE; import com.neotel.smfcore.core.barcode.enums.COMPONENT_TYPE;
import com.neotel.smfcore.core.barcode.rest.bean.dto.BarcodeDto;
import com.neotel.smfcore.core.barcode.rest.bean.mapstruct.BarcodeMapper; import com.neotel.smfcore.core.barcode.rest.bean.mapstruct.BarcodeMapper;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager; import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
import com.neotel.smfcore.core.barcode.service.manager.IComponentManager; import com.neotel.smfcore.core.barcode.service.manager.IComponentManager;
...@@ -24,7 +25,7 @@ import com.neotel.smfcore.core.system.rest.bean.mapstruct.TaskMapper; ...@@ -24,7 +25,7 @@ import com.neotel.smfcore.core.system.rest.bean.mapstruct.TaskMapper;
import com.neotel.smfcore.core.system.service.manager.IDataLogManager; import com.neotel.smfcore.core.system.service.manager.IDataLogManager;
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.TaskService; import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.security.annotation.AnonymousAccess; import com.neotel.smfcore.core.virtual.util.ShortUniqueCodeUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -37,7 +38,6 @@ import org.springframework.web.bind.annotation.RequestBody; ...@@ -37,7 +38,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -74,204 +74,243 @@ public class VirtualOperateController { ...@@ -74,204 +74,243 @@ public class VirtualOperateController {
@Autowired @Autowired
private TaskMapper taskMapper; private TaskMapper taskMapper;
@ApiOperation("查询料盒信息")
@PostMapping("/materialBox")
//@PreAuthorize("@el.check('materialBox')")
public BarcodeDto manualOut(@RequestBody String code) {
// String code = paramMap.get("barcode");
CodeBean codeBean = new CodeBean();
try {
codeBean = codeResolve.resolveSingleCode(code.trim(), COMPONENT_TYPE.FIXTURE);
} catch (ValidateException e) {
codeBean.setError(e.getMessage());
}
if (codeBean == null || codeBean.getBarcode() == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "未找到有效的条码");
}
if (codeBean.getErrorCode() != null) {
throw new ValidateException(codeBean.getErrorCode(), codeBean.getError(), codeBean.getParams());
}
List<BarcodeDto> codeDtos = new ArrayList<BarcodeDto>();
Barcode barcode = codeBean.getBarcode();
//此处需要判断是否是料盒
Component component=componentManager.findOneByPN(barcode.getPartNumber() );
if(component==null||(component.getType()!=COMPONENT_TYPE.FIXTURE)){
throw new ValidateException("smfcore.materialBox.invalid", "未找到料盒信息{0}", new String[]{code});
}
//判断是否有任务,有任务直接完成,不清空库存信息
DataLog dataLog = null;
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog task : allTasks) {
if (task.isCheckOutTask() && !task.isFinished() && !task.isCancel()) {
if (barcode.getBarcode().equals(task.getBarcode())){
dataLog = task;
break;
}
}
}
if (dataLog != null){
dataLog.setStatus(OP_STATUS.FINISHED.name());
taskService.removeQueueTask(dataLog);
taskService.updateFinishedTask(dataLog);
}
BarcodeDto barcodeDto=barcodeMapper.toDto(barcode);
// if(barcodeDto.getSubCodeMap()==null){
// barcodeDto.setSubCodeMap(new HashMap<>());
// }
if(barcodeDto.getSubCodeList()==null){
barcodeDto.setSubCodeList(new ArrayList<>());
}
return barcodeDto;
}
@ApiOperation("扫描条码返回具体的信息") @ApiOperation("(唯一码)物料放入料盒中")
@RequestMapping("/scanReelPutIn") @PostMapping(value = "/reelToBox")
@AnonymousAccess //@AnonymousAccess
public ResultBean scanPutInReel(@RequestBody Map<String, String> paramMap) { public ResultBean reelToBox(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("barcode");//料盒条码 String code = paramMap.get("barcode");//料盒条码
String operageStr = paramMap.get("operatePN");//操作信息 String operageStr = paramMap.get("operatePN");//操作信息
//判断条码是否存在 log.info("收到物料放入料箱,boxStr:" + code + ",operageStr:" + operageStr);
Barcode barcode = codeResolve.resolveOneValideBarcode(code); //判断料箱是否存在
Barcode barcode = barcodeManager.findByBarcode(code);
if (barcode == null) { if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code}); throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
} }
Map<String, Object> resultMap = new HashMap<>(); //判断是否在库位中
//判断是不是按料号进行入库 StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
if (pos != null) {
barcode = pos.getBarcode();
}
//如果物料编码存在,则按物料编码进行入库
Component component = componentManager.findOneByPN(operageStr); Component component = componentManager.findOneByPN(operageStr);
if (component != null) { if (component != null) {
resultMap.put("type", "pn"); ResultBean resultBean = ResultBean.newOkResult(operageStr);
resultMap.put("partNumber", operageStr); resultBean.setCode(99);
return ResultBean.newOkResult(resultMap); return resultBean;
} }
//解析物料信息 //如果解析失败,则按物料编码进行入库
String newCodeStr = "=1x1=" + operageStr; String newCodeStr = "=1x1=" + operageStr;
CodeBean codeBean = codeResolve.resolveSingleCode(newCodeStr); CodeBean codeBean = codeResolve.resolveSingleCode(newCodeStr);
if (!codeBean.isValid()) { if (!codeBean.isValid()) {
resultMap.put("type", "pn"); ResultBean resultBean = ResultBean.newOkResult(operageStr);
resultMap.put("partNumber", operageStr); resultBean.setCode(99);
return ResultBean.newOkResult(resultMap); return resultBean;
} }
//判断是否存在其他料箱中
Barcode subCode = codeBean.getBarcode(); Barcode subCode = codeBean.getBarcode();
//判断是否存在其他料盒中
String hostBarcodeId = subCode.getHostBarcodeId(); String hostBarcodeId = subCode.getHostBarcodeId();
if (StringUtils.isNotEmpty(hostBarcodeId)) { if (StringUtils.isNotEmpty(hostBarcodeId)) {
if (!hostBarcodeId.equals(barcode.getId())) { if (!hostBarcodeId.equals(barcode.getId())) {
throw new ValidateException("smfcore.materialBox.inOtherBox", "物料已在料盒{0}中", new String[]{barcode.getBarcode()}); Barcode hostBarcode = barcodeManager.get(hostBarcodeId);
if (hostBarcode != null) {
throw new ValidateException("smfcore.materialBox.inOtherBox", "物料已在料盒{0}中", new String[]{hostBarcode.getBarcode()});
}
} }
} }
//如果是物料信息,返回ri //判断库位是否为空
resultMap.put("type", "ri"); String posName = subCode.getPosName();
resultMap.put("amount", subCode.getAmount()); if (StringUtils.isNotEmpty(posName)) {
return ResultBean.newOkResult(resultMap); throw new ValidateException("smfcore.materialBox.inPos", "物料已在库位{0}中", new String[]{posName});
}
subCode.setHostBarcodeId(barcode.getId());
subCode.setPosName(barcode.getBarcode());
subCode.setPutInTime(System.currentTimeMillis());
barcodeManager.saveBarcode(subCode);
barcode = finishTask(barcode, OP.PUT_IN, subCode, subCode.getAmount(), OP_STATUS.FINISHED.name(), subCode.getAmount());
log.info("条码" + subCode.getBarcode() + "[" + subCode.getPartNumber() + "]入库到料盒[" + barcode.getBarcode() + "]数量:" + barcode.getAmount());
//如果在库位中,则同步更新库位信息
if (pos != null) {
pos.setBarcode(barcode);
storagePosManager.save(pos);
Storage storage = dataCache.getStorageById(pos.getStorageId());
dataCache.addUsedPosList(storage.getCid(),pos);
dataCache.updateInventoryAmount(storage.getCid(),subCode.getPartNumber(),subCode.getAmount(),subCode.getBarcode());
}
return ResultBean.newOkResult(barcodeMapper.toDto(barcode));
} }
@ApiOperation("(物料编码)物料放入料盒中")
@ApiOperation("物料放入料盒中") @PostMapping(value = "/partNumberToBox")
@PostMapping(value = "/reelToBox")
//@AnonymousAccess //@AnonymousAccess
public ResultBean reelToBox(@RequestBody Map<String, String> paramMap) { public ResultBean partNumberToBox(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("barcode");//料盒条码 String code = paramMap.get("barcode");//料盒条码
String operageStr = paramMap.get("operatePN");//操作信息 String operageStr = paramMap.get("operatePN");//操作信息
String putInType = paramMap.get("putInType"); //判断是ri还是pn入库 String amountStr = paramMap.get("amount"); //数量
String reelType = paramMap.get("reelType"); log.info("收到物料放入料箱,boxStr:" + code + ",operageStr:" + operageStr + ",amountStr=" + amountStr);
String amountStr = paramMap.get("amount");
log.info("收到物料放入料箱,boxStr:" + code
+ ",operageStr:" + operageStr
+ ",putInType:" + putInType
+ ",reelType:" + reelType
+ ",amountStr=" + amountStr);
//判断料箱是否存在 //判断料箱是否存在
Barcode barcode = barcodeManager.findByBarcode(code); Barcode barcode = barcodeManager.findByBarcode(code);
if (barcode == null) { if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code}); throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
} }
//判断是否在库位中
StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
if (pos != null) {
barcode = pos.getBarcode();
}
//判断数量是否为正确的
int opQty = Integer.valueOf(amountStr); int opQty = Integer.valueOf(amountStr);
int opType = OP.NON_OP; if (opQty <= 0) {
if (opQty > 0) {
opType = OP.PUT_IN;
} else {
throw new ValidateException("smfcore.materialBox.qtyError", "请输入正确的数量"); throw new ValidateException("smfcore.materialBox.qtyError", "请输入正确的数量");
} }
if ("pn".equals(putInType)) { //不进行合并,每次入库都是新的唯一码
Barcode subBarcode = barcode.getSubCode(operageStr); Component component = autoGetComponent(operageStr, opQty);
if (subBarcode == null) { Barcode subBarcode = autoGetBarcode(barcode, component, operageStr, opQty);
Component component = autoGetComponent(operageStr, opQty); subBarcode.setHostBarcodeId(barcode.getId());
subBarcode = autoGetBarcode(barcode, component, operageStr, opQty); subBarcode.setPosName(barcode.getBarcode());
} else { subBarcode.setPutInTime(System.currentTimeMillis());
int oldAmount = subBarcode.getAmount(); subBarcode = barcodeManager.save(subBarcode);
subBarcode.setHostBarcodeId(barcode.getId()); barcode = finishTask(barcode, OP.PUT_IN, subBarcode, opQty, OP_STATUS.FINISHED.name(), subBarcode.getAmount());
subBarcode.setAmount(oldAmount + opQty); log.info("条码" + subBarcode.getBarcode() + "[" + subBarcode.getPartNumber() + "]入库到料盒[" + barcode.getBarcode() + "]数量:" + barcode.getAmount());
} if (pos != null) {
subBarcode.setPutInTime(System.currentTimeMillis()); pos.setBarcode(barcode);
subBarcode = barcodeManager.save(subBarcode); storagePosManager.save(pos);
barcode = finishTask(barcode, opType, subBarcode, opQty,OP_STATUS.FINISHED.name()); Storage storage = dataCache.getStorageById(pos.getStorageId());
log.info("条码" + subBarcode.getBarcode() + "[" + subBarcode.getPartNumber() + "]入库到料盒[" + barcode.getBarcode() + "]数量:" + barcode.getAmount()); dataCache.addUsedPosList(storage.getCid(),pos);
} else if ("ri".equals(putInType)) { dataCache.updateInventoryAmount(storage.getCid(),subBarcode.getPartNumber(),subBarcode.getAmount(),subBarcode.getBarcode());
//解析条码
Barcode subCode = codeResolve.resolveOneValideBarcode("=1x1="+operageStr);
if (subCode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{operageStr});
}
String hostBarcodeId = subCode.getHostBarcodeId();
if (StringUtils.isNotEmpty(hostBarcodeId)) {
if (!hostBarcodeId.equals(barcode.getId())) {
Barcode hostBarcode = barcodeManager.get(hostBarcodeId);
if (hostBarcode != null) {
throw new ValidateException("smfcore.materialBox.inOtherBox", "物料已在料盒{0}中", new String[]{hostBarcode.getBarcode()});
}
}
}
//判断物料是否存在料箱中
String posName = subCode.getPosName();
if (StringUtils.isNotEmpty(posName)) {
throw new ValidateException("smfcore.materialBox.inPos", "物料已在库位{0}中", new String[]{posName});
}
subCode.setHostBarcodeId(barcode.getId());
subCode.setAmount(opQty);
subCode.setPutInTime(System.currentTimeMillis());
barcodeManager.saveBarcode(subCode);
barcode = finishTask(barcode, opType, subCode, opQty,OP_STATUS.FINISHED.name());
log.info("条码" + subCode.getBarcode() + "[" + subCode.getPartNumber() + "]入库到料盒[" + barcode.getBarcode() + "]数量:" + barcode.getAmount());
} }
return ResultBean.newOkResult(barcodeMapper.toDto(barcode)); return ResultBean.newOkResult(barcodeMapper.toDto(barcode));
} }
@ApiOperation("物料从料盒中取出")
@ApiOperation("物料从料盒中取出(唯一码出库)")
@PostMapping(value = "/reelFromBox") @PostMapping(value = "/reelFromBox")
//@AnonymousAccess //@AnonymousAccess
public ResultBean reelFromBox(@RequestBody Map<String, String> paramMap) { public ResultBean reelFromBox(@RequestBody Map<String, String> paramMap) {
String code = paramMap.get("barcode");//料盒条码 String code = paramMap.get("barcode");//料盒条码
String operageStr = paramMap.get("operatePN");//操作信息 String operageStr = paramMap.get("operatePN");//操作信息
String checkOutType = paramMap.get("checkOutType");
String amountStr = paramMap.get("amount"); String amountStr = paramMap.get("amount");
String type = paramMap.get("type");
if ("pn".equals(type)){
if (StringUtils.isEmpty(amountStr)){
throw new ValidateException("smfcore.materialBox.qtyError", "请输入正确的数量");
}
}
//判断料箱是不是有效的参数
Barcode barcode = barcodeManager.findByBarcode(code); Barcode barcode = barcodeManager.findByBarcode(code);
if (barcode == null) { if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code}); throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
} }
//判断是否在库位中 //判断是否在库位中
String posName = barcode.getPosName(); StoragePos pos = storagePosManager.getByBarcode(barcode.getBarcode());
if (StringUtils.isNotEmpty(posName)) { if (pos != null) {
throw new ValidateException("smfcore.virtual.boxInPos", "[{0}]已在库位[{1}]中,请先取出", new String[]{barcode.getBarcode(), posName}); barcode = pos.getBarcode();
} }
int opQty = Integer.valueOf(amountStr);
int opType = OP.NON_OP; //判断输入的条码是否正确
if (opQty > 0) { CodeBean codeBean = codeResolve.resolveSingleCode("=1x1=" + operageStr);
opType = OP.CHECKOUT; if (!codeBean.isValid()) {
} else { throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{operageStr});
//请输入正确的数量 }
Barcode subBarcode = codeBean.getBarcode();
int opQty = subBarcode.getAmount();
if (StringUtils.isNotEmpty(amountStr)) {
opQty = Integer.valueOf(amountStr);
}
if (opQty <= 0) {
throw new ValidateException("smfcore.materialBox.qtyError", "请输入正确的数量"); throw new ValidateException("smfcore.materialBox.qtyError", "请输入正确的数量");
} }
//判断是pn还是ri出 //判断是否在此料箱中
if ("pn".equals(checkOutType)) { String hostBarcodeId = subBarcode.getHostBarcodeId();
//查看该库位中是否有相同的物料,有的话,数量累加 if (StringUtils.isEmpty(hostBarcodeId)) {
Barcode subBarcode = barcode.getSubCode(operageStr); throw new ValidateException("smfcore.materialBox.noReel", "料盒中未找到对应物料");
if (subBarcode == null) { }
throw new ValidateException("smfcore.materialBox.noReel", "料盒中未找到对应物料"); if (!hostBarcodeId.equals(barcode.getId())) {
} Barcode hostBarcode = barcodeManager.get(hostBarcodeId);
int oldAmount = subBarcode.getAmount(); if (hostBarcode != null) {
if (oldAmount < opQty) { throw new ValidateException("smfcore.materialBox.inOtherBox", "物料已在料盒{0}中", new String[]{hostBarcode.getBarcode()});
throw new ValidateException("smfcore.materialBox.quantityshort", "物料数量不足");
}
Integer awaitingNum = subBarcode.getAppendData("awaiting");
if (awaitingNum != null) {
if (opQty < awaitingNum) {
throw new ValidateException("smfcore.virtual.quantityError", "取出数量应为[{0}]",new String[]{awaitingNum+""});
}
}
int newAmount = oldAmount - opQty;
subBarcode.setHostBarcodeId(barcode.getId());
subBarcode.setAmount(newAmount);
subBarcode = barcodeManager.save(subBarcode);
barcode = finishTask(barcode, opType, subBarcode, opQty,OP_STATUS.FINISHED.name());
log.info(subBarcode.getPartNumber() + "从料盒[" + barcode.getPosName() + "]出库,物料数量:" + oldAmount + " - " + opQty + " = " + newAmount);
} else if ("ri".equals(checkOutType)) {
CodeBean codeBean = codeResolve.resolveSingleCode("=1x1="+operageStr);
if (!codeBean.isValid()) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{operageStr});
}
//判断是否在此料箱中
Barcode subBarcode = codeBean.getBarcode();
String hostBarcodeId = subBarcode.getHostBarcodeId();
if (StringUtils.isEmpty(hostBarcodeId)) {
throw new ValidateException("smfcore.materialBox.noReel", "料盒中未找到对应物料");
}
if (!hostBarcodeId.equals(barcode.getId())) {
Barcode hostBarcode = barcodeManager.get(hostBarcodeId);
if (hostBarcode != null) {
throw new ValidateException("smfcore.materialBox.inOtherBox", "物料已在料盒{0}中", new String[]{hostBarcode.getBarcode()});
}
}
int qty = subBarcode.getAmount() - opQty;
if (qty < 0) {
qty = 0;
} }
Integer awaitingNum = subBarcode.getAppendData("awaiting"); }
if (awaitingNum != null) { int amount = subBarcode.getAmount();
if (opQty < awaitingNum) { int qty = amount - opQty;
throw new ValidateException("smfcore.virtual.quantityError", "取出数量应为[{0}]",new String[]{awaitingNum+""}); if (qty < 0) {
} qty = 0;
}
Integer awaitingNum = subBarcode.getAppendData("awaiting");
if (awaitingNum != null) {
if (opQty < awaitingNum) {
throw new ValidateException("smfcore.virtual.quantityError", "取出数量应为[{0}]", new String[]{awaitingNum + ""});
} }
//出库 }
subBarcode.setAmount(qty); //出库
subBarcode = barcodeManager.save(subBarcode); subBarcode.setAmount(qty);
finishTask(barcode, OP.CHECKOUT, subBarcode, opQty,OP_STATUS.FINISHED.name()); subBarcode = barcodeManager.save(subBarcode);
log.info("条码" + subBarcode.getBarcode() + "[" + subBarcode.getPartNumber() + "]从料盒[" + barcode.getBarcode() + "]出库,数量:" + qty); barcode = finishTask(barcode, OP.CHECKOUT, subBarcode, opQty, OP_STATUS.FINISHED.name(), amount);
log.info("条码" + subBarcode.getBarcode() + "[" + subBarcode.getPartNumber() + "]从料盒[" + barcode.getBarcode() + "]出库,数量:" + qty);
if (pos != null) {
pos.setBarcode(barcode);
storagePosManager.save(pos);
Storage storage = dataCache.getStorageById(pos.getStorageId());
dataCache.addUsedPosList(storage.getCid(),pos);
dataCache.updateInventoryAmount(storage.getCid(), subBarcode.getPartNumber(), -opQty, subBarcode.getBarcode());
} }
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
} }
...@@ -285,7 +324,7 @@ public class VirtualOperateController { ...@@ -285,7 +324,7 @@ public class VirtualOperateController {
String describe = paramMap.get("describe"); String describe = paramMap.get("describe");
//判断料箱是否存在 //判断料箱是否存在
Barcode barcode = codeResolve.resolveOneValideBarcode("=1x1="+boxStr); Barcode barcode = codeResolve.resolveOneValideBarcode("=1x1=" + boxStr);
if (barcode == null) { if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{boxStr}); throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{boxStr});
} }
...@@ -293,6 +332,13 @@ public class VirtualOperateController { ...@@ -293,6 +332,13 @@ public class VirtualOperateController {
if (StringUtils.isNotEmpty(barcode.getPosName())) { if (StringUtils.isNotEmpty(barcode.getPosName())) {
throw new ValidateException("smfcore.materialBox.inPos", "物料已在库位{0}中", new String[]{barcode.getPosName()}); throw new ValidateException("smfcore.materialBox.inPos", "物料已在库位{0}中", new String[]{barcode.getPosName()});
} }
String hostBarcodeId = barcode.getHostBarcodeId();
if (StringUtils.isNotEmpty(hostBarcodeId)) {
Barcode hostBarcode = barcodeManager.get(hostBarcodeId);
if (hostBarcode != null) {
throw new ValidateException("smfcore.materialBox.inOtherBox", "物料已在料盒{0}中", new String[]{hostBarcode.getBarcode()});
}
}
//判断库位是否存在 //判断库位是否存在
StoragePos pos = storagePosManager.getByPosName(posNameStr); StoragePos pos = storagePosManager.getByPosName(posNameStr);
if (pos == null) { if (pos == null) {
...@@ -307,20 +353,28 @@ public class VirtualOperateController { ...@@ -307,20 +353,28 @@ public class VirtualOperateController {
if (!storage.isVirtual()) { if (!storage.isVirtual()) {
throw new ValidateException("smfcore.pos.noVirtual", "[{0}]不是虚拟仓的库位", new String[]{posNameStr}); throw new ValidateException("smfcore.pos.noVirtual", "[{0}]不是虚拟仓的库位", new String[]{posNameStr});
} }
barcode.setDescribe(describe); barcode.setMemo(describe);
List<Barcode> subCodeList = barcode.getSubCodeList(); List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList != null && !subCodeList.isEmpty()) { if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) { for (Barcode subCode : subCodeList) {
Integer awaiting = subCode.getAppendData("awaiting"); Integer awaiting = subCode.getAppendData("awaiting");
if (awaiting != null) { if (awaiting != null) {
barcode = finishTask(barcode, OP.CHECKOUT, subCode, awaiting, OP_STATUS.CANCEL.name()); barcode = finishTask(barcode, OP.CHECKOUT, subCode, awaiting, OP_STATUS.CANCEL.name(), subCode.getAmount());
} }
} }
} }
//开始入库 //开始入库
taskService.addTaskToFinished(pos, barcode, SecurityUtils.getLoginUsername()); taskService.addTaskToFinished(pos, barcode, SecurityUtils.getLoginUsername());
//同时更新subCode的缓存信息
if (subCodeList != null && !subCodeList.isEmpty()) {
for (Barcode subCode : subCodeList) {
dataCache.updateInventoryAmount(storage.getCid(),subCode.getPartNumber(),subCode.getAmount(),subCode.getBarcode());
}
}
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
} }
...@@ -330,7 +384,7 @@ public class VirtualOperateController { ...@@ -330,7 +384,7 @@ public class VirtualOperateController {
public ResultBean boxOutFromPosName(@RequestBody Map<String, String> paramMap) { public ResultBean boxOutFromPosName(@RequestBody Map<String, String> paramMap) {
String boxStr = paramMap.get("boxStr"); String boxStr = paramMap.get("boxStr");
//判断料箱是否存在 //判断料箱是否存在
Barcode barcode = codeResolve.resolveOneValideBarcode("=1x1="+boxStr); Barcode barcode = codeResolve.resolveOneValideBarcode("=1x1=" + boxStr);
if (barcode == null) { if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{boxStr}); throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{boxStr});
} }
...@@ -340,45 +394,19 @@ public class VirtualOperateController { ...@@ -340,45 +394,19 @@ public class VirtualOperateController {
throw new ValidateException("smfcore.virtual.posNoBarcode", "[{0}]不在库位中", new String[]{barcode.getBarcode()}); throw new ValidateException("smfcore.virtual.posNoBarcode", "[{0}]不在库位中", new String[]{barcode.getBarcode()});
} }
Storage storage = dataCache.getStorageById(pos.getStorageId()); Storage storage = dataCache.getStorageById(pos.getStorageId());
if (!storage.isVirtual()){ if (!storage.isVirtual()) {
throw new ValidateException("smfcore.virtual.barcodeNotExistVirtualPos", "[{0}]库位为[{1}],不属于虚拟仓库位", new String[]{barcode.getBarcode(),pos.getPosName()}); throw new ValidateException("smfcore.virtual.barcodeNotExistVirtualPos", "[{0}]库位为[{1}],不属于虚拟仓库位", new String[]{barcode.getBarcode(), pos.getPosName()});
} }
//开始入库 //开始入库
taskService.addTaskToFinished(pos, barcode, SecurityUtils.getLoginUsername()); taskService.addTaskToFinished(pos, barcode, SecurityUtils.getLoginUsername());
return ResultBean.newOkResult(""); dataCache.addUsedPosList(storage.getCid(),pos);
} //同时更新subCode的缓存信息
List<Barcode> subCodeList = barcode.getSubCodeList();
@ApiOperation("取出物料") if (subCodeList != null && !subCodeList.isEmpty()) {
@PostMapping("exeOut") for (Barcode subCode : subCodeList) {
//@PreAuthorize("@el.check('materialBox')") dataCache.updateInventoryAmount(storage.getCid(),subCode.getPartNumber(),-subCode.getAmount(),subCode.getBarcode());
public ResultBean exeOut(@RequestBody Map<String, String> paramMap) { }
String code = paramMap.get("barcode");//料盒条码
String subPN = paramMap.get("subPN");//物料条码
String qtyStr = paramMap.get("qty");//数量
Barcode barcode = barcodeManager.findByBarcode(code);
if (barcode == null) {
throw new ValidateException("smfcore.error.barcode.invalid", "{0}不是有效的条码", new String[]{code});
}
Barcode subBarcode = barcode.getSubCode(subPN);
if (subBarcode == null) {
throw new ValidateException("smfcore.materialBox.noReel", "料盒中未找到对应物料");
}
int opQty = Integer.valueOf(qtyStr);
int oldAmount = subBarcode.getAmount();
if (oldAmount < opQty) {
throw new ValidateException("smfcore.materialBox.quantityshort", "物料数量不足");
} }
int newAmount = oldAmount - opQty;
subBarcode.setAmount(newAmount);
subBarcode = barcodeManager.save(subBarcode);
finishTask(barcode, OP.CHECKOUT, subBarcode, opQty,OP_STATUS.FINISHED.name());
log.info(subBarcode.getPartNumber() + "从料盒[" + barcode.getPosName() + "]出库,物料数量:" + oldAmount + " - " + opQty + " = " + newAmount);
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
} }
...@@ -431,12 +459,12 @@ public class VirtualOperateController { ...@@ -431,12 +459,12 @@ public class VirtualOperateController {
if (storagePosList != null && !storagePosList.isEmpty()) { if (storagePosList != null && !storagePosList.isEmpty()) {
for (StoragePos pos : storagePosList) { for (StoragePos pos : storagePosList) {
Barcode barcode = pos.getBarcode(); Barcode barcode = pos.getBarcode();
if (barcode != null){ if (barcode != null) {
//COMPONENT_TYPE.FIXTURE 为料箱数据 //COMPONENT_TYPE.FIXTURE 为料箱数据
if (barcode.getType() == COMPONENT_TYPE.FIXTURE){ if (barcode.getType() == COMPONENT_TYPE.FIXTURE) {
boxCount ++; boxCount++;
} else { } else {
reelCount ++; reelCount++;
} }
} }
} }
...@@ -444,30 +472,30 @@ public class VirtualOperateController { ...@@ -444,30 +472,30 @@ public class VirtualOperateController {
//获取到进入出入库数据 //获取到进入出入库数据
Date startDate = DateUtil.addDaysFromToday(0); Date startDate = DateUtil.addDaysFromToday(0);
Date endDate = DateUtil.addDays(startDate,1); Date endDate = DateUtil.addDays(startDate, 1);
c = Criteria.where("createDate").gte(startDate).lt(endDate).and("status").in(OP_STATUS.FINISHED.name(),OP_STATUS.END.name()); c = Criteria.where("createDate").gte(startDate).lt(endDate).and("status").in(OP_STATUS.FINISHED.name(), OP_STATUS.END.name());
q = new Query(c); q = new Query(c);
q.fields().include("storageId","sourceType"); q.fields().include("storageId", "sourceType", "type");
List<DataLog> dataLogList = dataLogManager.findByQuery(q); List<DataLog> dataLogList = dataLogManager.findByQuery(q);
if (dataLogList != null && !dataLogList.isEmpty()){ if (dataLogList != null && !dataLogList.isEmpty()) {
for (DataLog dataLog : dataLogList) { for (DataLog dataLog : dataLogList) {
String storageId = dataLog.getStorageId(); String storageId = dataLog.getStorageId();
if (StringUtils.isNotEmpty(storageId)){ if (StringUtils.isNotEmpty(storageId)) {
Storage storage = dataCache.getStorageById(storageId); Storage storage = dataCache.getStorageById(storageId);
if (storage.isVirtual()) { if (storage.isVirtual()) {
if (dataLog.isCheckOutTask()){ if (dataLog.isCheckOutTask()) {
todayOutCount ++; todayOutCount++;
} else { } else {
todayInCount ++; todayInCount++;
} }
continue; continue;
} }
} }
if (BARCODE_SOURCE.VIRTUAL.equals(dataLog.getSourceType())){ if (BARCODE_SOURCE.VIRTUAL.equals(dataLog.getSourceType())) {
if (dataLog.isCheckOutTask()){ if (dataLog.isCheckOutTask()) {
todayOutCount ++; todayOutCount++;
} else { } else {
todayInCount ++; todayInCount++;
} }
} }
} }
...@@ -480,31 +508,45 @@ public class VirtualOperateController { ...@@ -480,31 +508,45 @@ public class VirtualOperateController {
return ResultBean.newOkResult(resultMap); return ResultBean.newOkResult(resultMap);
} }
/** /**
* 完成出入库任务 * 完成出入库任务
*
* @param pidBarcode 料箱 * @param pidBarcode 料箱
* @param subBarcode 箱内物料 * @param subBarcode 箱内物料
* @param opQty 数量 * @param opQty 数量
* @throws ValidateException*/ * @throws ValidateException
*/
private Barcode finishTask(Barcode pidBarcode, int opType, Barcode subBarcode, int opQty,String status) throws ValidateException { private Barcode finishTask(Barcode pidBarcode, int opType, Barcode subBarcode, int opQty, String status, int amount) throws ValidateException {
String orderItemId = subBarcode.getAppendData("orderItemId"); String orderItemId = subBarcode.getAppendData("orderItemId");
String orderNo = subBarcode.getAppendData("orderNo"); String orderNo = subBarcode.getAppendData("orderNo");
String orderId = subBarcode.getAppendData("orderId"); String orderId = subBarcode.getAppendData("orderId");
subBarcode.updateAppendData("orderItemId",null); subBarcode.updateAppendData("orderItemId", null);
subBarcode.updateAppendData("orderNo",null); subBarcode.updateAppendData("orderNo", null);
subBarcode.updateAppendData("orderId",null); subBarcode.updateAppendData("orderId", null);
subBarcode.updateAppendData("awaiting",null); subBarcode.updateAppendData("awaiting", null);
barcodeManager.save(subBarcode); barcodeManager.save(subBarcode);
//更新barcode缓存 //更新barcode缓存
pidBarcode.UpdateSubCode(subBarcode); pidBarcode.UpdateSubCode(subBarcode);
if (opType == OP.CHECKOUT && subBarcode.getAmount() <= 0) {
if (subBarcode.getAmount() <= 0) {
if (subBarcode.isAutoCreate()){
barcodeManager.delete(subBarcode);
} else {
subBarcode.setHostBarcodeId("");
subBarcode.setPosName("");
subBarcode.setAmount(amount);
barcodeManager.save(subBarcode);
}
}
/*if (opType == OP.CHECKOUT && subBarcode.getAmount() <= 0) {
//数量为0直接删除 //数量为0直接删除
barcodeManager.delete(subBarcode); barcodeManager.delete(subBarcode);
} }*/
barcodeManager.saveBarcode(pidBarcode); barcodeManager.saveBarcode(pidBarcode);
DataLog task = new DataLog(); DataLog task = new DataLog();
task.setStatus(status); task.setStatus(status);
...@@ -520,24 +562,25 @@ public class VirtualOperateController { ...@@ -520,24 +562,25 @@ public class VirtualOperateController {
task.setPosName(pidBarcode.getBarcode()); task.setPosName(pidBarcode.getBarcode());
task.setOperator(SecurityUtils.getLoginUsername()); task.setOperator(SecurityUtils.getLoginUsername());
task.setSourceType(BARCODE_SOURCE.VIRTUAL); task.setSourceType(BARCODE_SOURCE.VIRTUAL);
if (StringUtils.isNotEmpty(orderItemId)){ if (StringUtils.isNotEmpty(orderItemId)) {
task.setSubSourceId(orderItemId); task.setSubSourceId(orderItemId);
} }
if (StringUtils.isNotEmpty(orderNo)){ if (StringUtils.isNotEmpty(orderNo)) {
task.setSourceName(orderNo); task.setSourceName(orderNo);
} }
if (StringUtils.isNotEmpty(orderId)){ if (StringUtils.isNotEmpty(orderId)) {
task.setSourceId(orderId); task.setSourceId(orderId);
} }
task = dataLogManager.save(task); task = dataLogManager.save(task);
taskService.updateFinishedTask(task); taskService.updateFinishedTask(task);
//dataCache.updateInventoryAmount(getVirtialCid(),task.getPartNumber(),opQty,task.getBarcode());
return pidBarcode; return pidBarcode;
} }
private Barcode autoGetBarcode(Barcode barcode,Component component, String pnStr,int opQty){ private Barcode autoGetBarcode(Barcode barcode, Component component, String pnStr, int opQty) {
//条码设置为P+PosId+C+ComponentId //条码设置为P+PosId+C+ComponentId
String barcodeStr = "P" + barcode.getId() + "C" + component.getId(); String barcodeStr = ShortUniqueCodeUtil.generate().toUpperCase(Locale.ROOT);
Barcode subBarcode = barcodeManager.findByBarcode(barcodeStr); Barcode subBarcode = barcodeManager.findByBarcode(barcodeStr);
if (subBarcode == null) { if (subBarcode == null) {
//不存在,需要创建条码和库位 //不存在,需要创建条码和库位
subBarcode = new Barcode(); subBarcode = new Barcode();
...@@ -552,13 +595,14 @@ public class VirtualOperateController { ...@@ -552,13 +595,14 @@ public class VirtualOperateController {
subBarcode.updateSluggishTime(dataCache.getPNsluggishDay(barcode.getPartNumber())); subBarcode.updateSluggishTime(dataCache.getPNsluggishDay(barcode.getPartNumber()));
subBarcode.setCheckOutDate(null, ""); subBarcode.setCheckOutDate(null, "");
subBarcode.setHostBarcodeId(barcode.getId()); subBarcode.setHostBarcodeId(barcode.getId());
subBarcode.setAutoCreate(true);
subBarcode = barcodeManager.save(subBarcode); subBarcode = barcodeManager.save(subBarcode);
return subBarcode; return subBarcode;
} }
private Component autoGetComponent(String pnStr,int opQty){ private Component autoGetComponent(String pnStr, int opQty) {
Component component = componentManager.findOneByPN(pnStr); Component component = componentManager.findOneByPN(pnStr);
if(component == null){ if (component == null) {
component = new Component(); component = new Component();
component.setHeight(1); component.setHeight(1);
component.setPartNumber(pnStr); component.setPartNumber(pnStr);
...@@ -569,5 +613,4 @@ public class VirtualOperateController { ...@@ -569,5 +613,4 @@ public class VirtualOperateController {
} }
return component; return component;
} }
} }
package com.neotel.smfcore.core.virtual.util;
import java.util.concurrent.atomic.AtomicInteger;
public class ShortUniqueCodeUtil {
// 使用36进制(0-9,a-z)可以表示更多组合
private static final int RADIX = 36;
// 最后时间戳和序列号
private static volatile long lastTimestamp = 0L;
private static final AtomicInteger sequence = new AtomicInteger(0);
// 序列号最大值(保留2位36进制数)
private static final int MAX_SEQUENCE = RADIX * RADIX;
/**
* 生成6位不重复的唯一码
*
* @return 6位36进制的唯一码(包含数字和小写字母)
*/
public static synchronized String generate() {
long currentTime = System.currentTimeMillis();
// 如果同一毫秒内,增加序列号
if (currentTime == lastTimestamp) {
int seq = sequence.incrementAndGet();
if (seq >= MAX_SEQUENCE) {
// 序列号用尽,等待到下一毫秒
while (currentTime <= lastTimestamp) {
currentTime = System.currentTimeMillis();
}
sequence.set(0);
}
} else {
sequence.set(0);
}
lastTimestamp = currentTime;
// 将时间戳和序列号转换为36进制字符串
String timePart = Long.toString(currentTime, RADIX);
String seqPart = String.format("%02d", sequence.get());
// 组合并确保长度为6
String fullCode = timePart + seqPart;
if (fullCode.length() > 6) {
fullCode = fullCode.substring(fullCode.length() - 6);
} else if (fullCode.length() < 6) {
fullCode = String.format("%6s", fullCode).replace(' ', '0');
}
return fullCode;
}
}
...@@ -182,8 +182,8 @@ public class FujiApi extends BaseSmfApiListener { ...@@ -182,8 +182,8 @@ public class FujiApi extends BaseSmfApiListener {
*/ */
public String getAccessToken() { public String getAccessToken() {
Map<String, Object> paramMap = new HashMap<>(); Map<String, Object> paramMap = new HashMap<>();
paramMap.put("userName", FujiUrlConfig.userName); paramMap.put("userName", getAuthUserName());
paramMap.put("password", FujiUrlConfig.password); paramMap.put("password", getAuthPassword());
String paramStr = JSON.toJSONString(paramMap); String paramStr = JSON.toJSONString(paramMap);
log.info("获取Fuji的token参数为:" + paramStr); log.info("获取Fuji的token参数为:" + paramStr);
String accessToken = ""; String accessToken = "";
...@@ -218,6 +218,22 @@ public class FujiApi extends BaseSmfApiListener { ...@@ -218,6 +218,22 @@ public class FujiApi extends BaseSmfApiListener {
return config.getAuthUrl(); return config.getAuthUrl();
} }
private String getAuthUserName(){
FujiConfig config = dataCache.getCache(FujiCacheConfig.FujiConfig_Cache_Name);
if (config == null) {
config = new FujiConfig();
}
return config.getUserName();
}
private String getAuthPassword(){
FujiConfig config = dataCache.getCache(FujiCacheConfig.FujiConfig_Cache_Name);
if (config == null) {
config = new FujiConfig();
}
return config.getPassword();
}
private String getInventoryDids(){ private String getInventoryDids(){
FujiConfig config = dataCache.getCache(FujiCacheConfig.FujiConfig_Cache_Name); FujiConfig config = dataCache.getCache(FujiCacheConfig.FujiConfig_Cache_Name);
if (config == null) { if (config == null) {
......
...@@ -7,6 +7,8 @@ import java.util.Date; ...@@ -7,6 +7,8 @@ import java.util.Date;
@Data @Data
public class FujiConfig { public class FujiConfig {
private String authUrl = ""; private String authUrl = "";
private String userName = "";
private String password = "";
private String getDidInfoUrl = ""; private String getDidInfoUrl = "";
private String registerDidInfoUrl = ""; private String registerDidInfoUrl = "";
private String result = ""; private String result = "";
......
...@@ -7,9 +7,9 @@ public class FujiUrlConfig { ...@@ -7,9 +7,9 @@ public class FujiUrlConfig {
//private static final String baseUrl = "http://175.41.238.212/fujiopenwebapi/api/v1"; //private static final String baseUrl = "http://175.41.238.212/fujiopenwebapi/api/v1";
public static final String userName = "Neotel"; //public static final String userName = "Neotel";
public static final String password = "Neotel"; //public static final String password = "Neotel";
//private static final String authLogin = "/auth/login"; //private static final String authLogin = "/auth/login";
......
...@@ -62,6 +62,8 @@ public class FujiController { ...@@ -62,6 +62,8 @@ public class FujiController {
config.setInputEto(newConfig.getInputEto()); config.setInputEto(newConfig.getInputEto());
config.setOutputEtn(newConfig.getOutputEtn()); config.setOutputEtn(newConfig.getOutputEtn());
config.setTime(newConfig.getTime()); config.setTime(newConfig.getTime());
config.setUserName(newConfig.getUserName());
config.setPassword(newConfig.getPassword());
dataCache.updateCache(FujiCacheConfig.FujiConfig_Cache_Name, config); dataCache.updateCache(FujiCacheConfig.FujiConfig_Cache_Name, config);
return ResultBean.newOkResult(""); return ResultBean.newOkResult("");
} }
...@@ -85,6 +87,8 @@ public class FujiController { ...@@ -85,6 +87,8 @@ public class FujiController {
dto.setTime(config.getTime()); dto.setTime(config.getTime());
dto.setEtnUpdateDateStr(getUpdateDate(config.getOutputEtn())); dto.setEtnUpdateDateStr(getUpdateDate(config.getOutputEtn()));
dto.setEtoUpdateDateStr(getUpdateDate(config.getInputEto())); dto.setEtoUpdateDateStr(getUpdateDate(config.getInputEto()));
dto.setUserName(config.getUserName());
dto.setPassword(config.getPassword());
return ResultBean.newOkResult(dto); return ResultBean.newOkResult(dto);
} }
......
...@@ -58,4 +58,9 @@ public class UserDto implements Serializable { ...@@ -58,4 +58,9 @@ public class UserDto implements Serializable {
@ApiModelProperty("语言名称:简体中文,繁体中文 等") @ApiModelProperty("语言名称:简体中文,繁体中文 等")
private String lanName; private String lanName;
@ApiModelProperty("激活码")
private String checkCode;
@ApiModelProperty("是否启用")
private boolean active = false;
} }
...@@ -238,6 +238,15 @@ public class UserManagerImpl implements IUserManager { ...@@ -238,6 +238,15 @@ public class UserManagerImpl implements IUserManager {
dtos.get(i).setRoleName(role.getName()); dtos.get(i).setRoleName(role.getName());
} }
} }
String username = dtos.get(i).getUsername();
String checkCode = dtos.get(i).getCheckCode();
if (Constants.SUPER_USERNAME.equals(username)){
dtos.get(i).setActive(true);
} else {
if (StringUtils.isNotEmpty(checkCode)){
dtos.get(i).setActive(true);
}
}
} }
return dtos; return dtos;
} }
......
...@@ -433,4 +433,5 @@ smfcore.virtualLocationManager=\u865A\u62DF\u5E93\u4F4D\u7BA1\u7406 ...@@ -433,4 +433,5 @@ smfcore.virtualLocationManager=\u865A\u62DF\u5E93\u4F4D\u7BA1\u7406
smfcore.virtualOperations=\u865A\u62DF\u4ED3\u64CD\u4F5C smfcore.virtualOperations=\u865A\u62DF\u4ED3\u64CD\u4F5C
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}]\u5DF2\u5728\u5E93\u4F4D[{1}]\u4E2D,\u8BF7\u5148\u53D6\u51FA smfcore.virtual.boxInPos=[{0}]\u5DF2\u5728\u5E93\u4F4D[{1}]\u4E2D,\u8BF7\u5148\u53D6\u51FA
smfcore.virtual.quantityError=\u53D6\u51FA\u6570\u91CF\u5E94\u4E3A[{0}]
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=\u53D6\u51FA\u6570\u91CF\u5E94\u4E3A[{0}]
smfcode.virtual.enter=\u8BF7\u626B\u63CF\u6216\u8F93\u5165\u6761\u7801\u540E\u6309\u56DE\u8F66\u786E\u8BA4
\ No newline at end of file \ No newline at end of file
...@@ -423,4 +423,5 @@ smfcore.virtualLocationManager=Verwaltung virtueller Lagerpl\u00E4tze ...@@ -423,4 +423,5 @@ smfcore.virtualLocationManager=Verwaltung virtueller Lagerpl\u00E4tze
smfcore.virtualOperations=Vorg\u00E4nge im virtuellen Lager smfcore.virtualOperations=Vorg\u00E4nge im virtuellen Lager
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}] befindet sich bereits im Lagerplatz [{1}]. Bitte entnehmen Sie es zuerst smfcore.virtual.boxInPos=[{0}] befindet sich bereits im Lagerplatz [{1}]. Bitte entnehmen Sie es zuerst
smfcore.virtual.quantityError=Die zu entnehmende Menge sollte [{0}] betragen
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=Die zu entnehmende Menge sollte [{0}] betragen
smfcode.virtual.enter=Bitte scannen Sie den Barcode oder geben Sie ihn ein und best\u00E4tigen Sie mit Enter
\ No newline at end of file \ No newline at end of file
...@@ -146,7 +146,7 @@ smfcore.translation=Resource Translation ...@@ -146,7 +146,7 @@ smfcore.translation=Resource Translation
smfcore.languageCanotNull=Language type cannot be empty smfcore.languageCanotNull=Language type cannot be empty
smfcore.noLanguageSetAccess=No permission to edit the language smfcore.noLanguageSetAccess=No permission to edit the language
smfcore.languageCanotRemoveAll=Cannot delete all languages smfcore.languageCanotRemoveAll=Cannot delete all languages
smfcore.solderPaste=Solder Paste smfcore.solderPaste=Solder Paste Management
smfcore.solderPasteKanban=Equipment Overview smfcore.solderPasteKanban=Equipment Overview
smfcore.solderPasteManage=Inventory smfcore.solderPasteManage=Inventory
smfcore.solderPasteData=Traceability smfcore.solderPasteData=Traceability
...@@ -424,4 +424,5 @@ smfcore.virtualLocationManager=Virtual Location Mgmt ...@@ -424,4 +424,5 @@ smfcore.virtualLocationManager=Virtual Location Mgmt
smfcore.virtualOperations=Virtual Storage Op smfcore.virtualOperations=Virtual Storage Op
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}] is already in location [{1}]. Please remove it first smfcore.virtual.boxInPos=[{0}] is already in location [{1}]. Please remove it first
smfcore.virtual.quantityError=The quantity to be removed should be [{0}]
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=The quantity to be removed should be [{0}]
smfcode.virtual.enter=Please scan or enter the barcode, then press Enter
\ No newline at end of file \ No newline at end of file
...@@ -423,4 +423,5 @@ smfcore.virtualLocationManager=Gestion des emplacements virtuels ...@@ -423,4 +423,5 @@ smfcore.virtualLocationManager=Gestion des emplacements virtuels
smfcore.virtualOperations=Op\u00E9rations de l'entrep\u00F4t virtuel smfcore.virtualOperations=Op\u00E9rations de l'entrep\u00F4t virtuel
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}] est d\u00E9j\u00E0 dans l'emplacement [{1}]. Veuillez d'abord le retirer smfcore.virtual.boxInPos=[{0}] est d\u00E9j\u00E0 dans l'emplacement [{1}]. Veuillez d'abord le retirer
smfcore.virtual.quantityError=La quantit\u00E9 \u00E0 retirer doit \u00EAtre [{0}]
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=La quantit\u00E9 \u00E0 retirer doit \u00EAtre [{0}]
smfcode.virtual.enter=Veuillez scanner ou saisir le code-barres, puis appuyer sur Entr\u00E9e
\ No newline at end of file \ No newline at end of file
...@@ -420,4 +420,5 @@ smfcore.virtualLocationManager=\u4EEE\u60F3\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\ ...@@ -420,4 +420,5 @@ smfcore.virtualLocationManager=\u4EEE\u60F3\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3\
smfcore.virtualOperations=\u4EEE\u60F3\u5009\u5EAB\u64CD\u4F5C smfcore.virtualOperations=\u4EEE\u60F3\u5009\u5EAB\u64CD\u4F5C
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}] \u306F\u65E2\u306B\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3 [{1}] \u306B\u3042\u308A\u307E\u3059\u3002\u5148\u306B\u53D6\u308A\u51FA\u3057\u3066\u304F\u3060\u3055\u3044 smfcore.virtual.boxInPos=[{0}] \u306F\u65E2\u306B\u30ED\u30B1\u30FC\u30B7\u30E7\u30F3 [{1}] \u306B\u3042\u308A\u307E\u3059\u3002\u5148\u306B\u53D6\u308A\u51FA\u3057\u3066\u304F\u3060\u3055\u3044
smfcore.virtual.quantityError=\u53D6\u308A\u51FA\u3057\u6570\u91CF\u306F[{0}]\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=\u53D6\u308A\u51FA\u3057\u6570\u91CF\u306F[{0}]\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
smfcode.virtual.enter=\u30D0\u30FC\u30B3\u30FC\u30C9\u3092\u30B9\u30AD\u30E3\u30F3\u3001\u307E\u305F\u306F\u5165\u529B\u5F8C\u3001Enter\u30AD\u30FC\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044
\ No newline at end of file \ No newline at end of file
...@@ -420,4 +420,5 @@ smfcore.virtualLocationManager=\u865A\u62DF\u5E93\u4F4D\u7BA1\u7406 ...@@ -420,4 +420,5 @@ smfcore.virtualLocationManager=\u865A\u62DF\u5E93\u4F4D\u7BA1\u7406
smfcore.virtualOperations=\u865A\u62DF\u4ED3\u64CD\u4F5C smfcore.virtualOperations=\u865A\u62DF\u4ED3\u64CD\u4F5C
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}]\u5DF2\u5728\u5E93\u4F4D[{1}]\u4E2D,\u8BF7\u5148\u53D6\u51FA smfcore.virtual.boxInPos=[{0}]\u5DF2\u5728\u5E93\u4F4D[{1}]\u4E2D,\u8BF7\u5148\u53D6\u51FA
smfcore.virtual.quantityError=\u53D6\u51FA\u6570\u91CF\u5E94\u4E3A[{0}]
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=\u53D6\u51FA\u6570\u91CF\u5E94\u4E3A[{0}]
smfcode.virtual.enter=\u8BF7\u626B\u63CF\u6216\u8F93\u5165\u6761\u7801\u540E\u6309\u56DE\u8F66\u786E\u8BA4
\ No newline at end of file \ No newline at end of file
...@@ -420,4 +420,5 @@ smfcore.virtualLocationManager=\u865B\u64EC\u5EAB\u4F4D\u7BA1\u7406 ...@@ -420,4 +420,5 @@ smfcore.virtualLocationManager=\u865B\u64EC\u5EAB\u4F4D\u7BA1\u7406
smfcore.virtualOperations=\u865B\u64EC\u5009\u64CD\u4F5C smfcore.virtualOperations=\u865B\u64EC\u5009\u64CD\u4F5C
smfcore.equipment.view.ncgroup=Neo Counter smfcore.equipment.view.ncgroup=Neo Counter
smfcore.virtual.boxInPos=[{0}]\u5DF2\u5728\u5EAB\u4F4D[{1}]\u4E2D,\u8ACB\u5148\u53D6\u51FA smfcore.virtual.boxInPos=[{0}]\u5DF2\u5728\u5EAB\u4F4D[{1}]\u4E2D,\u8ACB\u5148\u53D6\u51FA
smfcore.virtual.quantityError=\u53D6\u51FA\u6578\u91CF\u61C9\u70BA[{0}]
\ No newline at end of file \ No newline at end of file
smfcore.virtual.quantityError=\u53D6\u51FA\u6578\u91CF\u61C9\u70BA[{0}]
smfcode.virtual.enter=\u8ACB\u6383\u63CF\u6216\u8F38\u5165\u689D\u78BC\u5F8C\u6309\u56DE\u8ECA\u78BA\u8A8D
\ No newline at end of file \ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!