Commit 9c5e4fc6 LN

Merge remote-tracking branch 'origin/master'

2 个父辈 4ece61d5 4b69d55c
...@@ -99,8 +99,19 @@ public class DateUtil { ...@@ -99,8 +99,19 @@ public class DateUtil {
} catch (Exception pe) { } catch (Exception pe) {
log.error("Parse ["+strDate+"] to date Exception: " + pe.getMessage()); log.error("Parse ["+strDate+"] to date Exception: " + pe.getMessage());
//throw new ParseException(pe.getMessage(), pe.getErrorOffset()); //throw new ParseException(pe.getMessage(), pe.getErrorOffset());
date = null;
}
if (date == null){
try {
df.setLenient(true);
date = df.parse(strDate);
} catch (Exception pe) {
log.error("Parse ["+strDate+"] to date Exception: " + pe.getMessage());
//throw new ParseException(pe.getMessage(), pe.getErrorOffset());
return null; return null;
} }
}
return (date); return (date);
} }
......
...@@ -672,6 +672,7 @@ public class BarcodeRule { ...@@ -672,6 +672,7 @@ public class BarcodeRule {
b.setMemo(memo); b.setMemo(memo);
} }
reelId = reelId.trim();
b.setBarcode(reelId); b.setBarcode(reelId);
codeBean.setCodeStr(reelId); codeBean.setCodeStr(reelId);
partNumber = partNumber.trim(); partNumber = partNumber.trim();
......
...@@ -65,8 +65,9 @@ public class ComponentManagerImpl implements IComponentManager { ...@@ -65,8 +65,9 @@ public class ComponentManagerImpl implements IComponentManager {
@Override @Override
public Component findByPartNumberAndProvider(String partNumber, String provider) { public Component findByPartNumberAndProvider(String partNumber, String provider) {
if (StringUtils.isEmpty(partNumber)) if (StringUtils.isEmpty(partNumber)) {
return null; return null;
}
else { else {
Component component = componentDao.findOneByCondition(new String[]{"partNumber", "provider"}, new String[]{partNumber, provider}); Component component = componentDao.findOneByCondition(new String[]{"partNumber", "provider"}, new String[]{partNumber, provider});
if (component == null) { if (component == null) {
......
...@@ -11,6 +11,9 @@ import com.neotel.smfcore.core.barcode.service.po.Barcode; ...@@ -11,6 +11,9 @@ import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.bean.StatusBean; import com.neotel.smfcore.core.device.bean.StatusBean;
import com.neotel.smfcore.core.device.enums.OP; import com.neotel.smfcore.core.device.enums.OP;
import com.neotel.smfcore.core.device.enums.OP_STATUS; import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.message.enums.MessageType;
import com.neotel.smfcore.core.message.service.manager.IMessageManager;
import com.neotel.smfcore.core.message.service.po.Message;
import com.neotel.smfcore.core.order.enums.ORDER_COLOR; import com.neotel.smfcore.core.order.enums.ORDER_COLOR;
import com.neotel.smfcore.core.storage.enums.DeviceType; import com.neotel.smfcore.core.storage.enums.DeviceType;
import com.neotel.smfcore.core.storage.service.po.Storage; import com.neotel.smfcore.core.storage.service.po.Storage;
...@@ -18,9 +21,6 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos; ...@@ -18,9 +21,6 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.bean.OrderSetting; import com.neotel.smfcore.core.system.bean.OrderSetting;
import com.neotel.smfcore.core.system.service.po.DataLog; import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.DevicesStatusUtil; import com.neotel.smfcore.core.system.util.DevicesStatusUtil;
import com.neotel.smfcore.core.system.websocket.MsgType;
import com.neotel.smfcore.core.system.websocket.SocketMsg;
import com.neotel.smfcore.core.system.websocket.WebSocketServer;
import com.neotel.smfcore.security.TokenProvider; import com.neotel.smfcore.security.TokenProvider;
import com.neotel.smfcore.security.annotation.AnonymousAccess; import com.neotel.smfcore.security.annotation.AnonymousAccess;
import com.neotel.smfcore.security.service.manager.IUserManager; import com.neotel.smfcore.security.service.manager.IUserManager;
...@@ -48,6 +48,9 @@ public class NLPShelfHandler extends BaseDeviceHandler { ...@@ -48,6 +48,9 @@ public class NLPShelfHandler extends BaseDeviceHandler {
@Autowired @Autowired
private IUserManager userManager; private IUserManager userManager;
@Autowired
private IMessageManager messageManager;
/** /**
* 扫码 * 扫码
*/ */
...@@ -327,11 +330,24 @@ public class NLPShelfHandler extends BaseDeviceHandler { ...@@ -327,11 +330,24 @@ public class NLPShelfHandler extends BaseDeviceHandler {
} }
} }
//先获取到上一次缓存的信息
List<List<String>> lastDeviceData = DevicesStatusUtil.getDeviceData(cid);
List<String> lastHasReelPosErrorList = new ArrayList<>();
List<String> lastNoReelPosErrorList = new ArrayList<>();
if (lastDeviceData != null && lastDeviceData.size() == 2){
lastHasReelPosErrorList = lastDeviceData.get(0);
lastNoReelPosErrorList = lastDeviceData.get(1);
}
List<List<String>> data = new ArrayList<>(); List<List<String>> data = new ArrayList<>();
data.add(Arrays.asList(hasReelPosErrorList)); data.add(Arrays.asList(hasReelPosErrorList));
data.add(Arrays.asList(noReelPosErrorList)); data.add(Arrays.asList(noReelPosErrorList));
DevicesStatusUtil.updateDeviceData(cid, data); DevicesStatusUtil.updateDeviceData(cid, data);
//在这里进行对比
compareErrorDataWithMessage(cid, lastHasReelPosErrorList, lastNoReelPosErrorList, data.get(0), data.get(1));
List<String> inOkList = new ArrayList<>(); List<String> inOkList = new ArrayList<>();
List<String> inNgList = new ArrayList<>(); List<String> inNgList = new ArrayList<>();
List<String> outOkList = new ArrayList<>(); List<String> outOkList = new ArrayList<>();
...@@ -574,6 +590,95 @@ public class NLPShelfHandler extends BaseDeviceHandler { ...@@ -574,6 +590,95 @@ public class NLPShelfHandler extends BaseDeviceHandler {
return ResultBean.newOkResult(posList); return ResultBean.newOkResult(posList);
} }
private void compareErrorDataWithMessage(String cid,
List<String> lastHasReelPosErrorList, List<String> lastNoReelPosErrorList,
List<String> currentHasReelPosErrorList, List<String> currentNoReelPosErrorList) {
Storage storage = dataCache.getStorage(cid);
// 处理空值
if (lastHasReelPosErrorList == null) lastHasReelPosErrorList = new ArrayList<>();
if (lastNoReelPosErrorList == null) lastNoReelPosErrorList = new ArrayList<>();
if (currentHasReelPosErrorList == null) currentHasReelPosErrorList = new ArrayList<>();
if (currentNoReelPosErrorList == null) currentNoReelPosErrorList = new ArrayList<>();
// 对比有料异常数据
List<String> hasNewErrors = new ArrayList<>();
List<String> hasRecoveredErrors = new ArrayList<>();
List<String> hasPersistentErrors = new ArrayList<>();
for (String item : currentHasReelPosErrorList) {
if (!lastHasReelPosErrorList.contains(item)) {
hasNewErrors.add(item);
} else {
hasPersistentErrors.add(item);
}
}
for (String item : lastHasReelPosErrorList) {
if (!currentHasReelPosErrorList.contains(item)) {
hasRecoveredErrors.add(item);
}
}
// 对比无料异常数据
List<String> noNewErrors = new ArrayList<>();
List<String> noRecoveredErrors = new ArrayList<>();
List<String> noPersistentErrors = new ArrayList<>();
for (String item : currentNoReelPosErrorList) {
if (!lastNoReelPosErrorList.contains(item)) {
noNewErrors.add(item);
} else {
noPersistentErrors.add(item);
}
}
for (String item : lastNoReelPosErrorList) {
if (!currentNoReelPosErrorList.contains(item)) {
noRecoveredErrors.add(item);
}
}
// 打印有料异常日志
if (!hasNewErrors.isEmpty()) {
log.warn("料架[{}] 有料异常(实际有料但数据库无信息) 新增异常库位: {}", cid, String.join(", ", hasNewErrors));
//smfcode.nlp.posHasReelError=库位[{0}]检测到有物料,但系统无库存记录
for (String hasNewError : hasNewErrors) {
Message message = Message.newMsg(MessageType.ERROR.name(), storage.getName(), storage.getId(), hasNewError, "smfcode.nlp.posHasReelError", "库位[{0}]检测到有物料,但系统无库存记录", new String[]{hasNewError});
messageManager.save(message);
}
}
if (!hasRecoveredErrors.isEmpty()) {
log.info("料架[{}] 有料异常(实际有料但数据库无信息) 恢复正常库位: {}", cid, String.join(", ", hasRecoveredErrors));
for (String hasRecoveredError : hasRecoveredErrors) {
//smfcode.nlp.posRecovered=库位[{0}]恢复正常
Message message = Message.newMsg(MessageType.INFO.name(), storage.getName(), storage.getId(), hasRecoveredError, "smfcode.nlp.posRecovered", "库位[{0}]恢复正常", new String[]{hasRecoveredError});
messageManager.save(message);
}
}
if (!hasPersistentErrors.isEmpty()) {
//log.error("⚠️ 料架[{}] 有料异常(实际有料但数据库无信息) 持续异常库位: {}", cid, String.join(", ", hasPersistentErrors));
}
// 打印无料异常日志
if (!noNewErrors.isEmpty()) {
log.warn("料架[{}] 无料异常(实际无料但数据库有信息) 新增异常库位: {}", cid, String.join(", ", noNewErrors));
for (String noNewError : noNewErrors) {
//smfcode.nlp.posNoReelError=库位[{0}]检测到没有物料,但系统有库存记录
Message message = Message.newMsg(MessageType.ERROR.name(), storage.getName(), storage.getId(), noNewError, "smfcode.nlp.posNoReelError", "库位[{0}]检测到没有物料,但系统有库存记录", new String[]{noNewError});
messageManager.save(message);
}
}
if (!noRecoveredErrors.isEmpty()) {
log.info("料架[{}] 无料异常(实际无料但数据库有信息) 恢复正常库位: {}", cid, String.join(", ", noRecoveredErrors));
for (String noRecoveredError : noRecoveredErrors) {
//smfcode.nlp.posRecovered=库位[{0}]恢复正常
Message message = Message.newMsg(MessageType.INFO.name(), storage.getName(), storage.getId(), noRecoveredError, "smfcode.nlp.posRecovered", "库位[{0}]恢复正常", new String[]{noRecoveredError});
messageManager.save(message);
}
}
if (!noPersistentErrors.isEmpty()) {
//log.error("⚠️ 料架[{}] 无料异常(实际无料但数据库有信息) 持续异常库位: {}", cid, String.join(", ", noPersistentErrors));
}
}
@Override @Override
public DeviceType getDeviceType() { public DeviceType getDeviceType() {
return DeviceType.NLP; return DeviceType.NLP;
......
...@@ -17,6 +17,7 @@ import com.neotel.smfcore.core.device.util.DataCache; ...@@ -17,6 +17,7 @@ import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.kanban.rest.bean.dto.*; import com.neotel.smfcore.core.kanban.rest.bean.dto.*;
import com.neotel.smfcore.core.kanban.rest.bean.mapstruct.BoxTaskMapper; import com.neotel.smfcore.core.kanban.rest.bean.mapstruct.BoxTaskMapper;
import com.neotel.smfcore.core.kanban.rest.bean.query.BoxTaskQueryCriter; import com.neotel.smfcore.core.kanban.rest.bean.query.BoxTaskQueryCriter;
import com.neotel.smfcore.core.kanban.rest.utils.NaturalOrderComparator;
import com.neotel.smfcore.core.message.util.DeviceMessageUtil; import com.neotel.smfcore.core.message.util.DeviceMessageUtil;
import com.neotel.smfcore.core.msd.bean.MSDSettiings; import com.neotel.smfcore.core.msd.bean.MSDSettiings;
import com.neotel.smfcore.core.solder.util.SolderBoxCache; import com.neotel.smfcore.core.solder.util.SolderBoxCache;
...@@ -107,7 +108,7 @@ public class BoxKanbanController { ...@@ -107,7 +108,7 @@ public class BoxKanbanController {
} }
} }
if(boxStatusDtos.size()>0){ if(boxStatusDtos.size()>0){
boxStatusDtos = boxStatusDtos.stream().sorted(Comparator.comparing(BoxStatusDto :: getName)).collect(Collectors.toList()); boxStatusDtos = boxStatusDtos.stream().sorted(Comparator.comparing(BoxStatusDto :: getName, new NaturalOrderComparator())).collect(Collectors.toList());
GroupStatusDto groupStatusDto = new GroupStatusDto(group.getId(),group.getGroupName(),boxStatusDtos,groupType); GroupStatusDto groupStatusDto = new GroupStatusDto(group.getId(),group.getGroupName(),boxStatusDtos,groupType);
groupStatusDtos.add(groupStatusDto); groupStatusDtos.add(groupStatusDto);
} }
......
package com.neotel.smfcore.core.kanban.rest.utils;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 自然排序比较器:字母按字典序,数字按数值大小排序
*/
public class NaturalOrderComparator implements Comparator<String> {
// 正则表达式:拆分字符串为"非数字"和"数字"交替的部分
private static final Pattern PATTERN = Pattern.compile("(\\D+)|(\\d+)");
@Override
public int compare(String s1, String s2) {
if (s1 == null && s2 == null) return 0;
if (s1 == null) return -1; // null放前面
if (s2 == null) return 1;
Matcher m1 = PATTERN.matcher(s1);
Matcher m2 = PATTERN.matcher(s2);
// 逐个匹配"非数字/数字"片段并比较
while (m1.find() && m2.find()) {
String group1 = m1.group();
String group2 = m2.group();
// 判断当前片段是数字还是非数字
if (group1.matches("\\d+") && group2.matches("\\d+")) {
// 数字片段:按数值大小比较(避免"10" < "2"的字符串排序问题)
Long num1 = Long.parseLong(group1);
Long num2 = Long.parseLong(group2);
int numCompare = num1.compareTo(num2);
if (numCompare != 0) {
return numCompare;
}
} else {
// 非数字片段:按字典序比较
int strCompare = group1.compareTo(group2);
if (strCompare != 0) {
return strCompare;
}
}
}
// 一个字符串是另一个的前缀,短的放前面
return Integer.compare(s1.length(), s2.length());
}
}
\ No newline at end of file \ No newline at end of file
...@@ -159,6 +159,11 @@ public enum DeviceType { ...@@ -159,6 +159,11 @@ public enum DeviceType {
* 26 smdOne * 26 smdOne
*/ */
SMD_ONE("storage.type.smdOne"), SMD_ONE("storage.type.smdOne"),
/**
* 尾料柜
*/
TAILING_MATERIAL("storage.type.tailingMaterial"),
; ;
private String key; private String key;
...@@ -180,6 +185,6 @@ public enum DeviceType { ...@@ -180,6 +185,6 @@ public enum DeviceType {
} }
public static List<DeviceType> availableTypeList(){ public static List<DeviceType> availableTypeList(){
return Lists.newArrayList(AUTO,LINE,BATCH,SOLDERPASTE,VERTICALBOX,SMD_XL,SMD_DUO,SMD_XLC,SMD_XLR,SMD_ONE,VIRTUAL,NL,NLP,NLM,NLL,NLS,NLSM,SMDBOX_THIRD,SMD_MIMO_G2,SMD_MIMO_G3); return Lists.newArrayList(AUTO,LINE,BATCH,SOLDERPASTE,VERTICALBOX,SMD_XL,SMD_DUO,SMD_XLC,SMD_XLR,SMD_ONE,VIRTUAL,NL,NLP,NLM,NLL,NLS,NLSM,SMDBOX_THIRD,SMD_MIMO_G2,SMD_MIMO_G3,TAILING_MATERIAL);
} }
} }
...@@ -100,4 +100,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> { ...@@ -100,4 +100,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
List<StoragePos> findPosListByPartNumber(List<String> storageIdList, String pn, Collection<String> excludePosIds, CHECKOUT_TYPE checkOutType,Map<String,String> appendData); 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); List<StoragePos> findPosListByMpn(List<String> availableStorageIds, String mpn, Collection<String> excludePosIds, CHECKOUT_TYPE checkoutType, Map<String, String> appendDate);
int getRemainPosCountByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String lastPosId, String endStr) throws ValidateException;
StoragePos dualPosNameGetEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds,String lastPosId,String needMovePosName,String endStr,List<String> needExcludePosNameList) throws ValidateException;
} }
...@@ -1038,4 +1038,95 @@ public class StoragePosManagerImpl implements IStoragePosManager { ...@@ -1038,4 +1038,95 @@ public class StoragePosManagerImpl implements IStoragePosManager {
q.with(sort); q.with(sort);
return storagePosDao.findByQuery(q); return storagePosDao.findByQuery(q);
} }
@Override
public int getRemainPosCountByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds, String lastPosId, String endStr) throws ValidateException {
Criteria c = Criteria.where("storageId").is(storage.getId());
COMPATIBLE_TYPE compatibleType = storage.getCompatibleType();
if (compatibleType == COMPATIBLE_TYPE.EXACT_MATCH) {//完全匹配
c = c.and("w").is(barcode.getPlateSize()).and("h").is(barcode.getHeight());
} else if (compatibleType == COMPATIBLE_TYPE.FULLY_COMPATIBLE) {//同厚度兼容
c = c.and("w").gte(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//除7寸外,完全兼容
} else if (compatibleType == COMPATIBLE_TYPE.SIZE_COMPATIBLE) {//同尺寸兼容
c = c.and("w").is(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//宽度等于料盘宽度,高度大于等于料盘高度
}
c = c.and("enabled").is(true)//可用
.and("used").is(false);//未使用
//去除的仓位
if (excludePosIds != null && !excludePosIds.isEmpty()) {
c = c.and("id").nin(excludePosIds);
}
if (StringUtils.isNotEmpty(endStr)) {
String regex = "" + endStr + "$";
c.and("posName").regex(Pattern.compile(regex));
}
Query query = new Query(c);
query.with(Sort.by(Sort.Direction.ASC, "w").and(Sort.by(Sort.Direction.ASC, "h")).and(Sort.by(Sort.Direction.DESC, "priority")));
return storagePosDao.countByQuery(query);
}
private static boolean max = true;
@Override
public StoragePos dualPosNameGetEmptyPosByStorage(Storage storage, Barcode barcode, Collection<String> excludePosIds,String lastPosId,String needMovePosName,String endStr,List<String> needExcludePosNameList) throws ValidateException {
Criteria c = Criteria.where("storageId").is(storage.getId());
COMPATIBLE_TYPE compatibleType = storage.getCompatibleType();
if (compatibleType == COMPATIBLE_TYPE.EXACT_MATCH) {//完全匹配
c = c.and("w").is(barcode.getPlateSize()).and("h").is(barcode.getHeight());
} else if (compatibleType == COMPATIBLE_TYPE.FULLY_COMPATIBLE) {//同厚度兼容
c = c.and("w").gte(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//除7寸外,完全兼容
} else if (compatibleType == COMPATIBLE_TYPE.SIZE_COMPATIBLE) {//同尺寸兼容
c = c.and("w").is(barcode.getPlateSize()).and("h").gte(barcode.getHeight());//宽度等于料盘宽度,高度大于等于料盘高度
}
c = c.and("enabled").is(true)//可用
.and("used").is(false);//未使用
//去除的仓位
if (excludePosIds != null && !excludePosIds.isEmpty()) {
c = c.and("id").nin(excludePosIds);
}
if (StringUtils.isNotEmpty(needMovePosName) && StringUtils.isNotEmpty(endStr)) {
Criteria posNameCriteria = new Criteria();
String regex = ""+endStr+"$";
posNameCriteria.andOperator(Criteria.where("posName").ne(needMovePosName), Criteria.where("posName").regex(Pattern.compile(regex)));
c.andOperator(posNameCriteria);
}
if (needExcludePosNameList != null && !needExcludePosNameList.isEmpty()){
c.and("posName").nin(needExcludePosNameList);
}
Query query = new Query(c);
String msg = "";
// if (lastPosId == null || lastPosId.equals("")) {
//优先放入最合适的位置(根据尺寸),相同尺寸按优先级排序
if (max){
query.with(Sort.by(Sort.Direction.ASC, "w").and(Sort.by(Sort.Direction.ASC, "h")).and(Sort.by(Sort.Direction.DESC, "priority")));
max = true;
} else {
query.with(Sort.by(Sort.Direction.ASC, "w").and(Sort.by(Sort.Direction.ASC, "h")).and(Sort.by(Sort.Direction.ASC, "priority")));
max = false;
}
StoragePos pos = storagePosDao.findOne(query);
if ((!ObjectUtil.isNotEmpty(msg) )&& (pos != null)) {
Point targetP = PointUtil.getPosPoint(lastPosId, false);
log.debug(msg + "结果:[" + pos.getPosName() + "][" + targetP.getX() + "," + targetP.getY() + "]");
}
return pos;
}
} }
...@@ -167,8 +167,8 @@ public class TaskService { ...@@ -167,8 +167,8 @@ public class TaskService {
* @param task * @param task
*/ */
private void tiggerTaskChangeListener(DataLog task) { private void tiggerTaskChangeListener(DataLog task) {
liteOrderCache.onTaskStatusChange(task);
smfApi.onTaskStatusChange(task); smfApi.onTaskStatusChange(task);
liteOrderCache.onTaskStatusChange(task);
selfAuditUtil.onTaskStatusChange(task); selfAuditUtil.onTaskStatusChange(task);
materialTraceUtil.onTaskStatusChange(task); materialTraceUtil.onTaskStatusChange(task);
} }
...@@ -1454,4 +1454,169 @@ public class TaskService { ...@@ -1454,4 +1454,169 @@ public class TaskService {
} }
} }
} }
public StoragePos dualPosNameFindEmptyPosForPutIn(List<Storage> storageList, Barcode barcode, String inRFID, String lastPosId,String needMovePosName,String endStr) throws ValidateException {
verifyBarcodePutIn(storageList, barcode, inRFID);
List<String> storageIds=new ArrayList<>();
//查找任务数最少的料仓
final Map<String, Integer> storageTaskCountMap = new HashMap<>();
for (Storage storage : storageList) {
storageTaskCountMap.put(storage.getId(), 0);
storageIds.add(storage.getId());
}
Set<String> hasOutTaskStorageIds = new HashSet<>();
//如果有正在执行的任务,把库位发过去
Collection<DataLog> allTasks = taskMap.values();
for (DataLog task : allTasks) {
if (barcode.getBarcode().equals(task.getBarcode())) {
String posId = task.getPosId();
log.info(barcode.getBarcode() + " 已有任务,返回任务中的库位:" + task.getPosName());
return storagePosManager.get(posId);
}
String storageId = task.getStorageId();
if (!Strings.isNullOrEmpty(storageId)) {
Integer taskCount = storageTaskCountMap.get(storageId);
if (taskCount != null) {
taskCount = taskCount + 1;
storageTaskCountMap.put(storageId, taskCount);
}
if (task.isCheckOutTask()) {
hasOutTaskStorageIds.add(storageId);
}
}
}
String lockPosId = ReelLockPosUtil.getReelLockPosId(barcode.getBarcode());
StoragePos pos = null;
if (!Strings.isNullOrEmpty(lockPosId)) {
//已有锁定库位
pos = storagePosManager.get(lockPosId);
if (pos != null) {
if(!storageIds.contains(pos.getStorageId())){
log.info("条码[" + barcode.getBarcode() + "]已有锁定库位[" + pos.getPosName() + "],料仓ID["+pos.getStorageId()+"]不在请求列表["+String.join(",",storageIds)+"]中,重新查找库位");
pos = null;
}
else if (pos.getW() != barcode.getPlateSize() || pos.getH() != barcode.getHeight()) {
log.info("条码[" + barcode.getBarcode() + "]尺寸已改变,无法放入已锁定库位[" + pos.getPosName() + "],重新查找库位");
pos = null;
} else {
Barcode posBarcode = pos.getBarcode();
if (posBarcode == null) {
log.info("条码[" + barcode.getBarcode() + "]已锁定库位[" + pos.getPosName() + "],返回锁定中的库位");
} else {
log.info("条码[" + barcode.getBarcode() + "]已锁定库位[" + pos.getPosName() + "]中已有物料[" + posBarcode.getBarcode() + "],重新查找库位");
pos = null;
}
}
}
}
if (pos != null) {
return pos;
}
//可用的料仓(在线,且可以放入)
List<Storage> availbleStorageList = new ArrayList<>();
for (Storage storage : storageList) {
if (storage.canPutIn(barcode.getPlateSize(), barcode.getHeight())) {
availbleStorageList.add(storage);
}
}
if (availbleStorageList.isEmpty()) {
throw new ValidateException("smfcore.noValidStorage", "[{0}]料仓列表中未找到可用的料仓",new String[]{barcode.getBarcode()});
}
availbleStorageList.sort(new Comparator<Storage>() {
@Override
public int compare(Storage o1, Storage o2) {
Integer taskCount1 = storageTaskCountMap.get(o1.getId());
Integer taskCount2 = storageTaskCountMap.get(o2.getId());
return taskCount1.compareTo(taskCount2);
}
});
return dualPosNameFindEmptyPosInStorages(barcode, availbleStorageList, hasOutTaskStorageIds, lastPosId,needMovePosName,endStr);
}
private synchronized StoragePos dualPosNameFindEmptyPosInStorages(Barcode barcode, List<Storage> availbleStorageList, final Set<String> hasOutTaskStorageIds, String lastPosId,String needMovePosName,String endStr) {
List<String> needExcludePosName = new ArrayList<>();
//新增外侧有料,里侧没料,排除里侧的库位信息
List<StoragePos> allUsePosList = new ArrayList<>();
for (Storage storage : availbleStorageList) {
Map<String, StoragePos> usedPosList = dataCache.getUsedPosList(storage.getCid());
for (StoragePos pos : usedPosList.values()) {
allUsePosList.add(pos);
}
}
for (StoragePos pos : allUsePosList) {
String posName = pos.getPosName();
if (posName.endsWith("_F")) {
boolean hasEndBPos = false;
String posName_B = posName.substring(0, posName.length() - 1) + "B";
for (StoragePos usePos : allUsePosList) {
if (posName_B.equals(usePos.getPosName())) {
hasEndBPos = true;
break;
}
}
if (!hasEndBPos) {
needExcludePosName.add(posName_B);
}
}
}
//第一遍查找,先不查找有出库任务的料仓
for (Storage storage : availbleStorageList) {
if(!storage.isSmdDuo()){//DUO料仓无论是否有出库任务,都可以查找空库位
if(hasOutTaskStorageIds.contains(storage.getId())){
continue;
}
}
try {
Collection<String> operatingPosIds = excludePosIds();
log.debug("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位");
StoragePos pos = storagePosManager.dualPosNameGetEmptyPosByStorage(storage, barcode, operatingPosIds, lastPosId,needMovePosName,endStr,needExcludePosName);
if (pos != null) {
return pos;
}
} catch (Exception e) {
log.error("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位失败:" + e.getMessage());
}
}
//第二遍查找,从所有料仓中查找
for (Storage storage : availbleStorageList) {
try {
Collection<String> operatingPosIds = excludePosIds();
log.debug("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位");
StoragePos pos = storagePosManager.dualPosNameGetEmptyPosByStorage(storage, barcode, operatingPosIds, lastPosId,needMovePosName,endStr,needExcludePosName);
if (pos != null) {
return pos;
}
} catch (Exception e) {
log.error("尝试从[" + storage.getCid() + "]中为[" + barcode.getBarcode() + "]查找空位失败:" + e.getMessage());
}
}
try {
String cids = "";
for (Storage storage : availbleStorageList) {
cids = cids + storage.getCid() + ",";
}
log.info(barcode.getBarcode() + " 未找到可用库位,可用料仓:" + cids);
} catch (Exception e) {
log.error("打印可用料仓出错", e);
}
return null;
}
} }
...@@ -319,6 +319,27 @@ public class NeotelApi extends BaseSmfApiListener { ...@@ -319,6 +319,27 @@ public class NeotelApi extends BaseSmfApiListener {
*/ */
@Override @Override
public void onOrderStatusChange(String orderNotifyUrl, LiteOrder liteOrder) { public void onOrderStatusChange(String orderNotifyUrl, LiteOrder liteOrder) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("hSerial", liteOrder.getOrderNo());
String status = "Created";
if (liteOrder.isClosed()){
status = "Closed";
} else {
if (liteOrder.isTaskFinished()){
status = "Completed";
} else if (liteOrder.isOutBom() || liteOrder.isOutTails() || liteOrder.isOutOne()){
status = "Executed";
}
}
paramMap.put("status", status);
paramMap.put("total", liteOrder.getTotalTaskReelCount());
paramMap.put("out", liteOrder.getTotalFinishedReelCount());
try {
log.info(liteOrder.getOrderNo() + "工单状态改变,参数为:" + JsonUtil.toJsonStr(paramMap));
String result = HttpHelper.postJson(orderNotifyUrl, paramMap);
log.info(liteOrder.getOrderNo() + "工单状态改变,返回结果为:" + result);
} catch (Exception e) {
log.error("入库验证接口出错:" + e.getMessage());
}
} }
} }
...@@ -443,3 +443,8 @@ smf.nexim.getInventoryFaile=\u83B7\u53D6did\u4FE1\u606F\u5931\u8D25:[{0}] ...@@ -443,3 +443,8 @@ smf.nexim.getInventoryFaile=\u83B7\u53D6did\u4FE1\u606F\u5931\u8D25:[{0}]
smfcore.registerdid.false=[{0}]\u6CE8\u518Cdid\u5931\u8D25:[{1}] smfcore.registerdid.false=[{0}]\u6CE8\u518Cdid\u5931\u8D25:[{1}]
smfcore.accessToken.ng=\u83B7\u53D6AccessToken\u5931\u8D25 smfcore.accessToken.ng=\u83B7\u53D6AccessToken\u5931\u8D25
smfcore.barcode.hasOutTask=\u7269\u6599[{0}]\u5DF2\u6709\u51FA\u5E93\u4EFB\u52A1,\u9700\u7EE7\u7EED\u6267\u884C\u51FA\u5E93\u52A8\u4F5C smfcore.barcode.hasOutTask=\u7269\u6599[{0}]\u5DF2\u6709\u51FA\u5E93\u4EFB\u52A1,\u9700\u7EE7\u7EED\u6267\u884C\u51FA\u5E93\u52A8\u4F5C
smfcore.tailingmaterial.noPos=\u672A\u627E\u5230\u53EF\u7528\u7684\u67DC\u4F53
smfcore.tailingmaterial.pnError=\u5165\u5E93\u7684\u7269\u6599[{0}]\u4E0E\u67DC\u4F53\u4E2D[{1}]\u4E0D\u540C
smfcode.nlp.posRecovered=\u5E93\u4F4D[{0}]\u6062\u590D\u6B63\u5E38
smfcode.nlp.posNoReelError=\u5E93\u4F4D[{0}]\u68C0\u6D4B\u5230\u6CA1\u6709\u7269\u6599\uFF0C\u4F46\u7CFB\u7EDF\u6709\u5E93\u5B58\u8BB0\u5F55
smfcode.nlp.posHasReelError=\u5E93\u4F4D[{0}]\u68C0\u6D4B\u5230\u6709\u7269\u6599\uFF0C\u4F46\u7CFB\u7EDF\u65E0\u5E93\u5B58\u8BB0\u5F55
...@@ -431,3 +431,8 @@ smf.nexim.getInventoryFaile=Fehler beim Abrufen der did-Information: [{0}] ...@@ -431,3 +431,8 @@ smf.nexim.getInventoryFaile=Fehler beim Abrufen der did-Information: [{0}]
smfcore.registerdid.false=[{0}] Registrierung von did fehlgeschlagen:[{1}] smfcore.registerdid.false=[{0}] Registrierung von did fehlgeschlagen:[{1}]
smfcore.accessToken.ng=Fehler beim Abrufen des AccessToken smfcore.accessToken.ng=Fehler beim Abrufen des AccessToken
smfcore.barcode.hasOutTask=Material [{0}] hat bereits einen Ausgangsauftrag; die Ausgangsaktion muss fortgesetzt werden smfcore.barcode.hasOutTask=Material [{0}] hat bereits einen Ausgangsauftrag; die Ausgangsaktion muss fortgesetzt werden
smfcore.tailingmaterial.noPos=Kein verf\u00FCgbarer Schrank gefunden
smfcore.tailingmaterial.pnError=Das eingelagerte Material [{0}] unterscheidet sich von dem im Schrank [{1}]
smfcode.nlp.posRecovered=Position [{0}] wieder normal
smfcode.nlp.posNoReelError=Position [{0}] hat kein Material erkannt, aber das System hat einen Bestandsdatensatz
smfcode.nlp.posHasReelError=Position [{0}] hat Material erkannt, aber das System hat keinen Bestandsdatensatz
\ No newline at end of file \ No newline at end of file
...@@ -432,3 +432,8 @@ smf.nexim.getInventoryFaile=Failed to retrieve did information: [{0}] ...@@ -432,3 +432,8 @@ smf.nexim.getInventoryFaile=Failed to retrieve did information: [{0}]
smfcore.registerdid.false=[{0}] Failed to register did:[{1}] smfcore.registerdid.false=[{0}] Failed to register did:[{1}]
smfcore.accessToken.ng=Failed to obtain AccessToken smfcore.accessToken.ng=Failed to obtain AccessToken
smfcore.barcode.hasOutTask=Material [{0}] already has an outbound task; the outbound action needs to be continued. smfcore.barcode.hasOutTask=Material [{0}] already has an outbound task; the outbound action needs to be continued.
smfcore.tailingmaterial.noPos=No available cabinet found
smfcore.tailingmaterial.pnError=The material [{0}] put in is different from the one in the cabinet [{1}]
smfcode.nlp.posRecovered=Position [{0}] returned to normal
smfcode.nlp.posNoReelError=Position [{0}] detected no material, but system has inventory record
smfcode.nlp.posHasReelError=Position [{0}] detected material, but system has no inventory record
\ No newline at end of file \ No newline at end of file
...@@ -431,3 +431,8 @@ smf.nexim.getInventoryFaile=\u00C9chec de r\u00E9cup\u00E9ration des information ...@@ -431,3 +431,8 @@ smf.nexim.getInventoryFaile=\u00C9chec de r\u00E9cup\u00E9ration des information
smfcore.registerdid.false=[{0}] \u00C9chec de l'enregistrement de did:[{1}] smfcore.registerdid.false=[{0}] \u00C9chec de l'enregistrement de did:[{1}]
smfcore.accessToken.ng=\u00C9chec de l'obtention de l'AccessToken smfcore.accessToken.ng=\u00C9chec de l'obtention de l'AccessToken
smfcore.barcode.hasOutTask=La mati\u00E8re [{0}] a d\u00E9j\u00E0 une t\u00E2che de sortie ; l'action de sortie doit \u00EAtre poursuivie smfcore.barcode.hasOutTask=La mati\u00E8re [{0}] a d\u00E9j\u00E0 une t\u00E2che de sortie ; l'action de sortie doit \u00EAtre poursuivie
smfcore.tailingmaterial.noPos=Aucun cabinet disponible trouv\u00E9
smfcore.tailingmaterial.pnError=Le mat\u00E9riau [{0}] mis en stock est diff\u00E9rent de celui dans le cabinet [{1}]
smfcode.nlp.posRecovered=Position [{0}] revenue \u00E0 la normale
smfcode.nlp.posNoReelError=Position [{0}] n'a d\u00E9tect\u00E9 aucun mat\u00E9riau, mais le syst\u00E8me a un enregistrement d'inventaire
smfcode.nlp.posHasReelError=Position [{0}] a d\u00E9tect\u00E9 du mat\u00E9riau, mais le syst\u00E8me n'a pas d'enregistrement d'inventaire
\ No newline at end of file \ No newline at end of file
...@@ -428,3 +428,8 @@ smf.nexim.getInventoryFaile=did \u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557 ...@@ -428,3 +428,8 @@ smf.nexim.getInventoryFaile=did \u60C5\u5831\u306E\u53D6\u5F97\u306B\u5931\u6557
smfcore.registerdid.false=[{0}] did \u306E\u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F:[{1}] smfcore.registerdid.false=[{0}] did \u306E\u767B\u9332\u306B\u5931\u6557\u3057\u307E\u3057\u305F:[{1}]
smfcore.accessToken.ng=AccessToken \u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F smfcore.accessToken.ng=AccessToken \u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F
smfcore.barcode.hasOutTask=\u8CC7\u6750 [{0}] \u306B\u306F\u65E2\u306B\u51FA\u5EAB\u30BF\u30B9\u30AF\u304C\u3042\u308A\u3001\u51FA\u5EAB\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u7D9A\u884C\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 smfcore.barcode.hasOutTask=\u8CC7\u6750 [{0}] \u306B\u306F\u65E2\u306B\u51FA\u5EAB\u30BF\u30B9\u30AF\u304C\u3042\u308A\u3001\u51FA\u5EAB\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u7D9A\u884C\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059
smfcore.tailingmaterial.noPos=\u5229\u7528\u53EF\u80FD\u306A\u30AD\u30E3\u30D3\u30CD\u30C3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093
smfcore.tailingmaterial.pnError=\u5165\u5E93\u3055\u308C\u305F\u6750\u6599[{0}]\u306F\u30AD\u30E3\u30D3\u30CD\u30C3\u30C8\u5185\u306E[{1}]\u3068\u7570\u306A\u308A\u307E\u3059
smfcode.nlp.posRecovered=\u5EAB\u4F4D[{0}]\u304C\u6B63\u5E38\u306B\u623B\u308A\u307E\u3057\u305F
smfcode.nlp.posNoReelError=\u5EAB\u4F4D[{0}]\u306B\u7269\u6599\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u304C\u3001\u30B7\u30B9\u30C6\u30E0\u306B\u306F\u5728\u5EAB\u8A18\u9332\u304C\u3042\u308A\u307E\u3059
smfcode.nlp.posHasReelError=\u5EAB\u4F4D[{0}]\u306B\u7269\u6599\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u304C\u3001\u30B7\u30B9\u30C6\u30E0\u306B\u306F\u5728\u5EAB\u8A18\u9332\u304C\u3042\u308A\u307E\u305B\u3093
\ No newline at end of file \ No newline at end of file
...@@ -428,3 +428,8 @@ smf.nexim.getInventoryFaile=\u83B7\u53D6did\u4FE1\u606F\u5931\u8D25:[{0}] ...@@ -428,3 +428,8 @@ smf.nexim.getInventoryFaile=\u83B7\u53D6did\u4FE1\u606F\u5931\u8D25:[{0}]
smfcore.registerdid.false=[{0}]\u6CE8\u518Cdid\u5931\u8D25:[{1}] smfcore.registerdid.false=[{0}]\u6CE8\u518Cdid\u5931\u8D25:[{1}]
smfcore.accessToken.ng=\u83B7\u53D6AccessToken\u5931\u8D25 smfcore.accessToken.ng=\u83B7\u53D6AccessToken\u5931\u8D25
smfcore.barcode.hasOutTask=\u7269\u6599[{0}]\u5DF2\u6709\u51FA\u5E93\u4EFB\u52A1,\u9700\u7EE7\u7EED\u6267\u884C\u51FA\u5E93\u52A8\u4F5C smfcore.barcode.hasOutTask=\u7269\u6599[{0}]\u5DF2\u6709\u51FA\u5E93\u4EFB\u52A1,\u9700\u7EE7\u7EED\u6267\u884C\u51FA\u5E93\u52A8\u4F5C
smfcore.tailingmaterial.noPos=\u672A\u627E\u5230\u53EF\u7528\u7684\u67DC\u4F53
smfcore.tailingmaterial.pnError=\u5165\u5E93\u7684\u7269\u6599[{0}]\u4E0E\u67DC\u4F53\u4E2D[{1}]\u4E0D\u540C
smfcode.nlp.posRecovered=\u5E93\u4F4D[{0}]\u6062\u590D\u6B63\u5E38
smfcode.nlp.posNoReelError=\u5E93\u4F4D[{0}]\u68C0\u6D4B\u5230\u6CA1\u6709\u7269\u6599\uFF0C\u4F46\u7CFB\u7EDF\u6709\u5E93\u5B58\u8BB0\u5F55
smfcode.nlp.posHasReelError=\u5E93\u4F4D[{0}]\u68C0\u6D4B\u5230\u6709\u7269\u6599\uFF0C\u4F46\u7CFB\u7EDF\u65E0\u5E93\u5B58\u8BB0\u5F55
\ No newline at end of file \ No newline at end of file
...@@ -428,3 +428,8 @@ smf.nexim.getInventoryFaile=\u53D6\u5F97 did \u8CC7\u8A0A\u5931\u6557:[{0}] ...@@ -428,3 +428,8 @@ smf.nexim.getInventoryFaile=\u53D6\u5F97 did \u8CC7\u8A0A\u5931\u6557:[{0}]
smfcore.registerdid.false=[{0}]\u8A3B\u518Adid\u5931\u6557:[{1}] smfcore.registerdid.false=[{0}]\u8A3B\u518Adid\u5931\u6557:[{1}]
smfcore.accessToken.ng=\u7372\u53D6AccessToken\u5931\u6557 smfcore.accessToken.ng=\u7372\u53D6AccessToken\u5931\u6557
smfcore.barcode.hasOutTask=\u7269\u6599[{0}]\u5DF2\u6709\u51FA\u5EAB\u4EFB\u52D9\uFF0C\u9700\u7E7C\u7E8C\u57F7\u884C\u51FA\u5EAB\u52D5\u4F5C smfcore.barcode.hasOutTask=\u7269\u6599[{0}]\u5DF2\u6709\u51FA\u5EAB\u4EFB\u52D9\uFF0C\u9700\u7E7C\u7E8C\u57F7\u884C\u51FA\u5EAB\u52D5\u4F5C
smfcore.tailingmaterial.noPos=\u672A\u627E\u5230\u53EF\u7528\u7684\u6AC3\u9AD4
smfcore.tailingmaterial.pnError=\u5165\u5EAB\u7684\u7269\u6599[{0}]\u8207\u6AC3\u9AD4\u4E2D[{1}]\u4E0D\u540C
smfcode.nlp.posRecovered=\u5EAB\u4F4D[{0}]\u6062\u5FA9\u6B63\u5E38
smfcode.nlp.posNoReelError=\u5EAB\u4F4D[{0}]\u6AA2\u6E2C\u5230\u6C92\u6709\u7269\u6599\uFF0C\u4F46\u7CFB\u7D71\u6709\u5EAB\u5B58\u8A18\u9304
smfcode.nlp.posHasReelError=\u5EAB\u4F4D[{0}]\u6AA2\u6E2C\u5230\u6709\u7269\u6599\uFF0C\u4F46\u7CFB\u7D71\u7121\u5EAB\u5B58\u8A18\u9304
\ No newline at end of file \ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!