Commit 6fca78d8 zshaohui

1.PartNumber管理,回库报表开发

2.工单明细下载为txt文件
3.定时通信,出库任务不结束
4.移动库位信息修改
5.工单出库逻辑修改
6.流水线,客户端 接口提交
1 个父辈 ad334e30
正在显示 45 个修改的文件 包含 1680 行增加203 行删除
......@@ -183,6 +183,7 @@ public class MenuInit {
//档案管理:元器件
Menu pMenuWl = Menu.CreatePMenu("档案管理", 6, "materiel ", "BOM",null);
addDefaultFunctionMenu(41, pMenuWl,"元器件","componentParts", "parts/component/index","server",DEFAULT_SHOW_MENU);
addDefaultFunctionMenu(42, pMenuWl,"PartNumber管理","partNumberManager", "partNumberManager/index","partNumberManager");
//条形码:条码管理,条码设置
Menu pMenuBarcode = Menu.CreatePMenu("条形码", 7, "barcodes ", "barcodeMenu",null);
......@@ -204,6 +205,7 @@ public class MenuInit {
addDefaultFunctionMenu(72, pMenuReport,"库存", "inventory", "neolight/inventory/index", "inventory");
addDefaultFunctionMenu(73, pMenuReport,"温湿度", "humiture", "humiture/humitureReport/index", "humiture");
addDefaultFunctionMenu(73, pMenuReport,"温湿度", "spHumiture", "humiture/spHumitureReport/index", "humiture");
addDefaultFunctionMenu(74, pMenuReport,"回库", "returnStorage", "neolight/returnExport/index", "returnExport");
//可观测性:物料追踪
Menu guanceMenu = Menu.CreatePMenu("可观测性", 10, "observability", "scanKey",null);
......
......@@ -29,7 +29,6 @@ import com.neotel.smfcore.common.base.IExcelDownLoad;
import com.neotel.smfcore.common.config.file.CustomCellWriteHeightConfig;
import com.neotel.smfcore.common.config.file.CustomCellWriteWeightConfig;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.language.util.MessageUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFSheet;
......@@ -48,6 +47,7 @@ import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
......@@ -396,6 +396,35 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
.doWrite(datas);
}
public static void downloadTxtByConfig(String fileName, List<List<String>> headers, List<List<Object>> datas, HttpServletResponse response) throws IOException {
// 设置响应内容类型为文本
response.setContentType("text/plain; charset=UTF-8");
// 设置文件名,并进行URL编码以防止中文乱码
fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
// 设置响应头,提示浏览器以下载文件的形式处理响应内容
response.setHeader("Content-Disposition", "attachment; filename*=utf-8''" + fileName + ".txt");
// 假设这是您要导出的数据
List<String> dataToExport = new ArrayList<>();
//for (List<String> header : headers) {
dataToExport.add(org.apache.logging.log4j.util.Strings.join( headers, ','));
//}
for (List<Object> data : datas) {
dataToExport.add(org.apache.logging.log4j.util.Strings.join( data, ','));
}
// 使用BufferedWriter将数据写入响应输出流
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), "UTF-8"))) {
for (String line : dataToExport) {
writer.write(line);
writer.newLine(); // 写入换行符
}
writer.flush(); // 刷新缓冲区,确保所有数据都被写入
} catch (IOException e) {
e.printStackTrace();
log.error("导出数据到TXT文件时发生错误", e);
}
}
/**
* 设置Header
*
......
......@@ -432,6 +432,8 @@ public class BaseDeviceHandler implements IDeviceHandler {
if (pos != null) {
Storage storage = dataCache.getStorageById(pos.getStorageId());
log.info("出库已在库位中的物料[" + barcodeSave.getBarcode() + "]");
taskService.checkout(storage,pos,true,true,"","",barcodeSave.getBarcode()+"已存在库位:"+pos.getPosName());
throw new ValidateException("smfcore.error.barcode.inStorage", "[ " + barcodeSave.getBarcode() + "]已在" + storage.getName() + "[" + pos.getPosName() + "]中", new String[]{barcodeSave.getBarcode(), storage.getName(), pos.getPosName()});
}
......@@ -468,9 +470,9 @@ public class BaseDeviceHandler implements IDeviceHandler {
} else if (BOX_STATUS.IN_FAILED == status) {//入库失败
//暂不处理
} else if (BOX_STATUS.OUT_FINISHED == status) {//出仓完成
finishedOutPos(statusBean.getCid(),posName,barcode,executeTime);
//finishedOutPos(statusBean.getCid(),posName,barcode,executeTime);
} else if (BOX_STATUS.OUT_END == status) {//出库完成(放到仓门口
endOutTask(statusBean.getCid(),posName,barcode);
//endOutTask(statusBean.getCid(),posName,barcode);
}
// else if (BOX_STATUS.REWARM_TAKING_END == status) {
// //回温取料完成, 将库位清空
......
......@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import com.google.common.base.Strings;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.device.bean.BoxStatusBean;
import com.neotel.smfcore.core.device.bean.StatusBean;
......@@ -15,6 +16,9 @@ import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.DevicesStatusUtil;
import com.neotel.smfcore.custom.Jkem21481.bean.StorageExport;
import com.neotel.smfcore.custom.Jkem21481.util.StorageExportUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
......@@ -75,10 +79,10 @@ public class XLRBoxHandler extends BaseDeviceHandler {
if (BOX_STATUS.IN_FINISHED == status) {//入仓完成
finishedPutIn(statusBean.getCid(),posName,barcode,executeTime);
} else if (BOX_STATUS.OUT_FINISHED == status) {//出仓完成
finishedOutPos(statusBean.getCid(),posName,barcode,executeTime,OP_STATUS.OUT_BOX);
//finishedOutPos(statusBean.getCid(),posName,barcode,executeTime,OP_STATUS.OUT_BOX);
} else if (BOX_STATUS.OUT_END == status) {//出库完成(放到仓门口
log.info(statusBean.getCid() +"将物料从库位["+posName+"]出库到门口/料串完成");
reelOnShelf(statusBean.getCid(),posName);
//reelOnShelf(statusBean.getCid(),posName);
}
}
} catch (ValidateException e) {
......@@ -152,6 +156,7 @@ public class XLRBoxHandler extends BaseDeviceHandler {
isNg=true;
}
statusBean.addPosInfo(task.getBarcode(), posName, plateW, plateH, isSingleOut,isNg,NgMsg,0,task.getSourceName());
statusBean.addData("export",task.getExport());
log.info("出库" + storage.getName() + "[" + posName + "]物料[" + task.getBarcode() + "]" + isSingleOut + "["+NgMsg+"]发送到客户端" + cid);
}
}
......@@ -181,7 +186,7 @@ public class XLRBoxHandler extends BaseDeviceHandler {
List<DataLog> dataLogList = new ArrayList<>();
for (DataLog dataLog : allTasks) {
for (StoragePos pos : usedPosList.values()) {
if (pos.getPosName().equals(dataLog.getPosName())){
if (pos.getPosName().equals(dataLog.getPosName())) {
dataLog.setPriority(pos.getPriority());
}
}
......@@ -198,8 +203,8 @@ public class XLRBoxHandler extends BaseDeviceHandler {
if (task.isPutInTask()) {
log.error("cid[" + cid + "]已有入库任务,不可再分配出库任务");
return null;
} else if (task.needReSendToClient() && task.isCheckOutTask()) {//超过30秒仍未完成的出库再次发送到客户端
log.error("cid[" + cid + "]的出库任务[" + task.getPosName() + "]"+task.getBarcode()+"超过60秒仍未完成,重新发送到客户端!");
} else if (task.needReSendToClient() && task.isCheckOutTask()) {//超过180秒仍未完成的出库再次发送到客户端
log.error("cid[" + cid + "]的出库任务[" + task.getPosName() + "]" + task.getBarcode() + "超过180秒仍未完成,重新发送到客户端!");
task.setUpdateDate(new Date());
return task;
}
......@@ -217,9 +222,7 @@ public class XLRBoxHandler extends BaseDeviceHandler {
//指定紧急单盘出库的优先出库,否则按批量出库处理
DataLog singleOutTask = null;
DataLog outTask = null;
for (DataLog task : dataLogList) {//优先分配单盘任务和没有工单的任务
if (cid.equals(task.getCid()) && task.isCheckOutTask() && task.isWait()) {
String posName = task.getPosName();
......@@ -229,10 +232,6 @@ public class XLRBoxHandler extends BaseDeviceHandler {
if (singleOutTask == null || task.getCreateDate().before(singleOutTask.getCreateDate())) {
singleOutTask = task;
}
} else {
if (outTask == null || task.getPriority() < outTask.getPriority()) {
outTask = task;
}
}
}
}
......@@ -242,7 +241,66 @@ public class XLRBoxHandler extends BaseDeviceHandler {
return singleOutTask;
}
return outTask;
//出料口为空的
DataLog outTask = null;
for (DataLog task : dataLogList) {
if (cid.equals(task.getCid()) && task.isCheckOutTask() && task.isWait()) {
String posName = task.getPosName();
if (!Strings.isNullOrEmpty(posName)) {//有库位号
String export = task.getExport();
if (StringUtils.isEmpty(export)) {
//单盘优先出库
if (outTask == null || task.getCreateDate().before(outTask.getCreateDate())) {
outTask = task;
}
}
}
}
}
if (outTask != null) {
log.info("分配优先(单盘或无工单)出库任务" + outTask.getBarcode() + "[" + outTask.getPosName() + "]到 " + cid);
}
//分配出料口不为空的
DataLog orderTask = null;
//先提取出料口不为空的
List<DataLog> notEmptyExportList = new ArrayList<>();
for (DataLog dataLog : dataLogList) {
if (dataLog.isCheckOutTask() && dataLog.isWait()) {
String export = dataLog.getExport();
if (StringUtils.isNotEmpty(export)) {
notEmptyExportList.add(dataLog);
}
}
}
//按出料口进行分组
Map<String, List<DataLog>> map = notEmptyExportList.stream().collect(Collectors.groupingBy(DataLog::getExport));
for (String key : map.keySet()) {
List<DataLog> groupByList = map.get(key);
Collections.sort(groupByList, new Comparator<DataLog>() {
@Override
public int compare(DataLog o1, DataLog o2) {
String feederInfo1 = o1.getAppendData("feederInfo");
String feederInfo2 = o2.getAppendData("feederInfo");
return feederInfo1.compareTo(feederInfo2);
}
});
if (groupByList != null && !groupByList.isEmpty()) {
DataLog dataLog = groupByList.get(0);
if (cid.equals(dataLog.getCid())) {
//判断出料口信息是否相同
String feederInfo = dataLog.getAppendData("feederInfo");
StorageExport export = StorageExportUtil.getExport(key);
if (feederInfo.startsWith(export.getFeeder())) {
log.info("分配出库任务,站位号为:" + dataLog.getAppendData("feederInfo") + ",出料口为:" + key + ",barcode为:" + dataLog.getBarcode());
orderTask = dataLog;
break;
}
}
}
}
return orderTask;
}
@Override
......
package com.neotel.smfcore.core.device.handler.impl;
import com.neotel.smfcore.core.storage.enums.DeviceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class XLROneBoxHandler extends XLRBoxHandler{
@Override
public DeviceType getDeviceType() {
return DeviceType.SMD_ONE;
}
}
......@@ -893,10 +893,10 @@ public class DeviceController {
//如果是以S结尾的,则判断不带S的有没有料
posName = pos.getPosName();
String wPosName="";
if (posName.endsWith("S") || posName.endsWith("s")){
log.info(posName+"以S结尾,需要判断外层有没有物料");
if (posName.endsWith("B") || posName.endsWith("b")){
log.info(posName+"以B结尾,需要判断外层有没有物料");
wPosName = posName.substring(0,posName.length()-1);
wPosName= wPosName +"F";
StoragePos storagePos = storagePosManager.getByPosName(wPosName);
if (storagePos != null){
if (storagePos.getBarcode() != null){
......@@ -1039,12 +1039,12 @@ public class DeviceController {
if ( lock == null) {
if (needMovePosName.endsWith("S") || needMovePosName.endsWith("s")) {
if (needMovePosName.endsWith("F") || needMovePosName.endsWith("f")) {
log.info("需要移动的库位为:" + needMovePosName + "是内侧库位,不需要锁定库位");
} else {
String sPosname = needMovePosName + "S";
needMovePosName = needMovePosName.substring(0,needMovePosName.length()-1);
String sPosname = needMovePosName + "B";
StoragePos sPos = storagePosManager.getByPosName(sPosname);
if (sPos != null) {
String cid = dataCache.getStorageById(sPos.getStorageId()).getCid();
......
......@@ -806,6 +806,7 @@ public class DataCache {
if (bean == null || bean.timeOut() || !bean.isAvailable()) {
continue;
}
log.info("获取到可用料仓为:"+storage.getName());
availableStorageIds.add(storage.getId());
}
return availableStorageIds;
......
package com.neotel.smfcore.core.order;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.neotel.smfcore.common.bean.ResultBean;
......@@ -28,6 +29,9 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.DevicesStatusUtil;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.Jkem21481.manager.IPartNumberManager;
import com.neotel.smfcore.custom.Jkem21481.manager.IReturnStorageManager;
import com.neotel.smfcore.custom.Jkem21481.util.StorageExportUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -60,6 +64,12 @@ public class LiteOrderCache {
@Autowired
private SmfApi smfApi;
@Autowired
private IPartNumberManager partNumberManager;
@Autowired
private IReturnStorageManager returnStorageManager;
/**
* 正在执行的liteOrderMap, key 为orderNo,value 为order
*/
......@@ -272,7 +282,7 @@ public class LiteOrderCache {
order.setTotalTaskReelCount(order.getTotalTaskReelCount()-1);
log.info("工单[" + orderNo + "]的任务" + task.getPartNumber() + "[" + task.getBarcode() + "]已取消,任务数-1=" + order.getFinishedReelCount() + "/" + order.getTaskReelCount());
checkoutAgain(task,order);
//checkoutAgain(task,order);
}
else if (task.isFinished() || task.isEnd()) {
order.setFinishedReelCount(order.getFinishedReelCount() + 1);
......@@ -288,6 +298,7 @@ public class LiteOrderCache {
liteOrderItem.setTotalOutNum(liteOrderItem.getTotalOutNum()+task.getNum());
liteOrderItem.setTotalOutReelCount(liteOrderItem.getTotalOutReelCount()+1);
liteOrderItem.setBarcodeStr(task.getBarcode(),task.getNum());
liteOrderItem.setOutBarcodeList(task.getBarcode(),task.getPartNumber(),task.getExport());
liteOrderItem = liteOrderItemManager.save(liteOrderItem);
// Barcode barcode = barcodeManager.findByBarcode(task.getBarcode());
// if (barcode != null) {
......@@ -344,6 +355,12 @@ public class LiteOrderCache {
}
}
}
//入库的时候,增加回库信息
else {
if (task.isFinished()){
returnStorageManager.saveOrUpdateReturnStorage(task.getBarcode());
}
}
}
private LiteOrder checkoutAgain(DataLog task,LiteOrder order) {
......@@ -736,6 +753,7 @@ public class LiteOrderCache {
if(task.isCheckOutTask()){
String posId = task.getPosId();
if (!Strings.isNullOrEmpty(posId)) {
log.info("需要排除的库位为:"+task.getPosName()+",barcode为:"+task.getBarcode()+",任务状态为:"+task.getStatus()+",上一次修改时间为:"+task.getUpdateDate());
operatingPosIds.add(task.getPosId());
}
}
......@@ -882,4 +900,191 @@ public class LiteOrderCache {
}
public String checkOutJkemLiteOrder(String orderNo) {
//判断工单是否已经关闭
LiteOrder cacheOrder = liteOrderMap.get(orderNo);
if (cacheOrder == null) {
cacheOrder = liteOrderManager.findByOrderNo(orderNo);
}
if (cacheOrder == null) {
return "smfcore.order.out.notFound";
}
if (!cacheOrder.isTaskFinished() && !cacheOrder.isNew()) {
log.info("工单[" + orderNo + "]正在执行");
return "smfcore.order.out.executing";
}
if (cacheOrder.isClosed()) {
log.info("工单[" + orderNo + "]已关闭,无法出库");
return "smfcore.order.hasClose";
}
//判断有没有空闲的出料口
List<String> emptyExportList = StorageExportUtil.getEmptyExportList();
if (emptyExportList == null || emptyExportList.isEmpty()) {
return "smfcore.order.noEmptyExport";
}
log.info(orderNo + "获取到的出料口信息为:" + JSON.toJSONString(emptyExportList));
log.info("开始执行工单[" + orderNo + "]");
cacheOrder.setTaskReelCount(0);
cacheOrder.setTaskFinishedTime(-1);
cacheOrder.setFinishedReelCount(0);
cacheOrder.setStatus(LITEORDER_STATUS.TAILS);
//任务数量
int taskReelCount = 0;
//出库方式
CHECKOUT_TYPE checkoutType = dataCache.getCheckOutType();
//可用料仓
List<String> availableStorageIds = dataCache.getAvailableStorageIds();
//开始循环处理数据
for (LiteOrderItem orderItem : cacheOrder.getOrderItems()) {
orderItem.setOutNum(0);
orderItem.setOutReelCount(0);
liteOrderItemManager.save(orderItem);
int appendNum = 0;
int pitch = partNumberManager.getPitchByJkemPartNumber(orderItem.getPn());
if (pitch == 2 || pitch == 4){
appendNum = 300;
}
log.info("工单号为:"+orderNo+",料号为:"+orderItem.getPn()+",找到的pitch为:"+pitch+".需要增加的数量为:"+appendNum);
//判断剩余要出的数量和盘数
int remainNum = orderItem.getNeedNum() - orderItem.getTotalOutNum() + appendNum;
int remainReelCount = orderItem.getNeedReelCount() - orderItem.getTotalOutReelCount();
//统计任务数量
int countTask = 0;
if (remainNum > 0 || remainReelCount > 0) {
//已经分配的数量和料盘
int assignNum = 0;
int assignReelCount = 0;
while (assignNum < remainNum || assignReelCount < remainReelCount) {
Collection<String> excludePosIds = excludeOutPosIds();
String partNumber = orderItem.getPn();
String feederInfo = orderItem.getFeederInfo();
StoragePos pos = storagePosManager.findPartNumberInStorages(availableStorageIds, partNumber, excludePosIds, checkoutType);
if (pos == null) {
log.info(orderNo + "未找到可以出库的物料,料号为:" + partNumber + ",站位号为:" + feederInfo);
break;
}
countTask++;
//根据站位号,分配到不同出料口
String putInExport = StorageExportUtil.getPutInExport(emptyExportList, countTask > 1, feederInfo);
log.info("feeder为:" + feederInfo + ",工单号为:" + orderNo + ",获取到的出料口为:" + putInExport);
//开始生成出库任务
Barcode barcode = pos.getBarcode();
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList == null || subCodeList.isEmpty()) {
assignNum = assignNum + pos.getBarcode().getAmount();
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
log.info("工单[" + orderNo
+ "],任务数[" + taskReelCount
+ "]出库位置仓位【" + pos.getPosName()
+ "】RI=[" + pos.getBarcode().getBarcode()
+ "] PN=[" + partNumber
+ "] num:" + pos.getBarcode().getAmount()
+"]出料口为:"+putInExport
+"]站位为:"+feederInfo
);
DataLog task = newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
task.setType(OP.CHECKOUT);
//task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
//task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine());
task.setExport(putInExport);
task.updateAppendData("feederInfo",orderItem.getFeederInfo());
// task = dataLogDao.save(task);
taskService.addTaskToExecute(task);
StorageExportUtil.updateExportData(putInExport,barcode.getBarcode(),feederInfo,orderNo,task.getStatus());
} else { //开始处理料箱数据
boolean hasTask = false;
List<DataLog> allTasks = taskService.getAllTasks();
for (Barcode subCode : subCodeList) {
if (assignNum >= remainNum && assignReelCount >= remainReelCount) {
continue;
}
if (!subCode.getPartNumber().equals(orderItem.getPn())) {
continue;
}
for (DataLog dataLog : allTasks) {
if (!dataLog.isCancel() && !dataLog.isFinished()) {
if (subCode.getBarcode().equals(dataLog.getBarcode())) {
continue;
}
}
}
assignNum = assignNum + subCode.getAmount();
assignReelCount = assignReelCount + 1;
taskReelCount = taskReelCount + 1;
log.info("工单[" + orderNo
+ "],任务数[" + taskReelCount
+ "]出库位置仓位【" + pos.getPosName()+"barcode为:"+barcode.getBarcode()
+ "】RI=[" + subCode.getBarcode()
+ "] PN=[" + subCode.getPartNumber()
+ "] num:" + subCode.getAmount()
+"]出料口为:"+putInExport
+"]站位为:"+feederInfo
);
hasTask = true;
Storage storage = dataCache.getStorageById(pos.getStorageId());
DataLog task = new DataLog(storage, subCode, pos);
task.setPosId(barcode.getId());
task.setPosName(barcode.getPosName());
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setSubSourceId(orderItem.getId());
task.setSubSourceInfo(orderItem.getFeederInfo());
task.setType(OP.CHECKOUT);
//task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAITING_FOR_RETRIEVAL.name());
task.updateAppendData("feederInfo",orderItem.getFeederInfo());
task.setExport(putInExport);
//task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine());
taskService.updateQueueTask(task);
StorageExportUtil.updateExportData(putInExport,subCode.getBarcode(),feederInfo,orderNo,task.getStatus());
}
if (hasTask) {
taskReelCount = taskReelCount + 1;
DataLog task = newTask(pos);
task.setSourceId(cacheOrder.getId());
task.setSourceName(cacheOrder.getOrderNo());
task.setType(OP.CHECKOUT);
//task.setLightColor(nextColor.getRgb());
task.setStatus(OP_STATUS.WAIT.name());
task.setExport(putInExport);
task.updateAppendData("feederInfo",orderItem.getFeederInfo());
task.updateAppendData("isBox",true);
//task.setSingleOut(singleOut);
task.setLine(cacheOrder.getLine());
taskService.updateQueueTask(task);
StorageExportUtil.updateExportData(putInExport,barcode.getBarcode(),feederInfo,orderNo,task.getStatus());
}
}
}
}
}
cacheOrder.setTaskReelCount(taskReelCount);
cacheOrder.setTotalTaskReelCount(cacheOrder.getTotalTaskReelCount() + taskReelCount);
log.info("工单[" + orderNo + "]任务分配结束,任务数[" + taskReelCount + "]");
smfApi.onOrderStatusChange(cacheOrder);
//有需要出库的
if (taskReelCount <= 0) {
finishedOrderTasks(cacheOrder);
}
liteOrderManager.save(cacheOrder);
liteOrderMap.put(cacheOrder.getOrderNo(), cacheOrder);
if (taskReelCount <= 0) {
//return "工单无可执行的任务";
return "smfcore.order.out.noTask";
}
return "";
}
}
......@@ -22,6 +22,7 @@ import java.io.File;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* Created by sunke on 2021/7/12.
......@@ -66,6 +67,8 @@ public class DefaultOrderFileListener implements IOrderFileListener {
if (liteOrderItems.size() <= 0) {
continue;
}
//按站位进行排序
liteOrderItems = liteOrderItems.stream().sorted(Comparator.comparing(LiteOrderItem::getFeederInfo)).collect(Collectors.toList());
LiteOrder liteOrder = new LiteOrder(so, liteOrderItems);
liteOrder.setSource(fileName);
......
......@@ -171,7 +171,7 @@ public class OrderController {
if (liteOrder == null) {
throw new ValidateException("smfcore.valueNotFind", "未找到{0}[{1}]", new String[]{"orderNo", orderNo});
}
String result = liteOrderCache.checkOutLiteOrder(liteOrder.getOrderNo(), false);
String result = liteOrderCache.checkOutJkemLiteOrder(liteOrder.getOrderNo());
if (ObjectUtil.isEmpty(result)) {
return ResultBean.newOkResult(result);
} else {
......@@ -383,6 +383,7 @@ public class OrderController {
header.add(Lists.newArrayList(MessageUtils.getText("smfcore.order.needNum",locale,"需求数量")));
header.add(Lists.newArrayList(MessageUtils.getText("smfcore.order.outNum",locale,"已出数量")));
header.add(Lists.newArrayList(MessageUtils.getText("smfcore.order.out.barcode",locale,"出库物料详情")));
header.add(Lists.newArrayList(MessageUtils.getText("smfcore.order.outLet",locale,"出料口")));
//附加字段
OrderSetting orderSetting=dataCache.getOrderSetting();
......@@ -412,6 +413,18 @@ public class OrderController {
data.add(orderItem.getNeedNum());
data.add(orderItem.getOutNum());
data.add(orderItem.getBarcodeStr());
String export = "";
List<Barcode> outBarcodeList = orderItem.getOutBarcodeList();
for (Barcode barcode : outBarcodeList) {
String outLet = barcode.getAppendData("export");
if (StringUtils.isNotEmpty(outLet)){
export = outLet;
break;
}
}
data.add(export);
//附加字段
if(orderSetting.getAppendData()!=null&&orderSetting.getAppendData().size()>0){
for (String key :
......@@ -432,7 +445,7 @@ public class OrderController {
data.add(exception);
dataList.add(data);
}
FileUtil.downloadExcelByConfig(liteOrder.getOrderNo(), header,dataList,response);
FileUtil.downloadTxtByConfig(liteOrder.getOrderNo(), header,dataList,response);
}
}
......
package com.neotel.smfcore.core.order.rest.bean.dto;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Transient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Getter
......@@ -77,4 +80,9 @@ public class OrderItemDto {
@ApiModelProperty("自定义的附加字段,key=字段名,value=值")
public Map<String,String> appendData = new HashMap<>();
/**
* 出库清单列表
*/
private List<Barcode> outBarcodeList = new ArrayList<>();
}
......@@ -2,9 +2,12 @@ package com.neotel.smfcore.core.order.service.manager;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import org.springframework.data.mongodb.core.query.Query;
import java.util.List;
public interface ILiteOrderItemManager extends IBaseManager<LiteOrderItem> {
List<LiteOrderItem> findOrderItems(String orderId);
LiteOrderItem findOne(Query createDate);
}
......@@ -27,6 +27,11 @@ public class LiteOrderItemManagerImpl implements ILiteOrderItemManager {
}
@Override
public LiteOrderItem findOne(Query query) {
return liteOrderItemDao.findOne(query);
}
@Override
public LiteOrderItem get(String id) {
return liteOrderItemDao.findOneById(id);
}
......
......@@ -2,14 +2,14 @@ package com.neotel.smfcore.core.order.service.po;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import lombok.Data;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
@Data
@Document
......@@ -99,6 +99,11 @@ public class LiteOrderItem extends BasePo implements Serializable ,Comparable<Li
private String barcodeStr = "";
/**
* 出库清单列表
*/
private List<Barcode> outBarcodeList = new ArrayList<>();
/**
* 自定义的附加字段,key=字段名,value=值
*/
public Map<String,String> appendData = new HashMap<>();
......@@ -143,4 +148,14 @@ public class LiteOrderItem extends BasePo implements Serializable ,Comparable<Li
this.barcodeStr = barcodeStr + " (" + amount+")";
}
}
public void setOutBarcodeList(String barcode,String partNumber, String export) {
this.outBarcodeList.removeIf(t -> t.getBarcode().equals(barcode));
Barcode newBarcode = new Barcode();
newBarcode.setBarcode(barcode);
newBarcode.setPartNumber(partNumber);
newBarcode.updateAppendData("export", export);
newBarcode.setCreateDate(new Date());
this.outBarcodeList.add(newBarcode);
}
}
......@@ -89,6 +89,11 @@ public class StoragePosFindCriteria {
@ApiModelProperty("呆滞天数")
private Integer sluggishDay;
@ApiModelProperty("小于库存数量")
@QueryCondition(type = QueryCondition.Type.LT,propName = "barcode.amount")
private Integer lteSpecifiedAmount;
public int getComponentType(){
int componentType = getType();
if (componentType != -1) {
......
......@@ -8,7 +8,9 @@ import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Getter
@Setter
......@@ -150,4 +152,10 @@ public class TaskDto implements Serializable {
}
@ApiModelProperty("位置信息,如料架编号,托盘编号,移栽编号,皮带线编号,机器人编号等")
private String locInfo = "";
@ApiModelProperty("出料口")
private String export = "";
@ApiModelProperty("附加信息")
private Map<String,Object> appendData = new HashMap<>();
}
......@@ -152,6 +152,11 @@ public class DataLog extends BasePo implements Serializable ,Comparable<DataLog>
private String status;
/**
* 上一次任务状态
*/
private String lastStatus;
/**
* 指定批次Id
*/
private String batchId;
......@@ -376,11 +381,11 @@ public class DataLog extends BasePo implements Serializable ,Comparable<DataLog>
}
/**
* 正在执行的出库任务,如果60秒还未完成,再次发送到客户端
* 正在执行的出库任务,如果180秒还未完成,再次发送到客户端
*/
public boolean needReSendToClient(){
if(isCheckOutTask() && isExecuting()){
return System.currentTimeMillis() - super.getUpdateDate().getTime() >= 60 * 1000;
return System.currentTimeMillis() - super.getUpdateDate().getTime() >= 60 * 1000 * 3;
}
return false;
}
......
......@@ -29,6 +29,7 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.bean.MSDAppendInfo;
import com.neotel.smfcore.core.system.service.dao.IDataLogDao;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.custom.Jkem21481.util.StorageExportUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -165,6 +166,13 @@ public class TaskService {
liteOrderCache.onTaskStatusChange(task);
smfApi.onTaskStatusChange(task);
selfAuditUtil.onTaskStatusChange(task);
//修改出料口信息
if (task.isCheckOutTask()) {
String export = task.getExport();
if (StringUtils.isNotEmpty(export)) {
StorageExportUtil.updateExportData(export, task.getBarcode(), task.getAppendData("feederInfo"), task.getSourceName(), task.getStatus());
}
}
}
/**
......@@ -564,7 +572,7 @@ public class TaskService {
}
statusBean.addPosInfo(task.getBarcode(), posName, plateW, plateH, isSingleOut,isNg,NgMsg,0,task.getSourceName());
statusBean.addData("export",task.getExport());
log.info("出库" + storage.getName() + "[" + posName + "]物料[" + task.getBarcode() + "]" + isSingleOut + "["+NgMsg+"]发送到客户端" + cid);
log.info("出库" + storage.getName() + "[" + posName + "]物料[" + task.getBarcode() + "]" + isSingleOut + "["+NgMsg+"]发送到客户端" + cid+",出料口为:"+task.getExport());
}
}
String posId = statusBean.getData().get("posId");
......
......@@ -13,11 +13,14 @@ import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.api.SmfApi;
import com.neotel.smfcore.core.api.bean.CodeValidateParam;
import com.neotel.smfcore.core.barcode.bean.CodeBean;
import com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.barcode.utils.CodeResolve;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.language.util.MessageUtils;
import com.neotel.smfcore.core.message.util.DeviceMessageUtil;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.storage.service.manager.IStoragePosManager;
import com.neotel.smfcore.core.storage.service.po.Storage;
......@@ -26,7 +29,9 @@ import com.neotel.smfcore.core.system.service.dao.IAlarmInfoDao;
import com.neotel.smfcore.core.system.service.po.AlarmInfo;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.Jkem21481.bean.MJPartNumber;
import com.neotel.smfcore.custom.Jkem21481.bean.StorageExport;
import com.neotel.smfcore.custom.Jkem21481.manager.IPartNumberManager;
import com.neotel.smfcore.custom.Jkem21481.util.StorageExportUtil;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.ApiOperation;
......@@ -60,11 +65,22 @@ public class JkemController {
@Autowired
private IStoragePosManager storagePosManager;
@Autowired
private IBarcodeManager barcodeManager;
@Autowired
private ILiteOrderManager liteOrderManager;
@Autowired
private IPartNumberManager partNumberManager;
/**
* 流水线提示消息
*/
private static String lineMsg = "";
private static final List<String> msdCidList = Arrays.asList("XLR4A","XLR4B","XLR5A","XLR5B","XLR6A","XLR6B");
/**
* 流水线入库查找空的料格
*/
......@@ -129,6 +145,34 @@ public class JkemController {
throw new ValidateException("smfcore.error.barcode.invalid", "未找到有效的条码");
}
//判断是不是要入到指定的料仓
List<String> newCidList = new ArrayList<>();
List<Storage> newStorageList = new ArrayList<>();
MJPartNumber mjPartNumber = partNumberManager.findByMakerPartNumber(barcode.getPartNumber());
if (mjPartNumber != null){
log.info(barcode.getBarcode()+"查询到的信息为:"+JSON.toJSONString(mjPartNumber));
int msd = mjPartNumber.getMsd();
if (msd == 1){
for (String cid : cidList) {
if (!msdCidList.contains(cid)){
newCidList.add(cid);
Storage storage = dataCache.getStorage(cid);
newStorageList.add(storage);
}
}
if (newCidList == null || newCidList.isEmpty()){
throw new ValidateException("smf.barcode.msd.validate","该物料需要MSD管控不能在本料仓入库");
}
} else {
newCidList.addAll(cidList);
newStorageList.addAll(storageList);
}
} else {
newCidList.addAll(cidList);
newStorageList.addAll(storageList);
}
for (DataLog dataLog : taskService.getQueueTasks()) {
// if(!dataLog.isPackageReel()){
//已经在任务当中,返回对应的信息
......@@ -181,7 +225,7 @@ public class JkemController {
if (loopCount >= 10) {
log.info(barcode.getBarcode() + "已循环查找10次 直接跳出循环");
}
pos = taskService.findEmptyPosForPutIn(storageList, barcode, rfid, lastPosId);
pos = taskService.findEmptyPosForPutIn(newStorageList, barcode, rfid, lastPosId);
if (pos == null) {
break;
}
......@@ -204,7 +248,7 @@ public class JkemController {
reelLocInfo.setCid(dataCache.getStorageById(pos.getStorageId()).getCid());
reelLocInfo.setLockPosName(pos.getPosName());
reelLocInfo.setLockPosId(pos.getId());
ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, cidList);
ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, newCidList);
// needRemoveReelLockPosIdList.add(pos.getId());
pos = null;
}
......@@ -240,7 +284,7 @@ public class JkemController {
reelLocInfo.setCid(theStorage.getCid());
reelLocInfo.setLockPosName(pos.getPosName());
reelLocInfo.setLockPosId(pos.getId());
reelLocInfo = ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, cidList);
reelLocInfo = ReelLockPosUtil.addReelLockPosInfo(reelLocInfo, newCidList);
if (reelLocInfo == null) {
errorMsg = "[" + barcode.getBarcode() + "]库位[" + reelLocInfo.getLockPosName() + "]已被锁定,暂停入库";
lineMsg = errorMsg;
......@@ -300,97 +344,37 @@ public class JkemController {
}
@ApiOperation("获取出料口信息")
@RequestMapping("/getExport")
@AnonymousAccess
public ResultBean getExport(String export) {
StorageExport storageExport = StorageExportUtil.getExport(export);
if (StringUtils.isNotBlank(storageExport.getHSerial())) {
int remainTaskCount = 0;
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) {
if (dataLog.isCheckOutTask() && storageExport.getHSerial().equals(dataLog.getSourceName())) {
if (!dataLog.isFinished() && !dataLog.isCancel()) {
remainTaskCount++;
}
}
}
storageExport.setRemainTaskCount(remainTaskCount);
StorageExportUtil.updateExport(export, storageExport);
}
log.info(export + "获取出料口信息为:" + JSON.toJSONString(storageExport));
return ResultBean.newOkResult(storageExport);
}
//禁用或者启用出料口
@ApiOperation("禁用出料口")
@AnonymousAccess
@RequestMapping("/service/store/innerBox/disableExport")
public ResultBean disableExport(String name, int type) {
StorageExport storageExport = StorageExportUtil.getExport(name);
if (type == 1) {
storageExport.setDisable(true);
} else {
storageExport.setDisable(false);
}
StorageExportUtil.updateExport(name, storageExport);
return ResultBean.newOkResult("");
}
@ApiOperation("料箱离开工位")
@RequestMapping("/boxOutStation")
@AnonymousAccess
public synchronized ResultBean boxOutStation(String export, String material, String orderNo) {
log.info("收到料箱离开工位,出料口为:" + export + ",工单号为:" + orderNo);
StorageExport storageExport = StorageExportUtil.getExport(export);
String hSerial = storageExport.getHSerial();
StorageExport outStationExport = new StorageExport();
outStationExport.setDisable(storageExport.isDisable());
outStationExport.setLine(storageExport.getLine());
outStationExport.setHSerial(hSerial);
outStationExport.setMaterial(material);
StorageExportUtil.clearExport(export);
StorageExportUtil.updateExport(export + StorageExportUtil.OUT_STATION, outStationExport);
log.info(export + StorageExportUtil.OUT_STATION + "料箱离开工位,信息为:" + JSON.toJSONString(outStationExport));
return ResultBean.newOkResult(outStationExport);
}
@ApiOperation("根据条码获取目的地信息")
@RequestMapping("/getLine")
@RequestMapping("/service/store/innerBox/getLine")
@AnonymousAccess
public Map<String, Object> getLineByBarcode(@RequestBody Map<String, String> paramMap) {
Map<String, Object> resultMap = new HashMap<>();
String barcode = paramMap.get("barcode");
log.info(barcode + "获取目的地信息");
CodeBean codeBean = codeResolve.resolveSingleCode(barcode);
if (codeBean.getBarcode() != null) {
String barcodeStr = paramMap.get("barcode");
log.info(barcodeStr + "获取目的地信息");
CodeBean codeBean = codeResolve.resolveSingleCode(barcodeStr);
Barcode barcode = codeBean.getBarcode();
if (barcode != null) {
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) {
if (dataLog.isCheckOutTask() && dataLog.getBarcode().equals(codeBean.getBarcode().getBarcode()) && !dataLog.isFinished() && !dataLog.isCancel()) {
if (dataLog.isCheckOutTask() && dataLog.getBarcode().startsWith(codeBean.getBarcode().getBarcode()) && !dataLog.isFinished() && !dataLog.isCancel()) {
resultMap.put("cid", dataLog.getCid());
resultMap.put("export", "");
//如果sourceName和subSourceId都不为空时,则返回目标位置
String sourceName = dataLog.getSourceName();
String sourceId = dataLog.getSourceId();
if (StringUtils.isNotBlank(sourceId) && StringUtils.isNotBlank(sourceName)) {
//String export = StorageExportUtil.getExportByOrderNo(sourceName,false);
//判断是否禁用了
String exportStr = dataLog.getExport();
if (StringUtils.isNotBlank(exportStr)) {
StorageExport export = StorageExportUtil.getExport(exportStr);
if (export.isDisable()) {
log.info(exportStr + "出料口被禁用");
resultMap.put("export", "");
} else {
log.info(dataLog.getBarcode() + "获取出料口信息为:" + exportStr);
List<Barcode> subCodeList = barcode.getSubCodeList();
if (subCodeList == null || subCodeList.isEmpty()) {
resultMap.put("export", exportStr);
} else {
resultMap.put("export", "ng");
}
}
} else {
//String export = StorageExportUtil.getExportByOrderNo("", false, false);
log.info(dataLog.getBarcode() + "手动出库获取出料口信息为:" + "");
resultMap.put("export", "");
}
......@@ -405,8 +389,89 @@ public class JkemController {
}
@ApiOperation("IA 出库更新任务状态")
@RequestMapping("/service/store/innerBox/updateLocInfo")
@AnonymousAccess
public ResultBean updateLocInfo(HttpServletRequest request) {
String code = request.getParameter("barcode");
String status = request.getParameter("status");
String loc = request.getParameter("loc");
String cid = request.getParameter("cid");
String hSerial = request.getParameter("hSerial"); //工单序号
String outlet = request.getParameter("outlet"); //出口位置
String boxSide = request.getParameter("boxSide"); //料箱隔口
String x = request.getParameter("x");
String y = request.getParameter("y");
log.info("IA 出库更新任务状态--barcode:{},status:{},loc:{},hSerial:{},outlet:{},boxSide:{},cid:{},outlet:{},x:{},y:{}", code, status, loc, hSerial, outlet, boxSide, cid, outlet, x, y);
CodeBean codeBean = codeResolve.resolveSingleCode(code);
Barcode barcode = codeBean.getBarcode();
if (barcode == null) {
return ResultBean.newErrorResult(-1,"smfcore.error.barcode.invalid","{0}不是有效的条码",new String[]{code});
}
code = barcode.getBarcode();
log.info("解析到的料盘信息为:["+code+"]");
//获取到当前执行的任务
DataLog opTask = null;
Collection<DataLog> allTasks = taskService.getAllTasks();
//log.info("所有任务为:"+ JSON.toJSONString(allTasks));
for (DataLog task : allTasks) {
if (task.isCheckOutTask() && task.getBarcode().startsWith(code)) {
if (!task.isCancel() && !task.isFinished()) {
opTask = task;
break;
}
}
}
if (opTask == null) {
return ResultBean.newErrorResult(303, "smfcore.task.notExist", "任务不存在");
}
if (opTask.isFinished()) {
return ResultBean.newErrorResult(304, "smfcore.task.hasEnd", "任务已完成");
}
status = status.toUpperCase();
opTask.setStatus(status);
if (status.equals(OP_STATUS.EXECUTING.name())){
taskService.updateQueueTask(opTask);
} else {
outFromPos(opTask);
taskService.moveTaskToFinished(opTask);
taskService.updateFinishedTask(opTask);
}
return ResultBean.newOkResult("");
}
/**
* 物料取出
*/
private void outFromPos(DataLog opTask) {
//从队列里面移除操作
taskService.removeQueueTask(opTask);
StoragePos storagePos = storagePosManager.get(opTask.getPosId());
Barcode barcode = storagePos.getBarcode();
if (barcode == null) {
log.warn("任务:" + opTask.getId() + " 仓位:" + opTask.getPosId() + " 的 Barcode 为null, 之前可能处理过,结束任务后直接返回");
return;
}
barcode = barcodeManager.get(barcode.getId());
if (barcode != null) {
//二维码状态
barcode.setUsed(true);
barcode.setUsedDate(new Date());
//仓位状态
barcode.setCheckOutDate(new Date(), "");
barcode.setPosName("");
barcodeManager.save(barcode);
}
storagePos.setBarcode(null);
storagePos.setUsed(false);
storagePosManager.save(storagePos);
log.info("出库完成,清空仓位: " + storagePos.getId() + "[" + storagePos.getPosName() + "]");
//更新缓存中的库存信息
dataCache.updateInventory(storagePos, barcode);
}
public Barcode resolveBarcodeFromApi(CodeValidateParam params) {
Barcode barcodeSave = smfApi.canPutInBeforeResolve(params);
if (barcodeSave == null) {
......
package com.neotel.smfcore.custom.Jkem21481.bean;
import com.neotel.smfcore.common.base.BasePo;
import lombok.Data;
@Data
public class MJPartNumber extends BasePo {
private String makerPartNumber; // 供应商部品号
private String jkemPartNumber;//JKEM 部品号;
private int pitch;
private int msd; //MSD (1 = need control; 0 = no need control)
}
package com.neotel.smfcore.custom.Jkem21481.bean;
import com.neotel.smfcore.common.base.BasePo;
import lombok.Data;
@Data
public class ReturnStorage extends BasePo {
private String orderNo;
private String pn;
private String feederInfo;
private int needNum;
private int outNum;
private String returnBarcode;
private String lastExport;
private String orderItemId;
}
......@@ -4,6 +4,8 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@NoArgsConstructor
......@@ -13,24 +15,18 @@ public class StorageExport {
*/
private String hSerial = "";
/**
* 目的地(线体)
*/
private String line = "";
/**
* 当前料仓剩余未出的需求单数量
/*
*feeder号
*/
private int remainTaskCount = 0;
private String feeder = "-1";
/**
* 是否禁用
* 出料口名称
*/
private boolean disable = false;
private String exportName;
/**
* 料串信息
* 要出库的物料信息
*/
private String material = "";
private List<StorageExportOutDetail> detailList;
}
package com.neotel.smfcore.custom.Jkem21481.bean;
import lombok.Data;
@Data
public class StorageExportOutDetail {
private String barcode;
private String feederInfo;
private String status;
private String lastStatus;
}
package com.neotel.smfcore.custom.Jkem21481.bean.dto;
import com.neotel.smfcore.custom.Jkem21481.bean.StorageExport;
import lombok.Data;
import java.util.List;
@Data
public class StorageExportDto {
private String exportName;
private String feederInfo;
private String hSerial; //工单号
private List<StorageExport> outDetailList;
}
package com.neotel.smfcore.custom.Jkem21481.bean.query;
import com.neotel.smfcore.common.annotation.QueryCondition;
import com.neotel.smfcore.common.bean.BetweenData;
import lombok.Data;
import java.util.Date;
@Data
public class MjPartNumberQueryCondition {
@QueryCondition(blurry = "makerPartNumber,jkemPartNumber")
private String bluuy;
@QueryCondition(type = QueryCondition.Type.BETWEEN)
private BetweenData<Date> createDate;
}
package com.neotel.smfcore.custom.Jkem21481.bean.query;
import com.neotel.smfcore.common.annotation.QueryCondition;
import com.neotel.smfcore.common.bean.BetweenData;
import lombok.Data;
import java.util.Date;
@Data
public class ReturnStorageQueryCondition {
@QueryCondition(blurry = "orderNo,pn,returnBarcode,feederInfo")
private String blurry;
@QueryCondition(type = QueryCondition.Type.BETWEEN)
private BetweenData<Date> createDate;
}
package com.neotel.smfcore.custom.Jkem21481.controller;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.excel.ExcelReader;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.common.utils.FileUtil;
import com.neotel.smfcore.common.utils.QueryHelp;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.custom.Jkem21481.bean.MJPartNumber;
import com.neotel.smfcore.custom.Jkem21481.bean.query.MjPartNumberQueryCondition;
import com.neotel.smfcore.custom.Jkem21481.manager.IPartNumberManager;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import com.neotel.smfcore.security.bean.FileProperties;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/jkemPartNumber")
@RestController
public class PartNumberController {
@Autowired
private IPartNumberManager partNumberManager;
@Autowired
private final FileProperties properties;
@ApiOperation("文件上传")
@RequestMapping("/uploadFile")
@AnonymousAccess
public ResultBean uploadFile(@RequestParam("file") MultipartFile uploadFile) {
//判断是否为xlsx文件
String xlsx = "xlsx";
String fileType = FileUtil.getExtensionName(uploadFile.getOriginalFilename());
if (fileType != null && !xlsx.contains(fileType)) {
throw new ValidateException("smfcore.feleFormatError", "文件格式错误!, 仅支持{0}格式", new String[]{xlsx});
}
File folder = new File(properties.getPath(), "pos");
File file = FileUtil.upload(uploadFile, folder.getAbsolutePath());
List<MJPartNumber> partNumberList = handleMakerPnAndJkemPn(file.getAbsolutePath());
if (partNumberList == null || partNumberList.isEmpty()){
//throw new ValidateException("smfcore.fileError", "文件解析失败");
return ResultBean.newErrorResult(-1,"smfcore.fileError","文件解析失败");
}
//根据供应商的pn,查询是否存在,修改
for (MJPartNumber mjPartNumber : partNumberList) {
MJPartNumber daMjPartNumber = partNumberManager.findByMakerPartNumber(mjPartNumber.getMakerPartNumber());
if (daMjPartNumber == null){
partNumberManager.save(mjPartNumber);
} else {
if (!mjPartNumber.getMakerPartNumber().equals(daMjPartNumber.getMakerPartNumber())
|| !mjPartNumber.getJkemPartNumber().equals(daMjPartNumber.getJkemPartNumber())
|| mjPartNumber.getMsd() != daMjPartNumber.getMsd()
|| mjPartNumber.getPitch() != daMjPartNumber.getPitch()
) {
daMjPartNumber.setJkemPartNumber(mjPartNumber.getJkemPartNumber());
daMjPartNumber.setMakerPartNumber(mjPartNumber.getMakerPartNumber());
daMjPartNumber.setMsd(mjPartNumber.getMsd());
daMjPartNumber.setPitch(mjPartNumber.getPitch());
}
}
}
return ResultBean.newOkResult("");
}
@ApiOperation("获取列表")
@RequestMapping("/list")
//@AnonymousAccess
public PageData<MJPartNumber> list(MjPartNumberQueryCondition queryCondition, Pageable pageable){
return partNumberManager.findByPage(QueryHelp.getQuery(queryCondition),pageable);
}
@ApiOperation("获取所有给客户端使用")
@RequestMapping("/getALlMakerPnAndJkemPn")
@AnonymousAccess
public List<MJPartNumber> getALlMakerPnAndJkemPn(){
return partNumberManager.findAll();
}
@ApiOperation("批量删除")
@RequestMapping("/batchDelete")
@AnonymousAccess
public ResultBean batchDelete(@RequestBody Map<String,List<String>> paramMap){
List<String> idList = paramMap.get("ids");
if (idList == null || idList.isEmpty()){
return ResultBean.newErrorResult(-1,"smfcore.valueCanotNull","{0}不能为空",new String[]{"ids"});
}
partNumberManager.batchDelete(idList);
return ResultBean.newOkResult("");
}
@ApiOperation("修改")
@RequestMapping("/update")
@AnonymousAccess
public ResultBean update(@RequestBody MJPartNumber mjPartNumber){
String jkemPartNumber = mjPartNumber.getJkemPartNumber();
String makerPartNumber = mjPartNumber.getMakerPartNumber();
int pitch = mjPartNumber.getPitch();
int msd = mjPartNumber.getMsd();
String id = mjPartNumber.getId();
log.info("修改PartNumber维护信息,jkemPartNumber:"+jkemPartNumber+",makerPartNumber:"+makerPartNumber+",pitch:"+pitch+",msd:"+msd+",id:"+id);
partNumberManager.save(mjPartNumber);
return ResultBean.newOkResult("");
}
@ApiOperation("新增")
@RequestMapping("/save")
@AnonymousAccess
public ResultBean save(@RequestBody MJPartNumber mjPartNumber){
String jkemPartNumber = mjPartNumber.getJkemPartNumber();
String makerPartNumber = mjPartNumber.getMakerPartNumber();
int pitch = mjPartNumber.getPitch();
int msd = mjPartNumber.getMsd();
String id = mjPartNumber.getId();
log.info("新增PartNumber维护信息,jkemPartNumber:"+jkemPartNumber+",makerPartNumber:"+makerPartNumber+",pitch:"+pitch+",msd:"+msd+",id为:"+id);
if (StringUtils.isEmpty(jkemPartNumber)){
return ResultBean.newErrorResult(-1,"smfcore.valueCanotNull","{0}不能为空",new String[]{"JKEM Part Number"});
}
if (StringUtils.isEmpty(makerPartNumber)){
return ResultBean.newErrorResult(-1,"smfcore.valueCanotNull","{0}不能为空",new String[]{"Maker Part Number"});
}
partNumberManager.save(mjPartNumber);
return ResultBean.newOkResult("");
}
private List<MJPartNumber> handleMakerPnAndJkemPn(String absolutePath) {
List<MJPartNumber> partNumberList = new ArrayList<>();
List<Map<Integer, String>> dataMapList = ExcelReader.noModelRead(absolutePath);
if (dataMapList != null && dataMapList.size() > 2) {
//获取对应的标题,value为坐标
Map<String, Integer> headerMap = new HashMap<>();
Map<Integer, String> dataHeader = dataMapList.get(0);
for (Integer key : dataHeader.keySet()) {
if (key == null)
continue;
String header = dataHeader.get(key);
if (StringUtils.isEmpty(header))
continue;
headerMap.put(header, key);
}
//获取对应的坐标
int makerPartNumberIndex = -1;
int jkemPartNumberIndex = -1;
int pitchIndex = -1;
int msdIndex = -1;
for (String header : headerMap.keySet()) {
if (header.contains("Maker Part Number")) {
makerPartNumberIndex = headerMap.get(header);
} else if (header.contains("JKEM Part Number")) {
jkemPartNumberIndex = headerMap.get(header);
} else if (header.contains("Pitch")) {
pitchIndex = headerMap.get(header);
} else if (header.contains("MSD")) {
msdIndex = headerMap.get(header);
}
}
for (int i = 1; i < dataMapList.size(); i++) {
Map<Integer, String> dataMap = dataMapList.get(i);
MJPartNumber mjPartNumber = new MJPartNumber();
mjPartNumber.setJkemPartNumber(dataMap.get(jkemPartNumberIndex));
mjPartNumber.setMakerPartNumber(dataMap.get(makerPartNumberIndex));
//-1代表解析失败
mjPartNumber.setPitch(-1);
String pitchStr = dataMap.get(pitchIndex);
if (StringUtils.isNotEmpty(pitchStr)) {
try {
Integer pitch = Integer.valueOf(pitchStr);
mjPartNumber.setPitch(pitch);
} catch (Exception e) {
log.error("解析pitch 失败:", e);
}
}
mjPartNumber.setMsd(-1);
String msdStr = dataMap.get(msdIndex);
if (StringUtils.isNotEmpty(msdStr)) {
try {
Integer msd = Integer.valueOf(msdStr);
mjPartNumber.setMsd(msd);
} catch (Exception e) {
log.error("解析msd 失败:", e);
}
}
partNumberList.add(mjPartNumber);
}
}
return partNumberList;
}
}
package com.neotel.smfcore.custom.Jkem21481.controller;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.utils.QueryHelp;
import com.neotel.smfcore.custom.Jkem21481.bean.ReturnStorage;
import com.neotel.smfcore.custom.Jkem21481.bean.query.ReturnStorageQueryCondition;
import com.neotel.smfcore.custom.Jkem21481.manager.IReturnStorageManager;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/returnStorage")
public class ReturnStorageController {
@Autowired
private IReturnStorageManager returnStorageManager;
@ApiOperation("回库列表")
@RequestMapping("/list")
@AnonymousAccess
public PageData<ReturnStorage> list(ReturnStorageQueryCondition queryCondition, Pageable pageable) {
Query query = QueryHelp.getQuery(queryCondition);
return returnStorageManager.findByPage(query, pageable);
}
}
package com.neotel.smfcore.custom.Jkem21481.controller;
import com.neotel.smfcore.common.bean.ResultBean;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.device.enums.OP_STATUS;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.Jkem21481.bean.StorageExport;
import com.neotel.smfcore.custom.Jkem21481.bean.dto.StorageExportDto;
import com.neotel.smfcore.custom.Jkem21481.util.StorageExportUtil;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequestMapping("/storageExport")
public class StorageExportController {
@Autowired
private DataCache dataCache;
@Autowired
private TaskService taskService;
@ApiOperation("获取出料口详情")
@RequestMapping("/getDetailByExport")
@AnonymousAccess
public ResultBean getDetailByExport(String export) {
StorageExportDto dto = getStorageExportDto(export);
return ResultBean.newOkResult(dto);
}
@ApiOperation("清空出料口")
@RequestMapping("/clearExport")
@AnonymousAccess
public ResultBean clearExport(String export, String feeder) {
log.info("收到清空出料口信息:" + export + ",feeder为:" + feeder);
List<DataLog> needCancelTask = new ArrayList<>();
List<DataLog> allTasks = taskService.getAllTasks();
for (DataLog dataLog : allTasks) {
if (dataLog.isCancel() || dataLog.isFinished()){
continue;
}
String feederInfo = dataLog.getAppendData("feederInfo");
String taskExport = dataLog.getExport();
if (StringUtils.isNotEmpty(taskExport) && StringUtils.isNotEmpty(feederInfo)) {
if (taskExport.startsWith(export) && feederInfo.startsWith(feeder)) {
log.info("清空出料口:" + export + ",feeder为:" + feeder + ",任务需要取消,barcode为:" + dataLog.getBarcode() + ",状态为:" + dataLog.getStatus());
needCancelTask.add(dataLog);
}
}
}
String orderNo = "";
if (needCancelTask != null && !needCancelTask.isEmpty()) {
for (DataLog dataLog : needCancelTask) {
if (StringUtils.isEmpty(orderNo)) {
orderNo = dataLog.getSourceName();
}
dataLog.setStatus(OP_STATUS.CANCEL.name());
taskService.moveTaskToFinished(dataLog);
taskService.updateFinishedTask(dataLog);
//StorageExportUtil.updateExportData(dataLog.getExport(), dataLog.getBarcode(), dataLog.getAppendData("feederInfo"), dataLog.getSourceName(), OP_STATUS.CANCEL.name());
}
}
//判断是否要出下一个工单
String needFeeder = "";
if ("1".equals(feeder)) {
needFeeder = "5";
} else if ("2".equals(feeder)) {
needFeeder = "6";
} else if ("3".equals(feeder)) {
needFeeder = "7";
} else if ("4".equals(feeder)) {
needFeeder = "8";
} else if ("5".equals(feeder)) {
needFeeder = "-1";
} else if ("6".equals(feeder)) {
needFeeder = "-1";
} else if ("7".equals(feeder)) {
needFeeder = "-1";
} else if ("8".equals(feeder)) {
needFeeder = "-1";
}
//更新信息
List<StorageExport> exportList = StorageExportUtil.getSimpleExport(export);
for (StorageExport storageExport : exportList) {
if ("-1".equals(needFeeder)) {
StorageExportUtil.clearExport(storageExport.getExportName());
} else {
StorageExportUtil.updateExport(storageExport.getExportName(), needFeeder);
}
}
return ResultBean.newOkResult(getStorageExportDto(export));
}
private StorageExportDto getStorageExportDto(String export) {
StorageExportDto dto = new StorageExportDto();
dto.setExportName(export);
List<StorageExport> outDetailList = new ArrayList<>();
Map<String, StorageExport> exportMap = StorageExportUtil.exportMap;
for (String key : exportMap.keySet()) {
if (key.contains(export)) {
StorageExport storageExport = exportMap.get(key);
String feeder = storageExport.getFeeder();
if (StringUtils.isEmpty(dto.getFeederInfo())||"-1".equals(dto.getFeederInfo())) {
dto.setFeederInfo(feeder);
}
dto.setHSerial(storageExport.getHSerial());
outDetailList.add(storageExport);
}
}
outDetailList = outDetailList.stream().sorted(Comparator.comparing(StorageExport::getExportName)).collect(Collectors.toList());
dto.setOutDetailList(outDetailList);
return dto;
}
}
package com.neotel.smfcore.custom.Jkem21481.dao;
import com.neotel.smfcore.common.base.IBaseDao;
public interface IPartNumberDao extends IBaseDao {
}
package com.neotel.smfcore.custom.Jkem21481.dao;
import com.neotel.smfcore.common.base.IBaseDao;
public interface IReturnStorageDao extends IBaseDao {
}
package com.neotel.smfcore.custom.Jkem21481.dao.impl;
import com.neotel.smfcore.common.base.AbstractBaseDao;
import com.neotel.smfcore.custom.Jkem21481.bean.MJPartNumber;
import com.neotel.smfcore.custom.Jkem21481.dao.IPartNumberDao;
import org.springframework.stereotype.Service;
@Service
public class PartNumberDaoImpl extends AbstractBaseDao implements IPartNumberDao {
@Override
public Class getEntityClass() {
return MJPartNumber.class;
}
}
package com.neotel.smfcore.custom.Jkem21481.dao.impl;
import com.neotel.smfcore.common.base.AbstractBaseDao;
import com.neotel.smfcore.custom.Jkem21481.bean.ReturnStorage;
import com.neotel.smfcore.custom.Jkem21481.dao.IReturnStorageDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class ReturnStorageDaoImpl extends AbstractBaseDao implements IReturnStorageDao {
@Override
public Class getEntityClass() {
return ReturnStorage.class;
}
}
package com.neotel.smfcore.custom.Jkem21481.manager;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.custom.Jkem21481.bean.MJPartNumber;
import java.util.List;
public interface IPartNumberManager extends IBaseManager<MJPartNumber> {
MJPartNumber findByMakerPartNumber(String makerPartNumber);
List<MJPartNumber> findAll();
int getPitchByJkemPartNumber(String pn);
void batchDelete(List<String> idList);
}
package com.neotel.smfcore.custom.Jkem21481.manager;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.custom.Jkem21481.bean.ReturnStorage;
public interface IReturnStorageManager extends IBaseManager<ReturnStorage> {
void saveOrUpdateReturnStorage(String barcode);
}
package com.neotel.smfcore.custom.Jkem21481.manager.impl;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.custom.Jkem21481.bean.MJPartNumber;
import com.neotel.smfcore.custom.Jkem21481.dao.IPartNumberDao;
import com.neotel.smfcore.custom.Jkem21481.manager.IPartNumberManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class PartNumberManagerImpl implements IPartNumberManager {
@Autowired
private IPartNumberDao partNumberDao;
@Override
public MJPartNumber get(String id) {
return partNumberDao.findOneById(id);
}
@Override
public MJPartNumber save(MJPartNumber object) throws ValidateException {
return partNumberDao.save(object);
}
@Override
public void delete(MJPartNumber object) throws ValidateException {
partNumberDao.removeOne(object);
}
@Override
public PageData<MJPartNumber> findByPage(Query query, Pageable pageable) {
int count = partNumberDao.countByQuery(query);
List list = partNumberDao.findByQuery(query, pageable);
return new PageData<MJPartNumber>(list,count);
}
@Override
public List<MJPartNumber> findByQuery(Query query) {
return partNumberDao.findByQuery(query);
}
@Override
public MJPartNumber findByMakerPartNumber(String makerPartNumber) {
return partNumberDao.findOne(new Query(Criteria.where("makerPartNumber").is(makerPartNumber)));
}
@Override
public List<MJPartNumber> findAll() {
return partNumberDao.findAll();
}
@Override
public int getPitchByJkemPartNumber(String pn) {
MJPartNumber mjPartNumber = partNumberDao.findOne(new Query(Criteria.where("jkemPartNumber").is(pn)));
if (mjPartNumber == null){
return 0;
} else {
int pitch = mjPartNumber.getPitch();
if (pitch > 0){
return pitch;
}
}
return 0;
}
@Override
public void batchDelete(List<String> idList) {
for (String id : idList) {
partNumberDao.removeOneById(id);
}
}
}
package com.neotel.smfcore.custom.Jkem21481.manager.impl;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.barcode.service.po.Barcode;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderItemManager;
import com.neotel.smfcore.core.order.service.manager.ILiteOrderManager;
import com.neotel.smfcore.core.order.service.po.LiteOrder;
import com.neotel.smfcore.core.order.service.po.LiteOrderItem;
import com.neotel.smfcore.custom.Jkem21481.bean.ReturnStorage;
import com.neotel.smfcore.custom.Jkem21481.dao.IReturnStorageDao;
import com.neotel.smfcore.custom.Jkem21481.manager.IReturnStorageManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class ReturnStorageManagerImpl implements IReturnStorageManager {
@Autowired
private IReturnStorageDao returnStorageDao;
@Autowired
private ILiteOrderItemManager liteOrderItemManager;
@Autowired
private ILiteOrderManager liteOrderManager;
@Override
public ReturnStorage get(String id) {
return returnStorageDao.findOneById(id);
}
@Override
public ReturnStorage save(ReturnStorage object) throws ValidateException {
return returnStorageDao.save(object);
}
@Override
public void delete(ReturnStorage object) throws ValidateException {
returnStorageDao.removeOne(object);
}
@Override
public PageData<ReturnStorage> findByPage(Query query, Pageable pageable) {
int count = returnStorageDao.countByQuery(query);
List list = returnStorageDao.findByQuery(query, pageable);
return new PageData<>(list,count);
}
@Override
public List<ReturnStorage> findByQuery(Query query) {
return returnStorageDao.findByQuery(query);
}
@Override
public void saveOrUpdateReturnStorage(String barcode) {
LiteOrderItem item = liteOrderItemManager.findOne(new Query(Criteria.where("outBarcodeList.barcode").is(barcode)).with(Sort.by(Sort.Direction.DESC,"createDate")));
if (item != null) {
List<Barcode> outBarcodeList = item.getOutBarcodeList();
if (outBarcodeList != null && !outBarcodeList.isEmpty()){
for (Barcode subCode : outBarcodeList) {
if (barcode.equals(subCode.getBarcode())){
Date createDate = subCode.getCreateDate();
//超过48小时,就不统计
if (System.currentTimeMillis()-createDate.getTime() < 1000 * 60 * 60 * 48){
ReturnStorage returnStorage = new ReturnStorage();
returnStorage.setReturnBarcode(barcode);
returnStorage.setFeederInfo(item.getFeederInfo());
returnStorage.setLastExport(subCode.getAppendData("export"));
returnStorage.setNeedNum(item.getNeedNum());
returnStorage.setOutNum(item.getOutNum());
returnStorage.setPn(item.getPn());
LiteOrder liteOrder = liteOrderManager.get(item.getOrderId());
if (liteOrder != null) {
returnStorage.setOrderNo(liteOrder.getOrderNo());
}
returnStorage.setOrderItemId(item.getId());
returnStorageDao.save(returnStorage);
}
}
}
}
}
}
}
package com.neotel.smfcore.custom.Jkem21481.menu;
import com.neotel.smfcore.common.init.MenuInit;
import com.neotel.smfcore.core.api.SmfApi;
import com.neotel.smfcore.security.service.po.Menu;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class JkemMenu {
@Autowired
MenuInit menuInit;
@Autowired
SmfApi smfApi;
String menuLabel = "21481";
@PostConstruct
public void init() {
Menu menu = Menu.CreatePMenu("出料口", 10, "export", "um", null);
//Report菜单
MenuInit.addMenu(menuLabel, menu, 1, "UM1", "UM1", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 2, "UM2", "UM2", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 3, "UM3", "UM3", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 4, "UM4", "UM4", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 5, "UM5", "UM5", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 6, "UM6", "UM6", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 7, "UM7", "UM7", "neolight/um/index", "um");
MenuInit.addMenu(menuLabel, menu, 8, "UM8", "UM8", "neolight/um/index", "um");
String apiName = smfApi.getApiName();
if (Strings.isNotBlank(apiName) && apiName.equals(menuLabel)) {
menuInit.showMenu(apiName);
}
}
}
package com.neotel.smfcore.custom.Jkem21481.util;
import com.alibaba.fastjson.JSON;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.system.util.TaskService;
import com.neotel.smfcore.custom.Jkem21481.bean.StorageExport;
import com.neotel.smfcore.custom.Jkem21481.bean.StorageExportOutDetail;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
......@@ -26,135 +27,366 @@ public class StorageExportUtil {
dataCache = cache;
}
public static final String OUT_STATION = "_outStation";
private static TaskService taskService;
//出料口名称
private final static List<String> exportStrArr = Arrays.asList("UM_4", "UM_5", "UM_3", "UM_6", "UM_2", "UM_7", "UM_1", "UM_8");
@Autowired
void setTaskService(TaskService service) {
taskService = service;
}
//料仓前缀
public static final String EXPORT_PREFIX = "Storage_Export";
//出口信息缓存
public static Map<String, StorageExport> exportMap = new ConcurrentHashMap<>();
//初始化出料口信息
@PostConstruct
void initExport() {
for (String exportStr : exportStrArr) {
StorageExport exportStation = dataCache.getCache(EXPORT_PREFIX + "_" + exportStr);
if (exportStation == null) {
exportStation = new StorageExport();
private void initExport() {
for (String export : leftExportList) {
StorageExport storageExport = dataCache.getCache(EXPORT_PREFIX + "_" + export);
if (storageExport == null) {
storageExport = new StorageExport();
storageExport.setExportName(export);
}
exportMap.put(exportStr, exportStation);
String exportOutStationKey = exportStr + OUT_STATION;
StorageExport exportOutStation = dataCache.getCache(EXPORT_PREFIX + "_" + exportOutStationKey);
if (exportOutStation != null) {
exportMap.put(exportOutStationKey, exportStation);
exportMap.put(export, storageExport);
}
for (String export : rightExportList) {
StorageExport storageExport = dataCache.getCache(EXPORT_PREFIX + "_" + export);
if (storageExport == null) {
storageExport = new StorageExport();
storageExport.setExportName(export);
}
exportMap.put(export, storageExport);
}
}
//根据工单号,获取目的地信息
public static synchronized String getExportByOrderNo(String orderNo,boolean hasSameOrder,boolean maizheng) {
String exportStr = "";
//判断是否有相同工单
for (Map.Entry<String, StorageExport> entry : exportMap.entrySet()) {
StorageExport export = entry.getValue();
if (orderNo.equals(export.getHSerial())) {
if (hasSameOrder) {
//log.info(orderNo + "出库时,上一次工单未拉走,暂不出库");
return "";
private final static List<String> leftExportList = Arrays.asList(
"UM1_1", "UM1_2", "UM1_3"
, "UM2_1", "UM2_2", "UM2_3"
, "UM3_1", "UM3_2", "UM3_3"
, "UM4_1", "UM4_2", "UM4_3");
private final static List<String> rightExportList = Arrays.asList(
"UM5_1", "UM5_2", "UM5_3"
, "UM6_1", "UM6_2", "UM6_3"
, "UM7_1", "UM7_2", "UM7_3"
, "UM8_1", "UM8_2", "UM8_3");
public static List<String> getEmptyExportList() {
boolean leftClear = true;
for (String exportStr : leftExportList) {
StorageExport export = exportMap.get(exportStr);
if (!"-1".equals(export.getFeeder())) {
leftClear = false;
}
exportStr = entry.getKey();
break;
}
if (leftClear) {
return leftExportList;
}
//判断是否为新工单
if (StringUtils.isBlank(exportStr)) {
for (String export : exportStrArr) {
StorageExport storageExport = exportMap.get(export);
if (export.contains(StorageExportUtil.OUT_STATION)) {
continue;
boolean rightClear = true;
for (String exportStr : rightExportList) {
StorageExport export = exportMap.get(exportStr);
if (!"-1".equals(export.getFeeder())) {
rightClear = false;
}
}
if (rightClear) {
return rightExportList;
}
return new ArrayList<>();
}
public static String getPutInExport(List<String> exportList, boolean secondReel, String feederInfo) {
//判断是左侧还是右侧
boolean left = true;
if (!exportList.contains("UM1_1")) {
left = false;
}
String export = "";
//截取倒数第二第三位,当判断放到哪个箱子10001L
String currentLocStr = feederInfo.substring(feederInfo.length() - 3, feederInfo.length() - 1);
int currentLoc = Integer.valueOf(currentLocStr);
if (storageExport.isDisable()) {
continue;
if (feederInfo.startsWith("1") || feederInfo.startsWith("5")) {
if (left) {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM1_3";
} else {
export = "UM1_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM1_3";
} else {
export = "UM1_2";
}
}
} else {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM5_3";
} else {
export = "UM5_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM5_3";
} else {
export = "UM5_2";
}
}
}
} else if (feederInfo.startsWith("2") || feederInfo.startsWith("6")) {
if (left) {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM2_3";
} else {
export = "UM2_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM2_3";
} else {
export = "UM2_2";
}
}
} else {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM6_3";
} else {
export = "UM6_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM6_3";
} else {
export = "UM6_2";
}
}
}
} else if (feederInfo.startsWith("3") || feederInfo.startsWith("7")) {
if (left) {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM3_3";
} else {
export = "UM3_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM3_3";
} else {
export = "UM3_2";
}
}
} else {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM7_3";
} else {
export = "UM7_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM7_3";
} else {
export = "UM7_2";
}
}
}
} else if (feederInfo.startsWith("4") || feederInfo.startsWith("8")) {
if (left) {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM4_3";
} else {
export = "UM4_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM4_3";
} else {
export = "UM4_2";
}
}
} else {
if (currentLoc >= 1 && currentLoc <= 15) {
if (secondReel) {
export = "UM8_3";
} else {
export = "UM8_1";
}
} else if (currentLoc >= 16 && currentLoc <= 30) {
if (secondReel) {
export = "UM8_3";
} else {
export = "UM8_2";
}
}
}
}
return export;
}
public static synchronized void updateExportData(String export, String barcode, String feederInfo, String orderNo,String status) {
log.info("修改出料口:"+export+"barcode为:"+barcode+",站位信息为:"+feederInfo+"工单号为:"+orderNo+",状态为:"+status);
if (StringUtils.isBlank(storageExport.getHSerial())) {
log.info(orderNo+"获取到出料口信息为:"+ JSON.toJSONString(storageExport));
exportStr = export;
StorageExport storageExport = exportMap.get(export);
List<StorageExportOutDetail> detailList = storageExport.getDetailList();
if (detailList == null) {
detailList = new ArrayList<>();
}
if (StringUtils.isNotEmpty(barcode)){
StorageExportOutDetail outDetail = null;
for (StorageExportOutDetail detail : detailList) {
if (detail.getBarcode().equals(barcode)){
outDetail = detail;
break;
}
}
if (outDetail == null){
outDetail = new StorageExportOutDetail();
}
return exportStr;
String lastStatus = outDetail.getStatus();
outDetail.setLastStatus(lastStatus);
outDetail.setStatus(status);
outDetail.setFeederInfo(feederInfo);
outDetail.setBarcode(barcode);
detailList.removeIf(t->t.getBarcode().equals(barcode));
detailList.add(outDetail);
}
storageExport.setHSerial(orderNo);
String feeder = storageExport.getFeeder();
//只放feeder为1/5的
if (export.equals("UM1_1")
|| export.equals("UM1_2")
|| export.equals("UM1_3")
|| export.equals("UM5_1")
|| export.equals("UM5_2")
|| export.equals("UM5_3")
) {
String feederStart = "1";
if (!feederInfo.startsWith("1")){
feederStart="5";
}
//清空出料口信息
public static void clearExport(String key) {
StorageExport oldExport = exportMap.get(key);
if (oldExport != null) {
log.info("清除出料口信息为:" + JSON.toJSONString(oldExport));
StorageExport newExport = new StorageExport();
newExport.setDisable(oldExport.isDisable());
exportMap.put(key, newExport);
dataCache.updateCache(EXPORT_PREFIX + "_" + key, newExport);
if ("-1".equals(feeder)){
storageExport.setFeeder(feederStart);
} else {
if ("1".equals(feederStart)){
storageExport.setFeeder(feederStart);
}
}
}
public static void updateExport(String outlet, StorageExport storageExport) {
boolean hasOutLet = false;
for (String exportStr : exportStrArr) {
if (outlet.startsWith(exportStr)) {
hasOutLet = true;
break;
//只放feeder为2/6的
else if (export.equals("UM2_1")
|| export.equals("UM2_2")
|| export.equals("UM2_3")
|| export.equals("UM6_1")
|| export.equals("UM6_2")
|| export.equals("UM6_3")
) {
String feederStart = "2";
if (!feederInfo.startsWith("2")){
feederStart="6";
}
if ("-1".equals(feeder)){
storageExport.setFeeder(feederStart);
} else {
if ("2".equals(feederStart)){
storageExport.setFeeder(feederStart);
}
if (hasOutLet) {
exportMap.put(outlet, storageExport);
dataCache.updateCache(EXPORT_PREFIX + "_" + outlet, storageExport);
}
}
//更新出料口信息
public static void updateExport(String key, String hSerial, String line, int remainTaskCount) {
boolean hasOutLet = false;
for (String export : exportStrArr) {
if (export.equals(key)) {
hasOutLet = true;
break;
//只放feeder为3/7的
else if (export.equals("UM3_1")
|| export.equals("UM3_2")
|| export.equals("UM3_3")
|| export.equals("UM7_1")
|| export.equals("UM7_2")
|| export.equals("UM7_3")
) {
String feederStart = "3";
if (!feederInfo.startsWith("3")) {
feederStart = "7";
}
if ("-1".equals(feeder)) {
storageExport.setFeeder(feederStart);
} else {
if ("3".equals(feederStart)) {
storageExport.setFeeder(feederStart);
}
}
}
//只放feeder为4/8的
else if (export.equals("UM4_1")
|| export.equals("UM4_2")
|| export.equals("UM4_3")
|| export.equals("UM8_1")
|| export.equals("UM8_2")
|| export.equals("UM8_3")
) {
String feederStart = "4";
if (!feederInfo.startsWith("4")) {
feederStart = "8";
}
if ("-1".equals(feeder)) {
storageExport.setFeeder(feederStart);
} else {
if ("4".equals(feederStart)) {
storageExport.setFeeder(feederStart);
}
}
if (hasOutLet) {
StorageExport storageExport = exportMap.get(key);
}
storageExport.setDetailList(detailList);
exportMap.put(export,storageExport);
dataCache.updateCache(EXPORT_PREFIX + "_" + export,storageExport);
}
StorageExport newExport = new StorageExport();
if (StringUtils.isNotBlank(hSerial)) {
newExport.setHSerial(hSerial);
public static List<StorageExport> getSimpleExport(String export) {
List<StorageExport> list = new ArrayList<>();
for (String key : exportMap.keySet()) {
if (key.startsWith(export)){
list.add(exportMap.get(key));
}
}
if (StringUtils.isNotBlank(line)) {
newExport.setLine(line);
return list;
}
newExport.setRemainTaskCount(remainTaskCount);
newExport.setDisable(storageExport.isDisable());
//storageExport.setRemainTaskCount(100);
exportMap.put(key, newExport);
dataCache.updateCache(EXPORT_PREFIX + "_" + key, newExport);
public static void updateExport(String export,String feeder){
StorageExport storageExport = exportMap.get(export);
storageExport.setFeeder(feeder);
exportMap.put(export,storageExport);
dataCache.updateCache(EXPORT_PREFIX + "_" + export,storageExport);
}
public static void clearExport(String export){
StorageExport storageExport = new StorageExport();
storageExport.setExportName(export);
exportMap.put(export,storageExport);
dataCache.updateCache(EXPORT_PREFIX + "_" + export,storageExport);
}
//获取出料口信息
public static StorageExport getExport(String key) {
StorageExport storageExport = exportMap.get(key);
if (storageExport == null) {
public static StorageExport getExport(String export){
StorageExport storageExport = exportMap.get(export);
if (storageExport == null){
storageExport = new StorageExport();
storageExport.setExportName(export);
}
return storageExport;
}
}
......@@ -2,7 +2,7 @@ server:
port: 8800
api:
name:
name: 21481
inCheckUrl:
outNotifyUrl:
inNotifyUrl:
......@@ -47,7 +47,7 @@ app:
type: ""
menu:
show:
show: partNumberManager,translation,returnStorage
hide:
smd:
......
......@@ -388,3 +388,8 @@ smfcore.msg.op.fail=\u64CD\u4F5C\u5931\u8D25
smfcore.equip.notExist=\u8BBE\u5907\u4E0D\u5B58\u5728
smfcore.order.finished=\u5DE5\u5355[{0}]\u7684\u4EFB\u52A1\u5DF2\u5168\u90E8\u5B8C\u6210
smfcore.spkanban=SP\u4EEA\u8868\u76D8
smfcore.order.noEmptyExport=\u6CA1\u6709\u7A7A\u95F2\u7684\u51FA\u6599\u53E3
smfcore.export=\u51FA\u6599\u53E3
smfcore.partNumberManager=PartNumber\u7BA1\u7406
smfcore.returnStorage=\u56DE\u5E93
smf.barcode.msd.validate=\u8BE5\u7269\u6599\u9700\u8981MSD\u7BA1\u63A7\u4E0D\u80FD\u5728\u672C\u6599\u4ED3\u5165\u5E93
\ No newline at end of file
......@@ -379,3 +379,8 @@ smfcore.msg.op.fail=failure of an operation
smfcore.equip.notExist=Device does not exist
smfcore.order.finished=workorder[{0}] has completed all of its tasks
smfcore.spkanban=SP Dash Board
smfcore.order.noEmptyExport=No available discharge outlet
smfcore.export=Outlet
smfcore.partNumberManager=PartNumber Management
smfcore.returnStorage=Return to Inventory
smf.barcode.msd.validate=This material requires MSD control and cannot be stored in this warehouse
\ No newline at end of file
......@@ -375,3 +375,8 @@ smfcore.msg.op.fail=\u64CD\u4F5C\u5931\u8D25
smfcore.equip.notExist=\u8BBE\u5907\u4E0D\u5B58\u5728
smfcore.order.finished=\u30EF\u30FC\u30AF\u30AA\u30FC\u30C0\u30FC[{0}]\u306E\u30BF\u30B9\u30AF\u306F\u3059\u3079\u3066\u5B8C\u4E86\u3057\u307E\u3057\u305F
smfcore.spkanban=\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9
smfcore.order.noEmptyExport=\u7A7A\u304D\u306E\u6392\u51FA\u53E3\u304C\u3042\u308A\u307E\u305B\u3093
smfcore.export=\u306F\u3044\u3058\u3085\u3064\u3053\u3046
smfcore.partNumberManager=PartNumber \u304B\u3093\u308A
smfcore.returnStorage=\u305D\u3046\u3053\u306B\u3082\u3069\u308B
smf.barcode.msd.validate=\u3053\u306E\u6750\u6599\u306FMSD\u7BA1\u7406\u304C\u5FC5\u8981\u3067\u3001\u672C\u5009\u5EAB\u306B\u5165\u5EAB\u3067\u304D\u307E\u305B\u3093\u3002
\ No newline at end of file
......@@ -375,3 +375,8 @@ smfcore.msg.op.fail=\u64CD\u4F5C\u5931\u8D25
smfcore.equip.notExist=\u8BBE\u5907\u4E0D\u5B58\u5728
smfcore.order.finished=\u5DE5\u5355[{0}]\u7684\u4EFB\u52A1\u5DF2\u5168\u90E8\u5B8C\u6210
smfcore.spkanban=SP\u4EEA\u8868\u76D8
smfcore.order.noEmptyExport=\u6CA1\u6709\u7A7A\u95F2\u7684\u51FA\u6599\u53E3
smfcore.export=\u51FA\u6599\u53E3
smfcore.partNumberManager=PartNumber\u7BA1\u7406
smfcore.returnStorage=\u56DE\u5E93
smf.barcode.msd.validate=\u8BE5\u7269\u6599\u9700\u8981MSD\u7BA1\u63A7\u4E0D\u80FD\u5728\u672C\u6599\u4ED3\u5165\u5E93
\ No newline at end of file
......@@ -375,3 +375,8 @@ smfcore.msg.op.fail=\u64CD\u4F5C\u5931\u6557
smfcore.equip.notExist=\u8A2D\u5099\u4E0D\u5B58\u5728
smfcore.order.finished=\u5DE5\u55AE[{0}]\u7684\u4EFB\u52D9\u5DF2\u5168\u90E8\u5B8C\u6210
smfcore.spkanban=SP\u5100\u9336\u76E4
smfcore.order.noEmptyExport=\u6C92\u6709\u7A7A\u9592\u7684\u51FA\u6599\u53E3
smfcore.export=\u51FA\u6599\u53E3
smfcore.partNumberManager=PartNumber\u7BA1\u7406
smfcore.returnStorage=\u56DE\u5EAB
smf.barcode.msd.validate=\u8A72\u7269\u6599\u9700\u9032\u884CMSD\u7BA1\u63A7\uFF0C\u4E0D\u53EF\u5728\u672C\u6599\u5009\u5165\u5EAB
\ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!