Commit a1a331a3 LN

工单监控功能

1 个父辈 2046e95c
......@@ -205,6 +205,11 @@
<artifactId>mina-core</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.samba.jcifs</groupId>
<artifactId>jcifs</artifactId>
<version>1.3.3</version>
</dependency>
</dependencies>
......
......@@ -3,6 +3,7 @@ package com.neotel.smfcore.common.init;
import com.neotel.smfcore.common.utils.PermissionInitUtil;
import com.neotel.smfcore.common.utils.Constants;
import com.neotel.smfcore.common.utils.UserCodeUtil;
import com.neotel.smfcore.core.order.util.OrderFileWatch;
import com.neotel.smfcore.core.system.service.manager.IDataLogManager;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.TaskService;
......@@ -49,6 +50,9 @@ public class DataInitManager {
@Autowired
PermissionInitUtil annotationUtil;
@Autowired
OrderFileWatch orderFileWatch;
@PostConstruct
public void DataInit() {
try {
......@@ -101,6 +105,8 @@ public class DataInitManager {
mainTimer.init();
orderFileWatch.init();
allPermissionSet= annotationUtil.initPermission();
} catch (Exception exception) {
log.error("初始化环境出错..." + exception.toString());
......
package com.neotel.smfcore.common.utils;
import com.google.common.collect.Lists;
import jcifs.Config;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.net.URI;
import java.util.List;
@Slf4j
public class SmbUtil {
/**
* 列出SMB服务器文件夹中的所有文件名称,如果目录不存在或者访问出错返回null
*/
public static List<String> smbFileNameList(String smbDir){
try {
SmbFile remoteFile = new SmbFile(smbDir);
if (remoteFile.exists() && remoteFile.isDirectory()) {
String[] fileNames = remoteFile.list();
return Lists.newArrayList(fileNames);
} else {
log.info("SMB目录["+smbDir+"]不存在");
}
} catch (Exception e) {
log.error("访问SMB目录["+smbDir+"]出错",e);
}
return null;
}
/**
* @Title smbGet
* @Param shareUrl 共享目录中的文件路径,如smb://132.20.2.33/CIMPublicTest/eg.txt
* @Param localDirectory 本地目录,如tempStore/smb
*/
public static boolean smbGet(String smbFile, String localDirectory){
InputStream in = null;
OutputStream out = null;
try {
Config.registerSmbURLHandler();
SmbFile remoteFile = new SmbFile(smbFile);
if (!remoteFile.exists()) {
log.info("共享文件不存在");
return false;
}
// 有文件的时候再初始化输入输出流
log.info("下载共享目录的文件 "+smbFile+" 到 "+ localDirectory);
String fileName = remoteFile.getName();
File localFile = new File(localDirectory + File.separator + fileName);
File fileParent = localFile.getParentFile();
if (null != fileParent && !fileParent.exists()) {
fileParent.mkdirs();
}
in = new BufferedInputStream(new SmbFileInputStream(remoteFile));
out = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] buffer = new byte[1024];
while (in.read(buffer) != -1) {
out.write(buffer);
buffer = new byte[1024];
}
out.flush(); //刷新缓冲区输出流
return true;
} catch (Exception e) {
log.error("获取 SMB 文件出错",e);
} finally {
close(in,out);
}
return false;
}
private static void close(InputStream in,OutputStream out){
try {
if(in != null){
out.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* @Title smbPut
* @Description 向共享目录上传文件
* @Param shareDirectory 共享目录
* @Param localFilePath 本地目录中的文件路径
* @date 2019-01-10 20:16
*/
public static boolean smbPut(String shareDirectory, String localFilePath) {
InputStream in = null;
OutputStream out = null;
String domain = "";
try {
if(!shareDirectory.toLowerCase().startsWith("smb")){
return false;
}
File localFile = new File(localFilePath);
Config.registerSmbURLHandler();
URI uri = new URI(shareDirectory);
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication(uri.getUserInfo());
String smbFileName = uri.getScheme() + "://" + uri.getHost() + uri.getPath() + localFile.getName();
SmbFile remoteFile = new SmbFile(smbFileName,auth);
log.info("put " + localFilePath + " to " +remoteFile.getPath());
in = new BufferedInputStream(new FileInputStream(localFile));
out = new BufferedOutputStream(remoteFile.getOutputStream());
byte[] buffer = new byte[1024];
while (in.read(buffer) != -1) {
out.write(buffer);
buffer = new byte[1024];
}
out.flush();
return true;
} catch (Exception e) {
log.error("上传 SMB 文件出错",e);
} finally {
close(in,out);
}
return false;
}
}
......@@ -21,6 +21,7 @@ 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.core.order.util.OrderFileWatch;
import com.neotel.smfcore.core.storage.service.po.Storage;
import com.neotel.smfcore.core.storage.service.po.StoragePos;
import com.neotel.smfcore.core.system.bean.OrderSetting;
......@@ -93,7 +94,7 @@ public class OrderController {
private final FileProperties properties;
@Autowired
private DataCache dataCache;
private OrderFileWatch orderFileWatch;
// @ApiOperation("导出用户数据")
// @GetMapping(value = "/download")
......@@ -115,7 +116,7 @@ public class OrderController {
}
File folder = new File(properties.getPath(), "pos");
File localFile = FileUtil.upload(orderFile, folder.getAbsolutePath());
Map<String, List<LiteOrderItem>> itemMap = handleOrderCsv(fileName,localFile.getAbsolutePath());
Map<String, List<LiteOrderItem>> itemMap = orderFileWatch.readCsvFile(fileName,localFile.getAbsolutePath());
if (itemMap == null || itemMap.size() <= 0) {
throw new ValidateException("smfcore.fileError", "文件解析失败");
......@@ -128,20 +129,8 @@ public class OrderController {
if (liteOrderItems.size() <= 0) {
continue;
}
int type = 2;
for (LiteOrderItem item :
liteOrderItems) {
if (!StringUtils.isEmpty(item.getPn()) && (StringUtils.isEmpty(item.getRi()))) {
type = 1;
break;
}
}
LiteOrder liteOrder = new LiteOrder(so, liteOrderItems);
liteOrder.setType(type);
liteOrder.setSource(localFile.getName());
liteOrder.setStatus(LITEORDER_STATUS.NEW);
LiteOrder dbOrder = liteOrderManager.findByOrderNo(liteOrder.getOrderNo());
if (dbOrder != null) {
......@@ -276,87 +265,7 @@ public class OrderController {
}
protected Map<String ,List<LiteOrderItem>> handleOrderCsv(String fileName,String fileURL) {
try {
fileName=fileName.replace(".csv","");
log.info("开始更解析上传的工单");
Map<String ,List<LiteOrderItem>> itemMap=new HashMap<>();
List<LiteOrderItem> items = Lists.newArrayList();
OrderSetting orderSetting = dataCache.getCache(Constants.CACHE_OrderSetting);
if (orderSetting == null) {
orderSetting = new OrderSetting();
}
CsvReader csvRead = CsvReader.newReader(fileURL,"PN", orderSetting.getPn());
int partNumberIndex = csvRead.getIndex("PN", orderSetting.getPn());
int qtyIndex = csvRead.getIndex("QTY", orderSetting.getQty());
int feederIndex = csvRead.getIndex("FEEDER", orderSetting.getFeeder());
int riIndex = csvRead.getIndex("RI",orderSetting.getRi());
int soIndex = csvRead.getIndex("SO", orderSetting.getSo());
int row = 1;
int newRowCount = 0;
int updateRowCount = 0;
while (csvRead.readRecord()) {
row++;
String[] lineValues = csvRead.getValues();
String partNumber = lineValues[partNumberIndex];
String ri="";
if(riIndex!=-1){
ri=lineValues[riIndex];
}
if (partNumber.isEmpty()&&ri.isEmpty()) {
log.warn("行[partNumber=" + partNumber + "]中PN和RI都 为空,此行忽略");
} else {
int num = 1;
if (qtyIndex != -1) {
String numStr = lineValues[qtyIndex];
if (Strings.isNotBlank(numStr)) {
try {
num = Integer.valueOf(numStr);
} catch (Exception e) {
log.error(partNumber + "的数量:" + numStr + " 不是数字,使用1");
}
}
}
String feeder = "";
if (feederIndex != -1) {
feeder = lineValues[feederIndex];
}
String so=fileName;
if(soIndex!=-1){
so=lineValues[soIndex];
}
if(!ObjectUtil.isNotEmpty(so)){
so=fileName;
}
LiteOrderItem item = new LiteOrderItem();
item.setPn(partNumber);
if(partNumber.isEmpty()){
item.setNeedReelCount(1);
}
item.setNeedNum(num);
item.setFeederInfo(feeder);
item.setRi(ri);
if(!itemMap.containsKey(so)){
itemMap.put(so,new ArrayList<LiteOrderItem>());
}
itemMap.get(so).add(item);
items.add(item);
}
}
return itemMap;
} catch (Exception ex) {
log.error("解析上传的工单出错:" + ex.toString());
}
return null;
}
//
@ApiOperation("工单详情")
@GetMapping("/detial")
......@@ -453,4 +362,83 @@ public class OrderController {
return ResultBean.newOkResult(orderMapper.toDto(order));
}
// protected Map<String ,List<LiteOrderItem>> handleOrderCsv(String fileName,String fileURL) {
// try {
// fileName=fileName.replace(".csv","");
// log.info("开始更解析上传的工单");
// Map<String ,List<LiteOrderItem>> itemMap=new HashMap<>();
// List<LiteOrderItem> items = Lists.newArrayList();
//
// OrderSetting orderSetting = dataCache.getOrderSetting();
//
// CsvReader csvRead = CsvReader.newReader(fileURL,"PN", orderSetting.getPn());
// int partNumberIndex = csvRead.getIndex("PN", orderSetting.getPn());
// int qtyIndex = csvRead.getIndex("QTY", orderSetting.getQty());
// int feederIndex = csvRead.getIndex("FEEDER", orderSetting.getFeeder());
// int riIndex = csvRead.getIndex("RI",orderSetting.getRi());
// int soIndex = csvRead.getIndex("SO", orderSetting.getSo());
//
// int row = 1;
// int newRowCount = 0;
// int updateRowCount = 0;
//
// while (csvRead.readRecord()) {
// row++;
// String[] lineValues = csvRead.getValues();
// String partNumber = lineValues[partNumberIndex];
// String ri="";
// if(riIndex!=-1){
// ri=lineValues[riIndex];
// }
// if (partNumber.isEmpty()&&ri.isEmpty()) {
// log.warn("行[partNumber=" + partNumber + "]中PN和RI都 为空,此行忽略");
// } else {
// int num = 1;
// if (qtyIndex != -1) {
// String numStr = lineValues[qtyIndex];
// if (Strings.isNotBlank(numStr)) {
// try {
// num = Integer.valueOf(numStr);
// } catch (Exception e) {
// log.error(partNumber + "的数量:" + numStr + " 不是数字,使用1");
// }
// }
// }
// String feeder = "";
// if (feederIndex != -1) {
// feeder = lineValues[feederIndex];
// }
// String so=fileName;
//
// if(soIndex!=-1){
// so=lineValues[soIndex];
// }
// if(!ObjectUtil.isNotEmpty(so)){
// so=fileName;
// }
// LiteOrderItem item = new LiteOrderItem();
// item.setPn(partNumber);
// if(partNumber.isEmpty()){
// item.setNeedReelCount(1);
// }
// item.setNeedNum(num);
//
// item.setFeederInfo(feeder);
// item.setRi(ri);
// if(!itemMap.containsKey(so)){
// itemMap.put(so,new ArrayList<LiteOrderItem>());
// }
// itemMap.get(so).add(item);
//
//
// items.add(item);
// }
// }
// return itemMap;
// } catch (Exception ex) {
// log.error("解析上传的工单出错:" + ex.toString());
// }
// return null;
// }
}
......@@ -12,4 +12,6 @@ public interface ILiteOrderManager extends IBaseManager<LiteOrder> {
LiteOrder createWithItems(LiteOrder liteOrder) throws ValidateException;
List<LiteOrder> findUnEndOrdersList();
LiteOrder findBySource(String source);
}
......@@ -94,6 +94,15 @@ public class LiteOrderManagerImpl implements ILiteOrderManager {
}
@Override
public LiteOrder findBySource(String source) {
if (StringUtils.isEmpty(source)) {
return null;
} else {
return liteOrderDao.findOneByCondition(new String[]{"source"}, new String[]{source});
}
}
@Override
public PageData<LiteOrder> findByPage(Query query, Pageable pageable) {
int totalCount = liteOrderDao.countByQuery(query);
List<LiteOrder> list = liteOrderDao.findByQuery(query, pageable);
......
......@@ -2,6 +2,7 @@ package com.neotel.smfcore.core.order.service.po;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.common.utils.StorageConstants;
import com.neotel.smfcore.common.utils.StringUtils;
import com.neotel.smfcore.core.order.enums.LITEORDER_STATUS;
import lombok.Data;
import org.springframework.data.annotation.Transient;
......@@ -21,7 +22,15 @@ public class LiteOrder extends BasePo implements Serializable {
public LiteOrder(String orderNo, List<LiteOrderItem> orderItems) {
this.orderItems = orderItems;
this.orderNo = orderNo;
this.type=1;
this.type = 2;
for (LiteOrderItem item :
orderItems) {
if (!StringUtils.isEmpty(item.getPn()) && (StringUtils.isEmpty(item.getRi()))) {
this.type = 1;
break;
}
}
this.status = LITEORDER_STATUS.NEW;
}
/**
......
package com.neotel.smfcore.core.order.util;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.neotel.smfcore.common.csv.CsvReader;
import com.neotel.smfcore.common.utils.SmbUtil;
import com.neotel.smfcore.core.device.util.DataCache;
import com.neotel.smfcore.core.order.LiteOrderCache;
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.core.system.bean.OrderSetting;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 工单文件夹监控
*/
@Service
@Slf4j
public class OrderFileWatch {
@Autowired
private DataCache dataCache;
@Autowired
private ILiteOrderManager liteOrderManager;
@Autowired
private LiteOrderCache liteOrderCache;
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
private static boolean isRunning = false;
public void init(){
if(!isRunning){
isRunning = true;
log.info("开启订单监控任务");
//10 秒之后执行,每5秒钟执行一次
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
watchOrderDir();
}
}, 10, 5, TimeUnit.SECONDS);
}
}
private synchronized void watchOrderDir(){
try{
String dir = dataCache.getOrderSetting().getOrderDir() ;
if(Strings.isNotBlank(dir)){
dir = dir.replaceAll("\\\\", "/");
}else{
return;
}
final String orderDir = dir;
final String localDir = getLocalDir(orderDir);
//orderFileDir = "/Volumes/SSD/code";
if(Strings.isNotBlank(localDir)){
File orderFolder = new File(localDir);
if(orderFolder.exists() && orderFolder.isDirectory()){
for (File file : orderFolder.listFiles()) {
if(file.isDirectory()){
continue;
}
File resultFile = null;
String fileName = file.getName();
String backupFileName = fileName +"_" + System.currentTimeMillis();
//看数据库是否已有此工单
if(fileName.endsWith(".process") || fileName.endsWith("_result.txt")){
continue;
}
if(isOrderFileType(fileName)){
LiteOrder fileNameOrder = liteOrderManager.findBySource(fileName);
if(fileNameOrder == null){
log.info("watchOrderDir:监控到新的Order文件,准备处理:" + file.getAbsolutePath());
try{
Map<String, List<LiteOrderItem>> itemMap = readCsvFile(fileName,file.getAbsolutePath());
if (itemMap == null || itemMap.size() <= 0) {
log.error("watchOrderDir: 文件["+fileName+"]解析失败");
continue;
}
for (String so:itemMap.keySet()
) {
List<LiteOrderItem> liteOrderItems = itemMap.get(so);
if (liteOrderItems.size() <= 0) {
continue;
}
LiteOrder liteOrder = new LiteOrder(so, liteOrderItems);
liteOrder.setSource(fileName);
LiteOrder dbOrder = liteOrderManager.findByOrderNo(liteOrder.getOrderNo());
if (dbOrder != null) {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
//把名字改为带时间的
String newOrderNo = liteOrder.getOrderNo() + "-" + format.format(new Date());
dbOrder = liteOrderManager.findByOrderNo(newOrderNo);
if (dbOrder == null) {
liteOrder.setOrderNo(newOrderNo);
} else {
log.info("watchOrderDir:数据库中已存在工单号为[" + liteOrder.getOrderNo() + "],忽略文件:" + file.getAbsolutePath());
resultFile = new File(localDir+File.separator + "error",backupFileName);
continue;
}
}
log.info("watchOrderDir:新增加订单:" + liteOrder.getOrderNo() + ",共" + liteOrderItems.size() + "条工单详情");
liteOrder = liteOrderManager.createWithItems(liteOrder);
liteOrderCache.addOrderToMap(liteOrder);
resultFile = new File(localDir+File.separator + "sucess",backupFileName);
}
}catch (Exception e){
log.error("read order from file ["+file.getAbsolutePath()+"] :",e);
resultFile = new File(localDir+File.separator + "error",backupFileName);
}
}
resultFile = new File(localDir+File.separator + "sucess",backupFileName);
}
if(resultFile != null){
resultFile.getParentFile().mkdirs();
file.renameTo(resultFile);
}
}
}
}
}catch (Exception e){
log.error("订单监控出错",e);
}
}
private boolean isOrderFileType(String smbFile){
//判断是否是有效的工单文件
if( smbFile.toLowerCase().endsWith("csv")){
return true;
}
return false;
}
private String getLocalDir(String orderDir){
String[] fileTypes=new String[]{"csv","xml"};
String localDir = orderDir;
if(Strings.isNotBlank(orderDir)) {
orderDir = orderDir.replaceAll("\\\\", "/");
if(orderDir.toLowerCase().startsWith("smb")){
localDir = System.getProperty("user.dir") + File.separator + "orderDir";
List<String> smbFiles = SmbUtil.smbFileNameList(orderDir);
File localDirFile = new File(localDir);
if(!localDirFile.exists()){
log.info("生成临时文件夹:" + localDir);
localDirFile.mkdir();
}
if(smbFiles != null){
for (String smbFile : smbFiles) {
if(isOrderFileType(smbFile)){
File localFile = new File(localDirFile,smbFile);
if(!localFile.exists()){
SmbUtil.smbGet(orderDir + smbFile,localDir);
}
}
}
//再删除远程不存在的
String[] localFiles = localDirFile.list();
if(localFiles != null){
for(String fileName : localFiles){
if(isOrderFileType(fileName)){
if(!smbFiles.contains(fileName)){
//同时删除本地的result 文件
log.info("远程文件["+fileName+"]已经清除,删除本地文件和result 文件");
String suffixName = fileName.substring(0,fileName.length()-4);
File resultFile = new File(localDir,suffixName+"_result.txt");
if(resultFile.exists()){
resultFile.delete();
}
//远程已不包含,删除本地的
File file = new File(localDir,fileName);
file.delete();
}
}
}
}
}
}
}
return localDir;
}
public Map<String ,List<LiteOrderItem>> readCsvFile(String fileName, String fileURL) {
try {
fileName=fileName.replace(".csv","");
log.info("开始更解析上传的工单");
Map<String ,List<LiteOrderItem>> itemMap=new HashMap<>();
List<LiteOrderItem> items = Lists.newArrayList();
OrderSetting orderSetting = dataCache.getOrderSetting();
CsvReader csvRead = CsvReader.newReader(fileURL,"PN", orderSetting.getPn());
int partNumberIndex = csvRead.getIndex("PN", orderSetting.getPn());
int qtyIndex = csvRead.getIndex("QTY", orderSetting.getQty());
int feederIndex = csvRead.getIndex("FEEDER", orderSetting.getFeeder());
int riIndex = csvRead.getIndex("RI",orderSetting.getRi());
int soIndex = csvRead.getIndex("SO", orderSetting.getSo());
int row = 1;
int newRowCount = 0;
int updateRowCount = 0;
while (csvRead.readRecord()) {
row++;
String[] lineValues = csvRead.getValues();
String partNumber = lineValues[partNumberIndex];
String ri="";
if(riIndex!=-1){
ri=lineValues[riIndex];
}
if (partNumber.isEmpty()&&ri.isEmpty()) {
log.warn("行[partNumber=" + partNumber + "]中PN和RI都 为空,此行忽略");
} else {
int num = 1;
if (qtyIndex != -1) {
String numStr = lineValues[qtyIndex];
if (Strings.isNotBlank(numStr)) {
try {
num = Integer.valueOf(numStr);
} catch (Exception e) {
log.error(partNumber + "的数量:" + numStr + " 不是数字,使用1");
}
}
}
String feeder = "";
if (feederIndex != -1) {
feeder = lineValues[feederIndex];
}
String so=fileName;
if(soIndex!=-1){
so=lineValues[soIndex];
}
if(!ObjectUtil.isNotEmpty(so)){
so=fileName;
}
LiteOrderItem item = new LiteOrderItem();
item.setPn(partNumber);
if(partNumber.isEmpty()){
item.setNeedReelCount(1);
}
item.setNeedNum(num);
item.setFeederInfo(feeder);
item.setRi(ri);
if(!itemMap.containsKey(so)){
itemMap.put(so,new ArrayList<LiteOrderItem>());
}
itemMap.get(so).add(item);
items.add(item);
}
}
return itemMap;
} catch (Exception ex) {
log.error("解析上传的工单出错:" + ex.toString());
}
return null;
}
}
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!