Commit c00de27b sunke

查询料盘绑定接口增加slot字段,当slot大于0时为真实绑定,其他为预绑定

需求单最后一盘E状态修改为EL
排队页面增加需求单创建时间
需求单页面增加需求时间
双层线上AGV拉走料架时调用清理料架,使料架可以重复使用
1 个父辈 3fa4b128
......@@ -373,6 +373,33 @@ public class InquiryShelfBean {
}
/**
* 双层线上AGV拉走料架时调用清理料架,使料架可以重复使用
*/
public static void agvRemoveRfid(String realRfid){
ShelfInfo shelfToRemove = null;
for (Map<String, ShelfInfo> shelfInfoMap : hSerialShelfMap.values()) {
for (ShelfInfo shelfInfo : shelfInfoMap.values()) {
String shelfRFID = shelfInfo.getRealRfid();
if(shelfRFID.equals(realRfid)){
//已经绑定过该Temp料架
shelfToRemove = shelfInfo;
}
}
}
if(shelfToRemove != null){
String hSerial = shelfToRemove.gethSerial();
Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
if(shelfMap != null){
log.info("料架"+shelfToRemove.tempRfid()+"["+shelfToRemove.getRealRfid()+"]已放上AGV,从缓存中清理");
shelfMap.remove(shelfToRemove.tempRfid());
hSerialShelfMap.put(hSerial, shelfMap);
QisdaCache.saveShelfMap(hSerialShelfMap);
}
}
}
/**
* 根据tempRfid编号获取料架信息
*/
public static ShelfInfo findSameShelf(String hSerial, String rfid){
......@@ -481,6 +508,23 @@ public class InquiryShelfBean {
return null;
}
/**
* 获取需求单使用的所有D料架
*/
public static List<ShelfInfo> getAllDShelf(String hSerial){
List<ShelfInfo> shelfInfos = new ArrayList<>();
Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
if(shelfMap != null){
for (ShelfInfo shelf : shelfMap.values()) {
if(shelf.isDShelf()){
shelfInfos.add(shelf);
}
}
}
return shelfInfos;
}
public static ShelfInfo findMaxUsedShelf(String hSerial, String shelfType){
Map<String, ShelfInfo> shelfMap = hSerialShelfMap.get(hSerial);
if(shelfMap == null){
......
......@@ -2,6 +2,7 @@ package com.myproject.bean.update.qisda;
import com.myproject.bean.BaseMongoBean;
import com.myproject.util.StorageConstants;
import org.apache.logging.log4j.util.Strings;
import org.springframework.data.annotation.Transient;
import java.util.*;
......@@ -295,7 +296,16 @@ public class OutInfo extends BaseMongoBean {
/**
* 放上料架顺序
*/
public String getShelfLatest(){
public String getShelfLatest(String status){
if("E".equalsIgnoreCase(status)){
if(taskNum == 1){
return "EL";
}
if(taskFinishNum >= taskNum){
return "EL";
}
return "E";
}
if(taskNum == 1){
return "L";
}
......
......@@ -20,6 +20,8 @@ public interface IOutInfoDao extends IMongoDao {
void updateStatus(String hSerial, int bindStatus, int sendStatus);
void updateEndOutInfo(String hSerial, boolean endOutInfo);
void updateTaskEndTime(String hSerial, long taskEndTime);
void updateTaskFinishNum(String hSerail, int taskFinishNum);
......
......@@ -82,6 +82,15 @@ public class OutInfoDaoImpl extends AbstractMongoDao implements IOutInfoDao {
}
@Override
public void updateEndOutInfo(String hSerial, boolean endOutInfo){
Criteria c = Criteria.where("hSerial").is(hSerial);
Query query = Query.query(c);
Update update = new Update();
update.set("endOutInfo",endOutInfo);
updateFirst(query,update);
}
@Override
public void updateTaskEndTime(String hSerial, long taskEndTime){
update(hSerial, "taskEndTime", taskEndTime);
}
......
......@@ -660,10 +660,33 @@ public class QisdaApi {
if(result.contains("VehicleID")){
return result;
}
if(result.toLowerCase().contains("wait")){
return result;
}
return "";
} catch (Exception e) {
log.error("从Qisda检查工单料架是否解绑"+hserial+"["+line+"])接口(GetSerialData)出错",e);
return "检查出错:" + e.getMessage();
}
}
/**
* 将最后一个补料需求单的状态更新为不是最后一个需求单
* @param soseq
* @return
*/
public static String UpdateBatchRefillMark(String soseq){
String url = "http://10.85.17.233/ESMTCommonInterface/CommonService.asmx/UpdateBatchRefillMark";
Map<String,Object> paramMap = new HashMap<String,Object>();
paramMap.put("soseq",soseq);
try {
String result = HttpHelper.postParam(url,paramMap);
log.info("更新Qisda工单序号["+soseq+"]的最后一个需求单状态为非最后一个需求单(UpdateBatchRefillMark)返回:" + result);
return "";
} catch (Exception e) {
log.error("更新Qisda工单序号["+soseq+"]的最后一个需求单状态为非最后一个需求单(UpdateBatchRefillMark)出错",e);
return "工单序号最后一个需求单状态更新出错:" + e.getMessage();
}
}
}
......@@ -3,10 +3,7 @@ package com.myproject.webapp.controller.qisda.util;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.myproject.bean.qisda.AppendInfo;
import com.myproject.bean.qisda.InquiryShelfBean;
import com.myproject.bean.qisda.ResultBean;
import com.myproject.bean.qisda.ShelfInfo;
import com.myproject.bean.qisda.*;
import com.myproject.bean.update.*;
import com.myproject.bean.update.qisda.OutInfo;
import com.myproject.bean.update.qisda.OutItem;
......@@ -160,15 +157,18 @@ public class OutInfoCache {
log.info("需求单["+firstOutInfoToExecute.gethSerial()+"]产线有未解绑料架["+lineHasBindShelf+"]需要进行等待");
return;
}else{
if(firstOutInfoToExecute.isPreTailAction()){
//预补料,检查是否是同一个工单未解绑的料架
boolean preTailCanOut = isPreTailCanOut(firstOutInfoToExecute.getSoseq(),lineHasBindShelf);
if(preTailCanOut){
log.info("预补料需求单["+firstOutInfoToExecute.gethSerial()+"]对应产线的料架数量小于4个,可以进行出库");
int shelfCountToLine = shelfCountToLine(firstOutInfoToExecute.getSoseq(),lineHasBindShelf);
if(firstOutInfoToExecute.isPreTailAction() || firstOutInfoToExecute.isTailAction()){
//补料,检查是否是同一个工单未解绑的料架
//boolean preTailCanOut = isPreTailCanOut(firstOutInfoToExecute.getSoseq(),lineHasBindShelf);
if(shelfCountToLine > 0){
log.info("补料需求单["+firstOutInfoToExecute.gethSerial()+"]对应产线可放料架["+shelfCountToLine+"],可以进行出库");
outInfoToExecute = firstOutInfoToExecute;
firstOutInfoToExecute.setLineBindShelfInfo("");
outInfoMap.put(firstOutInfoToExecute.gethSerial(), firstOutInfoToExecute);
break;
}else{
log.info("预补料需求单["+firstOutInfoToExecute.gethSerial()+"]对应产线的料架数量大于4个,暂不进行出库");
log.info("补料需求单["+firstOutInfoToExecute.gethSerial()+"]对应产线可放料架["+shelfCountToLine+"],暂不进行出库");
}
}
//不需要等待,跳过验证下一个
......@@ -207,7 +207,16 @@ public class OutInfoCache {
}
private boolean isPreTailCanOut(String soseq, String lineHasBindShelfJsonStr){
/**
* 产线可放料架数量,有不是同一工单序号的未解绑料架,不允许出库, 同一工
* @param soseq
* @param lineHasBindShelfJsonStr
* @return
*/
private int shelfCountToLine(String soseq, String lineHasBindShelfJsonStr){
if(lineHasBindShelfJsonStr.isEmpty()){
return 4;
}
Map<String, Object> map = JsonUtil.toMap(lineHasBindShelfJsonStr);
Object data = map.get("data");
if(data != null){
......@@ -216,20 +225,45 @@ public class OutInfoCache {
for (Object info : dataList) {
Map<String,String> infoMap = (Map)info;
String hSerial = infoMap.get("Serial");
OutInfo outInfo = getOutInfoFromCache(hSerial);
OutInfo outInfo = outInfoDao.findByHSerial(hSerial);
if(outInfo != null && outInfo.getSoseq().equals(soseq)){
remainShelfCount ++;
}else{
//有不是同一个需求单的未解绑料架,不允许出库
return false;
return 0;
}
}
//必须小于4个(即有空位)才可以出料
return remainShelfCount < 4;
return 4 - remainShelfCount;
}else{
log.error("未找到data数据,无法出库");
return 0;
}
return false;
}
// private boolean isPreTailCanOut(String soseq, String lineHasBindShelfJsonStr){
// Map<String, Object> map = JsonUtil.toMap(lineHasBindShelfJsonStr);
// Object data = map.get("data");
// if(data != null){
// List<Object> dataList = (List)data;
// int remainShelfCount = 0;
// for (Object info : dataList) {
// Map<String,String> infoMap = (Map)info;
// String hSerial = infoMap.get("Serial");
// OutInfo outInfo = getOutInfoFromCache(hSerial);
// if(outInfo != null && outInfo.getSoseq().equals(soseq)){
// remainShelfCount ++;
// }else{
// //有不是同一个需求单的未解绑料架,不允许出库
// return false;
// }
// }
// //必须小于4个(即有空位)才可以出料
// return remainShelfCount < 4;
// }
// return false;
// }
private OutInfo findExecuteOrderHSerial(List<OutInfo> cachedOutInfos,List<String> excludeSerialList){
OutInfo mustOutInfo = null;
//已到达建议时间的需求单
......@@ -499,15 +533,15 @@ public class OutInfoCache {
outInfoList.sort(new Comparator<OutInfo>() {
@Override
public int compare(OutInfo o1, OutInfo o2) {
if(o1 == null && o2 == null) {
return 0;
}
if(o1 == null) {
return -1;
}
if(o2 == null) {
return 1;
}
// if(o1 == null && o2 == null) {
// return 0;
// }
// if(o1 == null) {
// return -1;
// }
// if(o2 == null) {
// return 1;
// }
//按优先级排序,如果没有优先级,使用
long executeTime1 = o1.getFirstExecuteTime();
long executeTime2 = o2.getFirstExecuteTime();
......@@ -519,14 +553,19 @@ public class OutInfoCache {
if(executeTime2 == 0){
return -1;
}
Long abs = Math.abs(executeTime1) - Math.abs(executeTime2);
int result = abs.intValue();
if(result < 0){
result = -1;
}else if(result > 0){
result = 1;
}
return result;
Long time1 = Math.abs(executeTime1);
Long time2 = Math.abs(executeTime2);
return time1.compareTo(time2);
// Long abs = Math.abs(executeTime1) - Math.abs(executeTime2);
// int result = abs.intValue();
// if(result < 0){
// result = -1;
// }else if(result > 0){
// result = 1;
// }
// return result;
}
//都为0即未执行过的,到这里的,理论上都是未达到必须出库时间(达到必须出库时间的,已经修改过优先级)
Date sdate1 = o1.getSdate();
......@@ -867,6 +906,7 @@ public class OutInfoCache {
return ResultBean.newErrorResult(1007,"有需求单执行任务未完成,请稍后再试");
}
}catch (Exception e){
log.error("需求单执行出错:",e);
return ResultBean.newErrorResult(1008,"需求单执行出错:"+e.getMessage());
}finally {
outProcessing.set(false);
......@@ -882,26 +922,12 @@ public class OutInfoCache {
return resultBean;
}
OutInfo outInfo = null;
if(outInfoToExecute.isPreTailAction()){
//预补料需求单,查找对应的未执行过的补料需求单
for (OutInfo info : outInfoMap.values()) {
if(info.getSoseq().equals(outInfoToExecute.getSoseq()) && info.getFirstExecuteTime() <=0){
outInfo = info;
break;
}
}
if(outInfo == null){
String msg = "未查找到预补料需求单"+hSerial+"["+outInfoToExecute.getSo()+"]对应的补料需求单,关闭预补料需求单";
log.info(msg);
closeHSerial(hSerial);
return ResultBean.newErrorResult(5001,msg);
}else{
log.info("查找到预补料需求单"+hSerial+"["+outInfoToExecute.getSo()+"]对应的补料需求单["+outInfo.gethSerial()+"],关闭预补料需求单,开始出库补料需求单");
closeHSerial(hSerial);
}
String msg = "预补料需求单"+hSerial+"["+outInfoToExecute.getSo()+"]已到执行时间,关闭预补料需求单";
log.info(msg);
closeHSerial(hSerial);
return ResultBean.newErrorResult(5001,msg);
}else{
outInfo = outInfoToExecute;
}
......@@ -952,61 +978,59 @@ public class OutInfoCache {
List<DataLog> tasks = new ArrayList<>();
List<OutItem> itemList = outInfo.getOutItems();
itemList.sort(new Comparator<OutItem>(){
List<String> allreadyOutPosIdList = new ArrayList<>();
// if(outInfo.isTailAction()){
// //尾料单独处理
//
//
// }else{
List<OutItem> itemList = outInfo.getOutItems();
@Override
public int compare(OutItem o1, OutItem o2) {
return o1.getSlotlocation() - o2.getSlotlocation();
}
});
itemList.sort(new Comparator<OutItem>(){
Date itemUpdateTime = new Date();
for (OutItem outItem : itemList) {
outItem.setUpdateDate(itemUpdateTime);
List<DataLog> itemTasks = new ArrayList<>();
//首盘料需求单
if(outItem.isFirstReelAction()){
itemTasks = checkOutFirst(outItem, outInfoExecuted);
}else if(outItem.isReelCutAction()){
itemTasks = checkOutCut(outItem);
}else if(outItem.isTailAction()){
itemTasks = checkOutTail(outItem, outInfoExecuted);
}else if(outItem.isUrgentAction()){
itemTasks = checkOutUrgent(outItem);
}
@Override
public int compare(OutItem o1, OutItem o2) {
return o1.getSlotlocation() - o2.getSlotlocation();
}
});
Date itemUpdateTime = new Date();
for (OutItem outItem : itemList) {
outItem.setUpdateDate(itemUpdateTime);
List<DataLog> itemTasks = new ArrayList<>();
//首盘料需求单
if(outItem.isFirstReelAction()){
itemTasks = checkOutFirst(outItem, outInfoExecuted);
}else if(outItem.isReelCutAction()){
itemTasks = checkOutCut(outItem);
}else if(outItem.isTailAction()){
itemTasks = checkOutTail(outItem, outInfoExecuted);
}else if(outItem.isUrgentAction()){
itemTasks = checkOutUrgent(outItem);
}
if(itemTasks != null && !itemTasks.isEmpty()){
for (DataLog itemTask : itemTasks) {
tasks.add(itemTask);
if(itemTasks != null && !itemTasks.isEmpty()){
for (DataLog itemTask : itemTasks) {
allreadyOutPosIdList.add(itemTask.getPosId());
tasks.add(itemTask);
}
boolean needAddToTotal = false;
resetTaskNum(hSerial, tasks.size(),outInfoExecuted,needAddToTotal);
updateOutItem(outItem.getId());
}
boolean needAddToTotal = false;
resetTaskNum(hSerial, tasks.size(),outInfoExecuted,needAddToTotal);
updateOutItem(outItem.getId());
}
// }
}
String msg = "";
int outReelNum = tasks.size();
if(outReelNum > 0){
//补料出库,且不是缺料重发,需要重新排序,按站位序号循环出,每次出最大的盘
if(outInfo.isTailAction() && !outInfoExecuted){
//是否满料架,没满需补满
// ShelfInfo maxDShelf = InquiryShelfBean.findMaxUsedShelf(outInfo.gethSerial(), StorageConstants.SHEFL_TYPE.D);
// if(!maxDShelf.reachMaxLoc()){
// //是否已放满,未放满的话,每个站别补一盘补满
// List<StoragePos> allBindPosList = storagePosDao.listSoSeqBindPos(outInfo.getSoseq());
// for (StoragePos storagePos : allBindPosList) {
// int slotIndex = storagePos.getBarcode().getAppendInfo().getSlotIndex();
//
// }
//
// }
tasks = fixDShelf(outInfo, allreadyOutPosIdList, tasks);
tasks = sortTailTasks(tasks);
outReelNum = tasks.size();
}
log.info("需求单"+outInfo.gethSerial()+"已出("+outInfo.getOutReelNum()+")/已发("+outInfo.getTaskFinishNum()+") 本次出库料盘数量:" + outReelNum);
......@@ -1042,6 +1066,183 @@ public class OutInfoCache {
return ResultBean.newOkResult(msg,"ok");
}
/**
* 补满或删除料架逻辑
*/
private List<DataLog> fixDShelf(OutInfo outInfo, List<String> allreadyOutPosIdList, List<DataLog> tasks){
String lineHasBindShelf = QisdaApi.GetSerialData(outInfo.getLine(),outInfo.gethSerial());
int shelfCountToLine = shelfCountToLine(outInfo.getSoseq(),lineHasBindShelf);
List<ShelfInfo> allDShelfs = InquiryShelfBean.getAllDShelf(outInfo.gethSerial());
try{
log.info("产线可放料架数:"+shelfCountToLine+" 需求单["+outInfo.gethSerial()+"]分配小料架数:" + allDShelfs.size());
if(shelfCountToLine > 0 && shelfCountToLine < allDShelfs.size()){
//产线不可放下那么多料架,需要删减一车
tasks = removeTailDShelf(outInfo,allDShelfs,tasks);
}else{
tasks = fillTailDShelf(outInfo,allDShelfs, allreadyOutPosIdList,tasks);
}
}catch (Exception e){
log.error("料架修正逻辑出错",e);
}
return tasks;
}
/**
* 清除多出来的料架
*/
private List<DataLog> removeTailDShelf(OutInfo outInfo, List<ShelfInfo> allDShelfs, List<DataLog> tasks){
ShelfInfo dShelfToRemove = null;
for (ShelfInfo dShelf : allDShelfs) {
if(dShelfToRemove == null || dShelfToRemove.getRfidIndex()< dShelf.getRfidIndex()){
dShelfToRemove = dShelf;
}
}
if(dShelfToRemove != null){
int needRemoveReelCount = dShelfToRemove.getUsedLocCount();
if(needRemoveReelCount > 0){
log.info("需求单["+outInfo.gethSerial()+"]的料架["+dShelfToRemove.tempRfid()+"]超出产线可容纳数量,开启删减最后一车逻辑,数量:" + needRemoveReelCount);
//站位料盘数统计
Map<Integer,Integer> slotReelCountMap = new HashMap<>();
for (DataLog task : tasks) {
if(task.getAppendInfo().isDShelfTask()){
int slotIndex = task.getAppendInfo().getSlotIndex();
Integer reelCount = slotReelCountMap.get(slotIndex);
if(reelCount == null){
reelCount = 0;
}
reelCount = reelCount + 1;
slotReelCountMap.put(slotIndex,reelCount);
}
}
while(needRemoveReelCount > 0){
Map.Entry<Integer, Integer> maxCountEntry = null;
for (Map.Entry<Integer, Integer> entry : slotReelCountMap.entrySet()) {
if(maxCountEntry == null || entry.getValue() > maxCountEntry.getValue()){
maxCountEntry = entry;
}
}
DataLog taskToRemove = null;
for (DataLog task : tasks) {
AppendInfo appendInfo = task.getAppendInfo();
if(appendInfo.isDShelfTask() && appendInfo.getSlotIndex() == maxCountEntry.getKey()){
//与料盘数最多的站位相同的D料架任务,找最小的一盘
if(taskToRemove == null || task.getNum() < taskToRemove.getNum()){
taskToRemove = task;
}
}
}
if(taskToRemove != null){
taskToRemove.setStatus(StorageConstants.OP_STATUS.CANCEL.name());
dataLogDao.save(taskToRemove);
tasks.remove(taskToRemove);
needRemoveReelCount = needRemoveReelCount -1;
log.info(taskToRemove.getBarcode()+"任务取消,剩余待取消任务数量:" + needRemoveReelCount);
InquiryShelfBean.cancelReelTask(taskToRemove);
int taskSlotIndex = taskToRemove.getAppendInfo().getSlotIndex();
int slotReelCount = slotReelCountMap.get(taskSlotIndex);
slotReelCount = slotReelCount -1;
slotReelCountMap.put(taskSlotIndex,slotReelCount);
}else{
break;
}
}
if(outInfo.isEndOutInfo()){
String soseq = outInfo.getSoseq();
log.info("需求单["+outInfo.gethSerial()+"]是工单序号["+soseq+"]最后一个补料单,删减料架后更新补料单状态,同时更新Qisda补料单状态");
boolean endOutInfo = false;
outInfo.setEndOutInfo(endOutInfo);
outInfoDao.updateEndOutInfo(outInfo.gethSerial(),endOutInfo);
outInfoMap.put(outInfo.gethSerial(), outInfo);
QisdaApi.UpdateBatchRefillMark(soseq);
}
}
}
return tasks;
}
/**
* 把料架填满
*/
private List<DataLog> fillTailDShelf(OutInfo outInfo, List<ShelfInfo> allDShelfs, List<String> allreadyOutPosIdList, List<DataLog> tasks){
//补满一车
ShelfInfo dShelfToFill = null;
for (ShelfInfo dShelf : allDShelfs) {
if(!dShelf.reachMaxLoc()){
dShelfToFill = dShelf;
break;
}
}
if(dShelfToFill != null){
int reelCountToFill = dShelfToFill.getMaxLocCount() - dShelfToFill.getUsedLocCount();
log.info("需求单["+outInfo.gethSerial()+"]的料架["+dShelfToFill.tempRfid()+"]还差["+reelCountToFill+"]盘料未放满,开启补满逻辑");
//是否已放满,未放满的话,每个站别补一盘补满
List<StoragePos> allBindPosList = storagePosDao.listSoSeqBindPos(outInfo.getSoseq());
Map<Integer,OutItemBindBean> itemBindMap = new HashMap<>();
for (StoragePos pos : allBindPosList) {
if(!allreadyOutPosIdList.contains(pos.getId()) && pos.getBarcode().isSmallReel()){
//正常流程未出料盘
int slotIndex = pos.getBarcode().getAppendInfo().getSlotIndex();
OutItem outItem = outInfo.findOutItem(slotIndex);
if(outItem != null){
//必须包含才能出,不然出库完成时会有问题
OutItemBindBean itemBindBean = itemBindMap.get(slotIndex);
if(itemBindBean == null){
itemBindBean =new OutItemBindBean(outItem);
}
itemBindBean.addBindPos(pos);
itemBindMap.put(slotIndex,itemBindBean);
}
}
}
if(!itemBindMap.isEmpty()){
List<OutItemBindBean> itemBindBeanList = new ArrayList<>(itemBindMap.values());
itemBindBeanList.sort(new Comparator<OutItemBindBean>() {
@Override
public int compare(OutItemBindBean o1, OutItemBindBean o2) {
return o2.getBindReelCount().compareTo(o1.getBindReelCount());
}
});
while (reelCountToFill > 0){
int remainBindCount = 0;
for (OutItemBindBean outItemBindBean : itemBindBeanList) {
StoragePos pos = outItemBindBean.takeOnePos();
if(pos != null){
reelCountToFill--;
OutItem outItem = outItemBindBean.getOutItem();
DataLog task = newTask(outItem, pos);
task = InquiryShelfBean.addUnlimitLoc(task, outItem);
task = dataLogDao.save(task);
tasks.add(task);
boolean needAddToTotal = false;
boolean outInfoExecuted = false;
resetTaskNum(outItem.gethSerial(), tasks.size(),outInfoExecuted,needAddToTotal);
updateOutItem(outItem.getId());
}
remainBindCount = remainBindCount + outItemBindBean.getBindReelCount();
if(reelCountToFill<=0){
break;
}
}
if(remainBindCount == 0 || reelCountToFill <= 0){
break;
}
}
}
}
return tasks;
}
/**
* 对补料任务进行出库排序
*/
......
......@@ -226,10 +226,10 @@ public class QisdaApiController extends BaseController {
public ResultBean smallBindCount(HttpServletRequest request){
String soseqListStr = receiveParamInfo(request,"soseqList");
log.info("收到获取工单的小料盘绑定数量 soseqList="+soseqListStr);
int smallBindCount = 0;
String[] soseqList = soseqListStr.split(",");
List<Map<String,String>> resultList = new ArrayList<>();
for (String soseq : soseqList) {
int smallBindCount = 0;
List<StoragePos> bindPosList = storagePosDao.listSoSeqBindPos(soseq);
for (StoragePos storagePos : bindPosList) {
Barcode reel = storagePos.getBarcode();
......@@ -240,6 +240,7 @@ public class QisdaApiController extends BaseController {
Map<String,String> itemMap = new HashMap<>();
itemMap.put("soseq", soseq);
itemMap.put("smallCount", "" + smallBindCount);
log.info("soseq=["+soseq+"]小料盘绑定数量:" + smallBindCount);
resultList.add(itemMap);
}
......@@ -266,14 +267,20 @@ public class QisdaApiController extends BaseController {
if(pos != null){
Barcode barcode = pos.getBarcode();
AppendInfo appendInfo = barcode.getAppendInfo();
int bindSlot = Integer.valueOf(appendInfo.getBindSlot());
if(bindSlot > 0 || barcode.hasCutInfo()) {
//已经真实绑定过
String so = appendInfo.getSo();
if(!Strings.isNullOrEmpty(so)){
String bindSlot = appendInfo.getBindSlot();
if(barcode.hasCutInfo()) {
bindSlot = "1";
}
//已经绑定过
Map<String,String> map = new HashMap<>();
map.put("reelId", reelId);
map.put("so", appendInfo.getSo());
map.put("slot", bindSlot);
bindReelInfos.add(map);
}
}else{
//无库存,返回Not Found
Map<String,String> map = new HashMap<>();
......@@ -290,7 +297,7 @@ public class QisdaApiController extends BaseController {
}
/**
* 检测料盘是否绑定工单
* 关闭工单
*/
@RequestMapping(value = "/closeSoSeq",method = RequestMethod.POST)
@ResponseBody
......@@ -349,7 +356,7 @@ public class QisdaApiController extends BaseController {
}
/**
* 出库
* 创建需求单
*/
@RequestMapping(value = "/out",method = RequestMethod.POST)
@ResponseBody
......@@ -438,8 +445,12 @@ public class QisdaApiController extends BaseController {
for (OutInfo outInfo : outInfoMap.values()) {
int bindReelNum = getBindReelNum(outInfo);
outInfo.setTotalBindNum(bindReelNum);
int bindReelNum = 0;
if(!outInfo.isPreTailAction()){
bindReelNum = getBindReelNum(outInfo);
outInfo.setTotalBindNum(bindReelNum);
}
log.info("创建出库需求单["+outInfo.gethSerial()+"]" + outInfo.getAction() + " 预估需求料盘数量为:" + bindReelNum);
outInfoDao.save(outInfo);
//新的需求单,更新缓存
......@@ -521,8 +532,21 @@ public class QisdaApiController extends BaseController {
}
return cutReelCount;
}else if(outInfo.isFirstReelAction()){
//首盘,每一条是一盘
return allItems.size();
//首盘
int bindNum = 0;
OutInfo cutOutInfo = soseqCache.getCutActionInfoFromCache(outInfo.getSoseq());
if(cutOutInfo != null){
for (OutItem outItem : cutOutInfo.getOutItems()) {
if(outItem.getRealLockQty()>0){
bindNum++;
}
}
}else{
//每一条有料的是一盘
bindNum = allItems.size();
}
return bindNum;
}else if(outInfo.isTailAction()){
//尾料,根据绑定信息进行统计
//绑定信息暂时放到ChartItem中,value1为需求量,value2为累计物料数量,value3为累计料盘数量
......
......@@ -397,12 +397,12 @@ public class QisdaCache {
});
for (QisdaApiRequest apiRequest : failedList) {
log.info("重发通知指令[" + apiRequest.getMapKey() + "]到Qisda");
//log.info("重发通知指令[" + apiRequest.getMapKey() + "]到Qisda");
String result = HttpHelper.postParam(apiRequest.getUrl(),apiRequest.getParamMap());
log.info("重发通知指令[" + apiRequest.getMapKey() + "]到Qisda返回:" + result);
//log.info("重发通知指令[" + apiRequest.getMapKey() + "]到Qisda返回:" + result);
String resultStr = XmlUtil.getNodeBody("string", result);
if(resultStr.startsWith("-1") || resultStr.startsWith("0")){
log.info(apiRequest.getMapKey() + "Qisda接口调用失败,需要进行重发");
//log.info(apiRequest.getMapKey() + "Qisda接口调用失败,需要进行重发");
}else{
QisdaCache.removeFailedRequest(apiRequest);
return;
......
......@@ -899,12 +899,12 @@ public class QisdaDeviceController extends BaseController {
}else if(cacheTask.isLessSendReel()){
log.info("缺料补发料需要通知Qisda");
Barcode barcodeObj = barcodeManager.findByBarcode(cacheTask.getBarcode());
String latest = outInfo.getShelfLatest();
String latest = outInfo.getShelfLatest("");
//放到线程中
QisdaApi.VMIMateriaRecAss(cacheTask, barcodeObj,latest);
} else{
Barcode barcodeObj = barcodeManager.findByBarcode(cacheTask.getBarcode());
String latest = outInfo.getShelfLatest();
String latest = outInfo.getShelfLatest("");
QisdaApi.VMIMateriaRecAss(cacheTask, barcodeObj,latest);
}
......@@ -1315,6 +1315,18 @@ public class QisdaDeviceController extends BaseController {
return ResultBean.newOkResult("");
}
/**
* 料架放上AGV时,根据RFID清理料架的缓存信息,使料架可以重复使用
*/
@RequestMapping(value = "/agvRemoveRfid")
@ResponseBody
public ResultBean agvRemoveRfid(HttpServletRequest request){
String realRfid = request.getParameter("rfid");
log.info("料架放上AGV时,清理["+realRfid+"]的缓存信息");
if(Strings.isNotBlank(realRfid)){
InquiryShelfBean.agvRemoveRfid(realRfid);
}
return ResultBean.newOkResult("料架放上AGV时,清理["+realRfid+"]的缓存信息成功");
}
}
......@@ -757,7 +757,8 @@ public class TaskService implements ITaskService {
if(outInfo != null) {
InquiryShelfBean.cancelReelTask(task);
Barcode barcodeObj = barcodeManager.findByBarcode(barcode);
QisdaApi.VMIMateriaRecAss(task, barcodeObj, "E");
String latest = outInfo.getShelfLatest("E");
QisdaApi.VMIMateriaRecAss(task, barcodeObj, latest);
}
}
}
......@@ -824,7 +825,8 @@ public class TaskService implements ITaskService {
OutInfo outInfo = outInfoCache.incTaskFinishNum(taskAppendInfo.gethSerial(), 0, 0);
if(outInfo != null) {
InquiryShelfBean.cancelReelTask(task);
QisdaApi.VMIMateriaRecAss(task, barcode, "E");
String latest = outInfo.getShelfLatest("E");
QisdaApi.VMIMateriaRecAss(task, barcode, latest);
}
}
}else if(taskAppendInfo.isUrgentAction() || taskAppendInfo.isReelCutAction()){
......@@ -1619,7 +1621,7 @@ public class TaskService implements ITaskService {
DataLog task = newTask(pos);
//手动出库的当做是工单料,放到皮带线上
task.setUrgentReel(false);
task.setUrgentReel(true);
AppendInfo appendInfo = task.getAppendInfo();
appendInfo.setShelfType(StorageConstants.SHEFL_TYPE.B);
......@@ -2036,20 +2038,20 @@ public class TaskService implements ITaskService {
//int slotIndex = task.getAppendInfo().getSlotIndex();
OutInfo outInfo = outInfoCache.incOutNum(outItem.gethSerial(),outItem.getId(), task.getNum());
String latest = outInfo.getOutLatest();
QisdaApiController.OutFinished(task, barcode, latest);
String outLatest = outInfo.getOutLatest();
QisdaApiController.OutFinished(task, barcode, outLatest);
if(task.isLessSendReel()){
outInfo = outInfoCache.incTaskFinishNum(outItem.gethSerial(),outItem.getSlotlocation(), task.getNum());
if(outInfo != null) {
//缺料补发的需求,需要进行发料
Barcode barcodeObj = barcodeManager.findByBarcode(task.getBarcode());
QisdaApi.VMIMateriaRecAss(task, barcodeObj,latest);
String latest = outInfo.getShelfLatest("E");
QisdaApi.VMIMateriaRecAss(task, barcodeObj, latest);
}
}
if (latest.equals("L")) {
if (outLatest.equals("L")) {
log.info("工单[" + outItem.getSo() + "]需求单["+outItem.gethSerial()+"]的最后一盘出库完成,发送缺料通知");
List<OutItem> outItemList = outItemDao.findByHSerial(outItem.gethSerial());
boolean lessBind = false;
......
......@@ -198,7 +198,7 @@
</div>
</display:column>
<display:column titleKey="Slot" sortProperty="barcode.appendInfo.slotIndex" sortable="true">
${pos.barcode.appendInfo.slotIndex}
${pos.barcode.appendInfo.bindSlot}
</display:column>
<%--<display:column titleKey="barcode.expireDate" sortProperty="barcode.expireDate" sortable="true">--%>
......
......@@ -138,12 +138,14 @@
var mdate = new Date(outInfo.mdate).Format("yyyy-MM-dd hh:mm:ss");
var sdate = new Date(outInfo.sdate).Format("yyyy-MM-dd hh:mm:ss");
var createDate = new Date(outInfo.createDate).Format("yyyy-MM-dd hh:mm:ss");
var infoHtml = '<div class="panel '+ pannelColor+' '+ bgClass + '">' +
'<div class="panel-heading">' +
'<h4 class="panel-title">' +
'<a class="accordion-toggle" data-toggle="collapse" href="#'+outInfo.hSerial+'">' +
moveHandle + //outInfo.firstExecuteTime +
'需求单:'+ outInfo.hSerial+' ['+outInfo.action+'] 工单: ' + outInfo.so +' 备料单: ' + outInfo.refno + '[' + outInfo.sendStatus +'] 工单序号:' + outInfo.soseq +
'<span class="right">创建时间: '+createDate+'</span>' +
'<span class="right">建议时间: '+sdate+'</span>' +
'<span class="right">必须时间: '+mdate+'</span>' +
//'<span class="right">['+outInfo.firstExecuteTime+']</span>' +
......@@ -155,6 +157,7 @@
'<li><i class="fa fa-briefcase"></i>备料单: '+outInfo.refno+'</li>' +
'<li><i class="fa fa-calendar"></i>建议时间:'+sdate+'</li>' +
'<li><i class="fa fa-star"></i>必须出仓日期:'+mdate+'</li>' +
'<li><i class="fa fa-star"></i>创建时间:'+createDate+'</li>' +
'</ul>' +
'<h4 class="list-inline '+bgClass+'">' +
'线体['+outInfo.line+']未解绑料架信息: '+outInfo.lineBindShelfInfo+'' +
......@@ -217,7 +220,7 @@
//if(!moving){
flushOutInfos();
//}
}, 1000);
}, 2000);
// var dragOptions = {
......
......@@ -115,6 +115,10 @@
<fmt:formatDate value="${outInfo.updateDate}" pattern="yyyy-MM-dd HH:mm"/>
</display:column>
<display:column titleKey="需求时间" sortable="true" sortProperty="taskNeedOutDate">
<fmt:formatDate value="${outInfo.taskNeedOutDate}" pattern="yyyy-MM-dd HH:mm"/>
</display:column>
<display:column titleKey="checkOut.operate" media="html" sortProperty="sendStatus" sortable="true">
<c:if test="${!outInfo.sendEnd && !outInfo.closed && !outInfo.executing}">
<button class="btn yellow" id="btn${outInfo.hSerial}" onclick="executeOut('${outInfo.hSerial}')">
......
......@@ -15,6 +15,94 @@
<li class="timeline-purple">
<div class="timeline-time">
<span class="date">2020 </span>
<span class="time">12-24 </span>
</div>
<div class="timeline-icon">
<i class="fa fa-clock-o"></i>
</div>
<div class="timeline-body">
<h2>版本: V2020122415</h2>
<div class="timeline-content">
<ul>
<li>需求单E状态除最后一盘外,其他状态使用E</li>
</ul>
</div>
</div>
</li>
<li class="timeline-green">
<div class="timeline-time">
<span class="date">2020</span>
<span class="time">12-15</span>
</div>
<div class="timeline-icon">
<i class="fa fa-clock-o"></i>
</div>
<div class="timeline-body">
<h2>版本: V2020121514</h2>
<div class="timeline-content">
<ul>
<li>AGV从双层线拉上料架时,清理料架信息,使料架可以重复使用</li>
</ul>
</div>
</div>
</li>
<li class="timeline-blue">
<div class="timeline-time">
<span class="date">2020 </span>
<span class="time">12-14 </span>
</div>
<div class="timeline-icon">
<i class="fa fa-clock-o"></i>
</div>
<div class="timeline-body">
<h2>版本: V2020121414</h2>
<div class="timeline-content">
<ul>
<li>查询料盘绑定接口增加slot字段,当slot大于0时为真实绑定,其他为预绑定</li>
<li>需求单最后一盘E状态修改为EL</li>
<li>排队页面增加需求单创建时间</li>
<li>需求单页面增加需求时间</li>
</ul>
</div>
</div>
</li>
<li class="timeline-yellow">
<div class="timeline-time">
<span class="date">2020 </span>
<span class="time">12-02 </span>
</div>
<div class="timeline-icon">
<i class="fa fa-clock-o"></i>
</div>
<div class="timeline-body">
<h2>版本: V2020120219</h2>
<div class="timeline-content">
<ul>
<li>Fixed: 补料需求单无对应预补料需求单问题</li>
</ul>
</div>
</div>
</li>
<li class="timeline-grey">
<div class="timeline-time">
<span class="date">2020 </span>
<span class="time">12-02 </span>
</div>
<div class="timeline-icon">
<i class="fa fa-clock-o"></i>
</div>
<div class="timeline-body">
<h2>版本: V2020120210</h2>
<div class="timeline-content">
<ul>
<li>Fixed:获取工单小料盘绑定数量接口参数为多个工单序号时有误的问题</li>
</ul>
</div>
</div>
</li>
<li class="timeline-purple">
<div class="timeline-time">
<span class="date">2020 </span>
<span class="time">11-27 </span>
</div>
<div class="timeline-icon">
......
......@@ -239,7 +239,7 @@
<div class="page-footer-inner">
2016&copy; <a href="${ctx}/updateHistory.html">SMD BOX</a>
</div>
<span class="right" style="color: #a3a3a3;">Version: 2020.11.27</span>
<span class="right" style="color: #a3a3a3;">Version: 2020.12.24</span>
<div class="scroll-to-top">
<i class="icon-arrow-up"></i>
</div>
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!