Commit 0cb430a4 孙克

阳光电源增加感应料架

1 个父辈 0ed0ccf9
package com.myproject.bean.utils;
import java.io.Serializable;
public class PosInfo implements Serializable {
/**
* 库位号
*/
private String pos;
/**
* 优先级
*/
private Integer pri;
/**
* 高度
*/
private Integer h;
/**
* 宽度
*/
private Integer w;
public String getPos() {
return pos;
}
public void setPos(String pos) {
this.pos = pos;
}
public Integer getPri() {
return pri;
}
public void setPri(Integer pri) {
this.pri = pri;
}
public Integer getH() {
return h;
}
public void setH(Integer h) {
this.h = h;
}
public Integer getW() {
return w;
}
public void setW(Integer w) {
this.w = w;
}
}
\ No newline at end of file
......@@ -22,7 +22,18 @@ public class StatusBean {
/// </summary>;
private String cid;
/// <summary>
///@ApiOperation("客户端判断CID是否存在")
// @RequestMapping(value = "/service/store/cidIsExists")
// @ResponseBody
// @AnonymousAccess
// public ResultBean cidIsExists(HttpServletRequest request) {
// String cid = request.getParameter("cid");
// Storage storage = dataCache.getStorage(cid);
// if (storage == null) {
// return ResultBean.newErrorResult(1, "smfcore.valueNotFind", "未找到{0}[{1}]", new String[]{"CID", cid});
// }
// return ResultBean.newOkResult(cid);
// } <summary>
/// 请求序列号
/// </summary>
private int seq;
......@@ -71,6 +82,9 @@ public class StatusBean {
/// </summary>
private Map<Integer,BoxStatusBean> boxStatus = new HashMap<>();
private List<PosInfo> posList=null;
/**
* 报警集合
*/
......@@ -462,4 +476,13 @@ public class StatusBean {
}
return doorReelSignal;
}
public List<PosInfo> getPosList() {
return posList;
}
public void setPosList(List<PosInfo> posList) {
this.posList = posList;
}
}
......@@ -38,6 +38,10 @@ public interface IStoragePosManager extends IManager<StoragePos> {
StoragePos getByBarcodeId(String barcodeId);
List<StoragePos> findUsedPosNameByStorageId(String storageId);
List<StoragePos> findDisabled();
List<StoragePos> findEnablePosList(String storageId);
void clearPos(String storageId);
......@@ -100,6 +104,8 @@ public interface IStoragePosManager extends IManager<StoragePos> {
List<StoragePos> findLockPos(String lockId);
List<StoragePos> findByStorage(String storageId);
int countByQuery(Query query);
/**
......
......@@ -17,8 +17,6 @@ import com.myproject.manager.IStoragePosManager;
import com.myproject.util.DateUtil;
import com.myproject.util.PLATE_SIZE;
import com.myproject.util.StorageConstants;
import com.myproject.webapp.controller.webService.DataCache;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -48,6 +46,25 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
@Override
public List<StoragePos> findUsedPosNameByStorageId(String storageId) {
Criteria c = Criteria.where("barcode").exists(true)
.and("enabled").is(true);//可用;
if(!Strings.isNullOrEmpty(storageId)){
c = c.and("storageId").is(storageId);
}
Query query = new Query(c);
// query.fields().include("posName").exclude("id");
return storagePosDao.findByQuery(query);
}
@Override
public List<StoragePos> findDisabled(){
Criteria c = Criteria.where("enabled").is(false);//不可用;
Query query = new Query(c);
return storagePosDao.findByQuery(query);
}
@Override
public List<StoragePos> findEnablePosList(String storageId) {
Criteria c = Criteria.where("storageId").is(storageId).and("enabled").is(true);//可用
Query query = new Query(c);
......@@ -565,6 +582,11 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
@Override
public List<StoragePos> findByStorage(String storageId) {
return storagePosDao.findListByCondition(new String[]{"storageId" }, new String[]{storageId });
}
@Override
public int countByQuery(Query query) {
return storagePosDao.countByQuery(query);
}
......
......@@ -260,7 +260,7 @@ public class StorageConstants {
/**
* 6智能料架
*/
SHELF("storage.type.shelf"),
SHELF("storage.type.nlp"),
/**
* 7 料柜
......@@ -293,6 +293,7 @@ public class StorageConstants {
*/
VERTICALBOX("storage.type.verticalBox")
;
private String key;
......
package com.myproject.webapp.controller.storage;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.myproject.bean.CodeBean;
import com.myproject.bean.json.ResultBean;
import com.myproject.bean.update.Barcode;
import com.myproject.bean.update.DataLog;
import com.myproject.bean.update.Storage;
import com.myproject.bean.update.StoragePos;
import com.myproject.bean.utils.PosInfo;
import com.myproject.bean.utils.StatusBean;
import com.myproject.dao.mongo.IDataLogDao;
import com.myproject.exception.ValidateException;
import com.myproject.manager.IBarcodeManager;
import com.myproject.manager.IStorageManager;
import com.myproject.manager.IStoragePosManager;
import com.myproject.util.StorageConstants;
import com.myproject.webapp.controller.webService.DataCache;
import com.myproject.webapp.controller.webService.ITaskService;
import com.myproject.webapp.controller.webService.StorageDataController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 挚锦料架
*/
@Controller
public class NLPShelfController extends BaseController {
@Autowired
private DataCache dataCache;
@Autowired
private ITaskService taskService;
@Autowired
private IStorageManager storageManager;
@Autowired
protected IStoragePosManager storagePosManager;
@Autowired
protected IBarcodeManager barcodeManager;
@Autowired
private IDataLogDao dataLogDao;
@RequestMapping("/storage/nlp/{cid}")
public String cabinetView(@PathVariable String cid, HttpServletRequest request){
request.getSession().setAttribute("show",cid);
Storage storage = dataCache.getStorage(cid);
request.setAttribute("storage",storage);
return "storage/nlpShelf";
}
/**
*
*/
@RequestMapping("/service/store/nlp/putInCode")
@ResponseBody
public String putInCode(HttpServletRequest request){
final String cid = request.getParameter("cid");
String code = request.getParameter("code");
Storage storage = dataCache.getStorage(cid);
Collection<DataLog> queueTasks = taskService.getQueueTasks();
for (DataLog queueTask : queueTasks) {
if (queueTask.isPutInTask() && (queueTask.isWait() || queueTask.isExecuting())) {
if (queueTask.getStorageId().equals(storage.getId())) {
log.info("codeIn [" + code + "][" + cid + "]入库时取消料架[" + queueTask.getStorageId() + "]的未完成入库任务");
taskService.cancelTask(queueTask.getId());
}
}
}
CodeBean codeBean = dataCache.resolveSingleCode(code);
if(codeBean.isValid()){
if(storage.isAccShelf()){
Barcode barcode = codeBean.getBarcode();
try {
long now = System.currentTimeMillis();
//5秒内同一个条码忽略
Date usedDate = barcode.getUsedDate();
if(usedDate != null && now - usedDate.getTime() < 5000){
return "条码操作频繁,请稍后再试";
}
StoragePos inPos = storagePosManager.getByBarcodeId(barcode.getId());
if(inPos != null){
Collection<DataLog> allTasks = taskService.getQueueTasks();
for (DataLog task : allTasks) {
if(task.getCid().equals(cid) && task.getBarcode() != null && task.getBarcode().equals(barcode.getBarcode())){
taskService.addTaskToFinished(inPos,null,null);
opPosLight("close",storage,inPos,null);
return "OK"+getText("shelf.msg.outConfirm",new String[]{inPos.getPosName()},request.getLocale(),"出库完成, 库位["+inPos.getPosName()+"]灭灯");
}
}
return getText("shelf.msg.noTask",new String[]{inPos.getPosName()},request.getLocale(),"操作失败,已在库位["+inPos.getPosName()+"]中,未找到对应的出库任务");
}
// List<Storage> storageList = Lists.newArrayList(storage);
// StoragePos pos = taskService.findEmptyPosForPutIn(storageList, barcode);
// int delayCloseTime = 30000;
// String color = "green";
// if(pos != null){
// log.info(barcode.getPartNumber()+" [ "+barcode.getBarcode()+" ] " + "入库到:" + storage.getName()+"["+cid+"] " + pos.getPosName());
// taskService.addTaskToFinished(pos,barcode,null);
// openAndCloseLights(storage,pos.getPosName(),delayCloseTime,color);
// pos.setCanCheckOutTime(System.currentTimeMillis() + delayCloseTime);
// return "OK"+getText("shelf.msg.inOk",new String[]{pos.getPosName()},request.getLocale(),"操作成功,请放入库位["+pos.getPosName()+"]");
// }else{
// //库位没找到
// String sizeInfo = barcode.getPlateSize()+" x "+ barcode.getHeight();
// String msg = "未找到适合["+sizeInfo +"]的库位";
// log.info(msg);
// msg = getText("shelf.msg.inError",new String[]{sizeInfo},request.getLocale(),msg);
// return msg;
// }
} catch (Exception e) {
log.error("Error:"+e.getMessage());
return getText(e.getMessage(), null,request.getLocale(),e.getMessage());
}
}
}else{
String msg = getText(codeBean.getErrorCode(),codeBean.getParams(),request.getLocale(),codeBean.getError());
return msg;
}
return "";
}
protected ResultBean putIn(String loginUser,String storageId, Barcode barcode) {
String pn = barcode.getPartNumber();
String reelId = barcode.getBarcode();
try {
//需要模拟一个库位
DataLog dataLog = new DataLog();
dataLog.setBarcode(reelId);
dataLog.setPartNumber(pn);
dataLog.setType(StorageConstants.OP.PUT_IN);
barcode.setPutInTime(System.currentTimeMillis());
barcodeManager.save(barcode);
dataLog.setNum(barcode.getAmount());
dataLog.setStatus(StorageConstants.OP_STATUS.WAIT.name());
dataLog.setStorageId(storageId);
dataLog.setMemo(barcode.getMemo());
dataLog.setOperator(loginUser);
if (!Strings.isNullOrEmpty(storageId)) {
Storage storage = dataCache.getStorageById(storageId);
if (storage != null) {
dataLog.setCid(storage.getCid());
dataLog.setStorageName(storage.getName());
}
}
try {
taskService.addTaskToExecute(dataLog);
} catch (Exception e) {
return ResultBean.newErrorResult(-1, "入库失败:" + e.getMessage());
}
} catch (ValidateException e) {
log.error(e.toString());
return ResultBean.newErrorResult(1, e.getDefaultMsg());
}
return ResultBean.newOkResult("");
}
/**
* 客户端sensor变化
*/
@RequestMapping("/service/store/sensorShelf/sensorChange")
@ResponseBody
public ResultBean sensorChange(HttpServletRequest request, HttpSession httpSession) {
String cid = request.getParameter("cid");
Storage storage = dataCache.getStorage(cid);
if (storage == null) {
return ResultBean.newErrorResult(-1, cid + "对应的料架不存在");
}
String[] hasReelPosList = request.getParameterValues("hasReelPosList");
String[] noReelPosList = request.getParameterValues("noReelPosList");
//实际信号有料,数据库无信息
String[] hasReelPosErrorList = request.getParameterValues("hasReelPosErrorList");
//实际信号无料,数据库有信息
String[] noReelPosErrorList = request.getParameterValues("noReelPosErrorList");
if (hasReelPosErrorList == null) {
hasReelPosErrorList = new String[]{};
}
if (noReelPosErrorList == null) {
noReelPosErrorList = new String[]{};
}
List<String> usedPosNameList = dataCache.getUsedPosNameList(storage.getCid());
List<String> ngToOk = new ArrayList<>();
//数据库有信息,实际无料
if(noReelPosErrorList.length>0){
//log.info("开始检测noReelPosErrorList");
for (String noReelPosName : noReelPosErrorList) {
if(!usedPosNameList.contains(noReelPosName)){
ngToOk.add(noReelPosName);
log.info(cid + "sensorChange 客户端上传 noReelPosErrorList 库位["+noReelPosName+"]数据库无物料,放入ngToOk");
}
}
}
//存储感应料架库位报警信息,展示到界面,暂不实现
// List<List<String>> data = new ArrayList<>();
// data.add(Arrays.asList(hasReelPosErrorList));
// data.add(Arrays.asList(noReelPosErrorList));
// DevicesStatusUtil.updateDeviceData(cid, data);
List<String> inOkList = new ArrayList<>();
List<String> inNgList = new ArrayList<>();
List<String> outOkList = new ArrayList<>();
List<String> outNgList = new ArrayList<>();
if (hasReelPosList != null) {
Set<String> disabledPosNameSet = dataCache.getDisabledPosNameSet();
List<String> usedPosList = dataCache.getUsedPosNameList(cid);
List<String> newList=new ArrayList<>();
for (String posName : hasReelPosList) {
if(disabledPosNameSet.contains(posName)){
//log.info(cid + "sensorChange hasReelPosList [" + posName + "]库位被禁用,忽略");
continue;
}else if(usedPosList.contains(posName)){
log.info(cid + "sensorChange hasReelPosList [" + posName + "]库位已有物料,加入到ok列表");
inOkList.add(posName);
continue;
}
newList.add(posName);
}
hasReelPosList = newList.toArray(new String[newList.size()]);
//入库的库位列表
if (hasReelPosList.length > 1) {
String msg = "不可同时放入多盘物料:" + String.join(",", hasReelPosList);
log.error(msg);
for (String posStr : hasReelPosList) {
inNgList.add(posStr);
}
} else if (hasReelPosList.length == 1) {
log.info(cid + "开始检测执行入库到库位:["+hasReelPosList[0]+"]");
StoragePos pos = storagePosManager.getByPosName(hasReelPosList[0]);
if (pos == null) {
String msg = "未找到库位:" + String.join(",", hasReelPosList);
log.error(msg);
} else if (!pos.getStorageId().equals(storage.getId())) {
String msg = "[" + storage.getName() + "]未找到库位:" + String.join(",", hasReelPosList);
log.error(msg);
}
//如果库位有料,直接结束
else if (pos.getBarcode() != null) {
log.info("料架[" + cid + "]入库库位[" + pos.getPosName() + "]已有料: [" + pos.getBarcode().getBarcode() + "]");
} else {
log.info(cid + "处理有料库位:["+pos.getPosName()+"]");
boolean posInResult = handlePosIn(storage,pos);
log.info(cid + "处理有料库位:["+pos.getPosName()+"]完成,结果:" + posInResult);
if(posInResult){
inOkList.add(pos.getPosName());
}else{
inNgList.add(pos.getPosName());
}
}
}
}
if (noReelPosList != null) {
//出库
for (String noReelPosName : noReelPosList) {
log.info(cid + "处理无料库位:[" + noReelPosName + "]");
boolean handleNoReelPosResult = handleNoReelPos(storage, usedPosNameList, noReelPosName);
log.info(cid + "处理无料库位:[" + noReelPosName + "]完成,结果:" + handleNoReelPosResult);
if (handleNoReelPosResult) {
outOkList.add(noReelPosName);
} else {
outNgList.add(noReelPosName);
}
}
}
Map<String, List<String>> dataMap = new HashMap<>();
dataMap.put("inOkList", inOkList);
dataMap.put("inNgList", inNgList);
dataMap.put("outOkList", outOkList);
dataMap.put("outNgList", outNgList);
dataMap.put("ngToOk", ngToOk);
return ResultBean.newOkResult(dataMap);
}
/**
* 处理库位入库
* @param storage
* @param pos
* @return
*/
private boolean handlePosIn(Storage storage, StoragePos pos){
boolean inResult = false;
Collection<DataLog> queueTasks = taskService.getQueueTasks();
for (DataLog queueTask : queueTasks) {
boolean isPutInTask = false;
if (!Strings.isNullOrEmpty(queueTask.getStorageId())) {
if (queueTask.isPutInTask() && queueTask.getStorageId().equals(storage.getId())) {
isPutInTask = true;
}
}
if (isPutInTask) {
queueTask.setCid(storage.getCid());
queueTask.setPosId(pos.getId());
queueTask.setPosName(pos.getPosName());
queueTask.setStorageId(storage.getId());
queueTask.setStorageName(storage.getName());
try {
//入库完成,发送入库完成请求
log.info(queueTask.getBarcode() + "入库完成,发送入库完成请求");
taskService.putInFinished(queueTask);
String msg = queueTask.getBarcode() + "入库到" + pos.getPosName() + "成功";
log.info(msg);
inResult = true;
break;
} catch (Exception e) {
log.error("入库出错" + e.getMessage());
}
return inResult;
}
}
log.warn("未找到["+pos.getPosName()+"]的入库任务");
return inResult;
}
/**
* 处理客户端发上来的无料库位
*
* @param storage
* @param usedPosNameList
* @param noReelPosName
* @return
*/
private boolean handleNoReelPos(Storage storage, List<String> usedPosNameList, String noReelPosName) {
boolean handleResult = false;
if (!usedPosNameList.contains(noReelPosName)) {
log.info("库位: " + noReelPosName + " 中数据库中已无物料信息,加入outOkList");
handleResult = true;
} else {
StoragePos pos = storagePosManager.getByPosName(noReelPosName);
if (pos == null) {
log.error("sensorChange 未找到库位 noReelPosList [" + noReelPosName + "],加入outOkList");
handleResult = true;
} else {
if (!pos.isEnabled()) {
log.error("sensorChange noReelPosList [" + noReelPosName + "]已禁用,加入outOkList");
handleResult = true;
} else if (!pos.getStorageId().equals(storage.getId())) {
String msg = "[" + storage.getName() + "]未找到库位:" + noReelPosName + ",加入outOkList";
log.error(msg);
handleResult = true;
} else if (pos.getBarcode() == null) {
log.info("库位: " + noReelPosName + " 数据库中已无物料信息,加入outOkList");
handleResult = true;
} else {
Collection<DataLog> queueTasks = taskService.getQueueTasks();
String outResult = "";
for (DataLog queueTask : queueTasks) {
//只有执行中的任务才可以正常出库
if (queueTask.isExecuting() && queueTask.isCheckOutTask() && queueTask.getPosName().equals(noReelPosName)) {
//出库完成
try {
outResult = noReelPosName;
taskService.checkoutFinished(queueTask);
String msg = queueTask.getBarcode() + "从" + noReelPosName + "出库成功";
log.info(msg);
break;
} catch (Exception e) {
log.error("库位:" + noReelPosName + "出库出错", e);
break;
}
}
}
if (outResult.isEmpty()) {
handleResult = false;
String msg = "未找到[" + noReelPosName + "]的出库任务";
log.error(msg);
//WebSocketServer.sendMsg("",new SocketMsg(msg, MsgType.ERROR,"smfclient.nlp.noOutTask",new String[]{posName,storage.getName()}));
} else {
handleResult = true;
}
}
}
}
return handleResult;
}
/**
* 获取料架的库位占用及出库任务
*/
@RequestMapping("/service/store/sensorShelf/shelfStatus")
@ResponseBody
public ResultBean shelfStatus(HttpServletRequest request) {
String cid = request.getParameter("cid");
List<String> posList = dataCache.getUsedPosNameList(cid);
List<String> outTaskPosList = new ArrayList<>();
Collection<DataLog> queueTasks = taskService.getQueueTasks(cid);
String color = "blue";
for (DataLog task : queueTasks) {
//只发执行中的任务
if (task.isCheckOutTask() && task.isExecuting()) {
String outTaskPos = task.getPosName() + "=" + color;
outTaskPosList.add(outTaskPos);
}
}
String hasReelPosColor = "orange";
//hasReelPosColor = ORDER_COLOR.DARKGREEN.name().toLowerCase();
// if(lightPosCidList.contains(cid)){
// hasReelPosColor = ORDER_COLOR.LIGHTBLUE.name();
// }
hasReelPosColor = "off";
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("hasReelPosList", posList);
dataMap.put("hasReelPosColor", hasReelPosColor);
dataMap.put("outTaskList", outTaskPosList);
//log.info("客户端获取["+cid+"]库位占用情况返回");
return ResultBean.newOkResult(dataMap);
}
/**
* 获取料架的库位占用情况
*/
@RequestMapping("/service/store/sensorShelf/hasReelPosList")
@ResponseBody
public ResultBean checkAll(HttpServletRequest request) {
String cid = request.getParameter("cid");
List<String> posList = dataCache.getUsedPosNameList(cid);
return ResultBean.newOkResult(posList);
}
/**
* 操作库位灯(开灯,或关灯)
* @param opKey
* @param storage
* @param pos
* @param colorStr
*/
private void opPosLight(String opKey, Storage storage, StoragePos pos, String colorStr){
String opStr = pos.getPosName();
if(!Strings.isNullOrEmpty(colorStr)){
opStr =opStr+ "=" + colorStr;
}
StorageDataController.appendOp(storage.getCid(), opKey , opStr);
log.info("操作库位["+pos.getPosName()+"]" + opKey + " : " + opStr);
}
//客户端判断CID是否存在")
@RequestMapping(value = "/service/store/cidIsExists")
@ResponseBody
public ResultBean cidIsExists(HttpServletRequest request) {
String cid = request.getParameter("cid");
Storage storage = dataCache.getStorage(cid);
if (storage == null) {
return ResultBean.newErrorResult(1, "未找到cid" +cid);
}
return ResultBean.newOkResult(cid);
}
//客户端上传料仓库位列表")
@RequestMapping(value = "/service/store/uploadStoragePos")
@ResponseBody
public ResultBean uploadStoragePos(@RequestBody final StatusBean statusBean, HttpServletRequest request) {
String cid = statusBean.getCid();
Storage storage = dataCache.getStorage(cid);
if (storage == null) {
log.error("uploadStoragePos料仓cid: [" + cid + "]不存在,默认自动创建料仓");
//自动创建料仓
storage = autoCreateStorage(cid);
if (storage == null) {
return ResultBean.newErrorResult(-1, "未找到cid:" +cid);
}
}
//料仓已存在,判断料仓是否有库位
List<StoragePos> storagePosList = storagePosManager.findByStorage(storage.getId());
if (storagePosList.size() > 0) {
return ResultBean.newErrorResult(1, "料仓"+cid+"已有库位数:"+storagePosList.size());
}
//取库位
List<PosInfo> posInfoList=statusBean.getPosList();
List<StoragePos> newList=new ArrayList<>();
List<String> posNameList=new ArrayList<>();
if(posInfoList!=null&&posInfoList.size()>0){
int row = 1;
int newRowCount = 0;
for (PosInfo pos : posInfoList) {
row++;
if (Strings.isNullOrEmpty(pos.getPos())) {
log.warn("第" + row + "条库位号中有空白内容,此行忽略");
continue;
}
if (posNameList.contains(pos.getPos())) {
log.warn("第" + row + "条库位号[" + storage + "]重复,只保留第一条,忽略其他行");
} else {
StoragePos posInfo = new StoragePos();
posInfo.setStorageId(storage.getId());
posInfo.setPosName(pos.getPos());
posInfo.setH(pos.getH());
posInfo.setW(pos.getW());
posInfo.setPriority(pos.getPri());
newRowCount++;
newList.add(posInfo);
}
}
if(newList.size()>0){
storagePosManager.insertAll(newList);
}
try {
dataCache.reloadStorage(storage);
} catch (ValidateException e) {
log.error("reload storage",e);
}
String msg = "读取到["+row+"]行数据:为料仓["+storage.getCid()+"]新增["+newRowCount+"]条库位号";
log.info(msg);
}
return ResultBean.newOkResult(cid);
}
public Storage autoCreateStorage(String cid) {
//判断cid存在
Storage storage = null;
storage = dataCache.getStorage(cid);
if (storage != null) {
return storage;
}
storage = new Storage();
storage.setCid(cid);
storage.setType(StorageConstants.TYPE.SHELF.name());
storage.setName(cid);
storage.setCompatibleType(StorageConstants.COMPATIBLE_TYPE.FULLY_COMPATIBLE);
storage.setSourcePath("");
try {
storage = storageManager.save(storage);
dataCache.reloadStorage(storage);
log.info("AutoCreateStorage :自动创建料仓完成:cid[" + storage.getCid() + "]name[" + storage.getName() + "]type[" + storage.getType() + "]");
} catch (ValidateException e) {
log.error("AutoCreateStorage失败",e);
}
return null;
}
}
......@@ -36,6 +36,7 @@ public class DataCache{
protected final transient Logger log = LogManager.getLogger(getClass());
//客户
public static class CUSTOMER{
public static String LIAN_DIAN = "LianDian";
......@@ -715,10 +716,13 @@ public class DataCache{
//出库
amount = - barcode.getAmount();
storage.emptyOnePos(pos);
removeUsedPosNameList(cid, pos.getPosName());
}else{
//入库
amount = barcode.getAmount();
storage.useOnePos(pos);
addUsedPosNameList(cid, pos.getPosName());
}
allStorage.put(cid, storage);
return updateInventoryAmount(cid,partNumber,amount);
......@@ -744,4 +748,89 @@ public class DataCache{
return allBoxMap;
}
/**
* 库位占用Map, key为cid,value为已使用的库位列表
*/
private static Map<String, List<String>> usedPosNameMap = new ConcurrentHashMap<>();
/**
* 出库时清除使用库位列表
*/
private void removeUsedPosNameList(String cid, String posName) {
List<String> usedPosNameList = getUsedPosNameList(cid);
usedPosNameList.remove(posName);
usedPosNameMap.put(cid, usedPosNameList);
}
/**
* 入库时增加使用库位列表
*/
private void addUsedPosNameList(String cid, String posName) {
List<String> usedPosNameList = getUsedPosNameList(cid);
usedPosNameList.add(posName);
usedPosNameMap.put(cid, usedPosNameList);
}
/**
* 获取设备所有占用的库位名称列表
*/
public synchronized List<String> getUsedPosNameList(String cid) {
if(cid == null || cid.isEmpty()){
return new ArrayList<>();
}
List<String> posNameList = usedPosNameMap.get(cid);
if (posNameList == null) {
Storage storage = getStorage(cid);
posNameList = new ArrayList<>();
if (storage != null) {
log.info("加载[" + cid + "]所有已使用库位到缓存");
List<StoragePos> allPos = storagePosManager.findNotEmptyByStorageId(storage.getId());
for (StoragePos pos : allPos) {
posNameList.add(pos.getPosName());
}
usedPosNameMap.put(cid, posNameList);
}
}
return posNameList;
}
/**
* 禁用库位名称列表
*/
private static Set<String> disabledPosNameSet;
/**
* 获取禁用库位缓存
*/
public Set<String> getDisabledPosNameSet(){
initDisabledPosNameSet();
return disabledPosNameSet;
}
/**
* 初始化禁用库位缓存
*/
private synchronized void initDisabledPosNameSet(){
if(disabledPosNameSet == null){
disabledPosNameSet = new HashSet<>();
List<StoragePos> disabledPosList = storagePosManager.findDisabled();
for (StoragePos disabledPos : disabledPosList) {
disabledPosNameSet.add(disabledPos.getPosName());
}
log.info("加载禁用库位缓存,共" + disabledPosNameSet.size() + "个");
}
}
/**
* 更新禁用库位缓存
*/
public void updateDisablePos(StoragePos pos){
initDisabledPosNameSet();
if(pos.isEnabled()){
disabledPosNameSet.remove(pos.getPosName());
}else{
disabledPosNameSet.add(pos.getPosName());
}
}
}
......@@ -75,4 +75,9 @@ public interface ITaskService {
void addTaskToFinished(StoragePos pos, Barcode barcode, String opUser);
void addTaskToExecute(DataLog task);
//入仓位完成
void putInFinished(DataLog task) throws ValidateException;
void checkoutFinished(DataLog task) throws ValidateException;
}
......@@ -1699,6 +1699,7 @@ public class TaskService implements ITaskService {
//入仓位完成
@Override
public void putInFinished(DataLog task) throws ValidateException {
//从队列里面移除操作
......@@ -1810,6 +1811,7 @@ public class TaskService implements ITaskService {
/**
* 出库完成
*/
@Override
public void checkoutFinished(DataLog task) throws ValidateException {
//从队列里面移除操作
......
......@@ -168,7 +168,7 @@
<c:set var="detailUrl" value="${ctx}/cabinet/${storage.cid}"/>
</c:if>
<c:if test="${storage.shelf}">
<c:set var="detailUrl" value="${ctx}/storage/shelf/${storage.cid}"/>
<c:set var="detailUrl" value="${ctx}/storage/nlp/${storage.cid}"/>
</c:if>
<c:if test="${storage.accShelf}">
<c:set var="detailUrl" value="${ctx}/storage/accShelf/${storage.cid}"/>
......
<%@ page import="com.myproject.util.StorageConstants" %>
<%@ include file="/common/taglibs.jsp" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<style type="text/css">
.box{
margin-top: 10px;
}
.alert{
padding:8px;
}
.partnumber-box{
height: 100px;text-align: center;
padding-top:35px;
margin-bottom:10px;
font-size: 16px;
vertical-align: middle;
word-wrap:break-word ;
cursor: pointer;
}
.table-scrollable{
overflow-y: auto;
}
</style>
<link href="${ctx}/scripts/lobibox/css/lobibox.min.css?id=2" rel="stylesheet" type="text/css"/>
<div class="row" id="codeBox">
<div class="col-md-6 col-sm-6">
<input type="text" class="form-control" id="scan-code"/>
</div>
<div class="col-md-6 col-sm-6">
<div class="alert alert-success" id="msg">&nbsp;
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-sm-12">
<!-- BEGIN EXAMPLE TABLE PORTLET-->
<div class="portlet box blue">
<div class="portlet-title">
<div class="caption">
${storage.name}
</div>
<div class="actions">
<button type="button" class="btn btn-fit-height default" onclick="checkAllPos();">
<fmt:message key="shelf.btn.posCheck"/>
</button>
<button type="button" class="btn btn-fit-height default" onclick="closeAllLights();">
<fmt:message key="shelf.btn.closeAll"/>
</button>
<button type="button" class="btn btn-fit-height yellow" onclick="showPartNumbers();">
<i class="fa fa-sign-out"></i><fmt:message key="button.checkout"/>
</button>
</div>
</div>
<div class="portlet-body">
<div class="table-scrollable" style="height:400px;">
<table class="table table-striped table-hover table-bordered no-footer" role="grid" aria-describedby="sample_editable_1_info">
<thead>
<tr role="row">
<th><fmt:message key="barcode.barcode"/></th>
<th><fmt:message key="barcode.partNumber"/></th>
<th><fmt:message key="checkOut.pos"/></th>
<th><fmt:message key="dataLog.type"/></th>
<th><fmt:message key="dataLog.status"/></th>
<th><fmt:message key="dataLog.date"/></th>
</tr>
</thead>
<tbody class="dataTable">
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tbody>
</table>
</div>
</div>
</div>
<!-- END EXAMPLE TABLE PORTLET-->
</div>
</div>
<div id="allPartNumbers" class="modal fade" tabindex="-1" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog" style="margin-top: 10%;width:80%;margin-left:10%;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="modal-title" style="font-weight: 500;"><fmt:message key="button.checkout"/> </h4>
<input type="text" class="form-control" id="searchPn"/>
</div>
<div class="modal-body">
<div class="row" id="partNumberItems">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">
<div class="bg-blue-madison partnumber-box">xxx</div>
</div>
</div>
</div>
<div class="modal-footer">
<div id="footerBtn">
<a href="" class="btn yellow left" id="findAndOut"><i class="fa fa-sign-out"></i><fmt:message key="allBoxView.findAndOut"/></a>
<button type="button" class="btn green" onclick="lastPage()" id="lastPage">
<fmt:message key="allBoxView.lastPage"/></button>
<button type="button" class="btn green" onclick="nextPage()" id="nextPage">
<fmt:message key="allBoxView.nextPage"/></button>
</div>
<%--<button type="button" data-dismiss="modal" class="btn default" id="cancelAuthBtn">取消</button>--%>
</div>
</div>
</div>
</div>
<div id="sizeConfirm" class="modal fade" tabindex="-1" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog" style="margin-top: 10%;width:80%;margin-left:10%;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" style="font-weight: 500;"><fmt:message key="shelf.size.title"/></h4>
</div>
<div class="modal-body">
<div class="row">
<c:forEach items="${storage.usageMap}" var="usageEntry">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-3">
<div class="bg-blue-madison partnumber-box psizeBox">${usageEntry.value.sizeStr}</div>
</div>
</c:forEach>
</div>
</div>
<div class="modal-footer">
<%--<button type="button" data-dismiss="modal" class="btn default" id="cancelAuthBtn">取消</button>--%>
</div>
</div>
</div>
</div>
<fmt:message key="op.1" var="op.1"/>
<fmt:message key="op.2" var="op.2"/>
<fmt:message key="inOutList.in" var="in_label"/>
<fmt:message key="inOutList.out" var="out_label"/>
<fmt:message key="op.status.wait" var="op_status_wait"/>
<fmt:message key="op.status.executing" var="op_status_executing"/>
<fmt:message key="op.status.pause" var="op_status_pause"/>
<fmt:message key="op.status.finished" var="op_status_finished"/>
<fmt:message key="op.status.cancel" var="op_status_cancel"/>
<fmt:message key="op.status.end" var="op_status_end"/>
<c:set var="scripts" scope="request">
<script type="text/javascript">
function showMsg(msg){
if(msg == ""){
$("#msg").attr("class","");
$("#msg").text("");
}else{
var error = true;
if(msg.indexOf("OK") == 0){
error = false;
msg = msg.substr(2);
}
if(msg.indexOf("0") == 0){
error = false;
msg = msg.substr(1);
}
if(msg.indexOf("x") == 0){
msg = msg.substr(1);
}
if(error){
$("#msg").attr("class","alert alert-danger");
}else{
$("#msg").attr("class","alert alert-success");
}
$("#msg").text(msg);
}
}
$("#scan-code").change(function () {
var codeValue = $(this).val();
$(this).val("");
showMsg("");
$(this).attr("placeholder", codeValue);
$.post("${ctx}/service/store/accShelf/putInCode", {cid: '${show}', code: codeValue}, function (data) {
showMsg(data);
if(data.indexOf("x") == 0){
//弹框,添加=7x8=尺寸信息后重新请求
$("#sizeConfirm").modal("show");
}
});
});
$(".psizeBox").click(function(){
$("#sizeConfirm").modal("hide");
var codeValue = $("#scan-code").attr("placeholder");
var sizeStr = $(this).text();
if(codeValue){
var newCodeStr = "="+sizeStr+"="+codeValue;
$.post("${ctx}/service/store/accShelf/putInCode", {cid: '${show}', code: newCodeStr}, function (data) {
showMsg(data);
});
}
});
setInterval(function(){
if($('#allPartNumbers').is(':visible')) {
$("#searchPn").focus();
}else{
$("#scan-code").focus();
}
}, 1000);
//页码从0开始
var pageIndex = 0;
var partNumberItems = [];
var itemPerPage = 12;
var bgColors = ["bg-blue-madison","bg-green-haze","bg-purple-plum","bg-red-intense","bg-green","bg-yellow","bg-blue","bg-red","bg-purple","bg-blue-ebonyclay","bg-red-sunglo","bg-yellow-crusta"];
showPartNumbers = function(type){
var findAndOutHref = '${ctx}/component/storagePosFind.html';
$("#findAndOut").attr("href",findAndOutHref);
$("#searchPn").val("");
$.post("${ctx}/service/store/storageTypeInventory", {type: type, cid: '${show}'}, function (data) {
pageIndex = -1;
partNumberItems = data;
nextPage();
});
}
nextPage=function(){
pageIndex ++ ;
pageShow();
}
lastPage = function(){
pageIndex -- ;
pageShow();
}
disableBtn = function(){
$("#lastPage").show();
$("#nextPage").show();
$("#footerBtn").show();
//上一页不可用
if(pageIndex <= 0){
$("#lastPage").addClass("disabled");
}else{
$("#lastPage").removeClass("disabled");
}
var totalPage = Math.ceil(partNumberItems.length/itemPerPage);
if(pageIndex + 1 >= totalPage - 1){
$("#nextPage").addClass("disabled");
}else{
$("#nextPage").removeClass("disabled");
}
if(totalPage <= 1){
$("#lastPage").hide();
$("#nextPage").hide();
}
}
pageShow = function(){
var itemStr = "";
var endIndex = itemPerPage * (pageIndex+1);
if(endIndex > partNumberItems.length){
endIndex = partNumberItems.length;
}
for(var index = itemPerPage * pageIndex;index<endIndex;index++){
var pn = partNumberItems[index].partNumber;
itemStr = itemStr + "<div class='col-lg-3 col-md-3 col-sm-6 col-xs-12' onclick='checkoutByPartNumber(\""+pn+"\");'> " +
"<div class='"+bgColors[index%itemPerPage]+" partnumber-box'>"+pn+"</div></div>";
}
if(itemStr == ""){
itemStr = "<div style='font-size: 20px;text-align: center;'>${noReel_label}</div>";
}
$("#partNumberItems").html(itemStr);
disableBtn();
$("#allPartNumbers").modal("show");
}
$("#searchPn").on('input propertychange',function(){
FilterPnItems();
});
function FilterPnItems(){
$("#lastPage").hide();
$("#nextPage").hide();
var itemStr = "";
var pnForSearch = $("#searchPn").val();
if(pnForSearch == ""){
pageShow();
return;
}
$.post("${ctx}/service/store/resolveBarcode", {code: pnForSearch}, function (data) {
var thePn = pnForSearch;
if (data.error == null) {
thePn = data.barcode.partNumber;
}
for(var index in partNumberItems){
var pn = partNumberItems[index].partNumber;
if(pn.indexOf(thePn) >= 0){
itemStr = itemStr + "<div class='col-lg-3 col-md-3 col-sm-6 col-xs-12' onclick='checkoutByPartNumber(\""+pn+"\");'> " +
"<div class='"+bgColors[index%itemPerPage]+" partnumber-box'>"+pn+"</div></div>";
}
}
if(itemStr == ""){
itemStr = "<div style='font-size: 20px;text-align: center;'>${noReel_label}</div>";
}
$("#partNumberItems").html(itemStr);
});
}
closeAllLights = function(){
$.post("${ctx}/service/store/accShelf/op", {opKey: 'closeAll', opValue:'true', cid: '${show}'}, function (data) {
showMsg(data);
waitting();
});
}
checkAllPos = function(){
$.post("${ctx}/service/store/accShelf/checkAll", {cid: '${show}'}, function (data) {
showMsg(data);
waitting();
});
}
checkoutByPartNumber = function(partnumber) {
$.post("${ctx}/service/store/checkout.html", {pn: partnumber, cid: '${show}',cl:'0'}, function (data) {
$("#allPartNumbers").modal("hide");
showMsg(data);
waitting();
});
}
function updateTasks(cid,seconds){
//任务列表
$.post("${ctx}/service/store/tasks", {cid: cid, seconds:seconds}, function (data) {
$(".dataTable").html("");
for(var item in data){
var taskId = data[item].id;
var partNumber = data[item].partNumber;
var barcode = data[item].barcode;
var posStr = data[item].posStr;
var typeStr = "${in_label}";
if(data[item].type == 2){//出库
typeStr = "${out_label}";
}
var statusStr = "";
if(data[item].cancel){
statusStr ="${op_status_cancel}";
} else if(data[item].executing){
statusStr ="${op_status_executing}";
}else if(data[item].finished){
statusStr ="${op_status_finished}";
}else if(data[item].wait){
statusStr ="${op_status_wait}";
}else if(data[item].end){
statusStr ="${op_status_end}";
}
var dateStr = data[item].updateDateStr;
var tdStr =
"<td>"+barcode+"</td>"+
"<td>"+partNumber+"</td>"+
"<td>"+posStr+"</td>"+
"<td>"+typeStr+"</td>"+
"<td><span class='label label-sm label-"+data[item].status.toLowerCase()+"'>"+statusStr+"</span></td>"+
"<td>"+dateStr+"</td>";
var trStr = "<tr>" + tdStr+ "</tr>";
$(".dataTable").append(trStr);
}
});
}
//updateTasks('${show}',-10*60);
setInterval(function(){
updateTasks('${show}',-10*60);
}, 1000);
waitting = function(){
Metronic.blockUI({
iconOnly: true,
overlayColor: '#4b8df8'
});
window.setTimeout(function() {
Metronic.unblockUI();
}, 1500);
}
</script>
</c:set>
\ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!