OrderFileWatch.java 15.6 KB
package com.myproject.api;

import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;
import com.google.common.collect.Lists;
import com.myproject.bean.json.LiteOrder;
import com.myproject.bean.json.LiteOrderItem;
import com.myproject.bean.update.Barcode;
import com.myproject.bean.update.Component;
import com.myproject.dao.mongo.ILiteOrderDao;
import com.myproject.manager.IStoragePosManager;
import com.myproject.util.XmlUtil;
import com.myproject.webapp.controller.webService.DataCache;
import com.myproject.webapp.controller.webService.ITaskService;
import com.myproject.webapp.controller.webService.TaskService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.nio.charset.Charset;
import java.nio.file.Files;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 订单文件监控
 * Created by sunke on 2019/8/20.
 */
@Service
public class OrderFileWatch {

    @Autowired
    private DataCache dataCache;

    @Autowired
    private IStoragePosManager storagePosManager;

    @Autowired
    protected ITaskService taskService;

    @Autowired
    protected ILiteOrderDao liteOrderDao;

    protected final transient Logger log = LogManager.getLogger(getClass());

    ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);

    private static boolean isRunning = false;

    public void init(){
        if(!isRunning){
            isRunning = true;
            log.info("开启订单监控任务");
            //5 秒之后执行,每2秒钟执行一次
            scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

                @Override
                public void run() {
                    watchOrderDir();
                }
            }, 5, 2, TimeUnit.SECONDS);
        }
    }

    private String getLocalDir(String orderDir){
        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(smbFile.endsWith(".xml") || smbFile.endsWith("csv")){
                            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(fileName.endsWith(".xml") || fileName.endsWith("csv")){
                                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;

    }

    private synchronized void watchOrderDir(){
        try{
            String dir = dataCache.getSettings().getOrderFileDir();
            if(Strings.isNotBlank(dir)){
                dir = dir.replaceAll("\\\\", "/");
            }
            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(fileName.toLowerCase().endsWith(".xml") || fileName.toLowerCase().endsWith(".csv") || fileName.toLowerCase().endsWith(".txt")){
                            LiteOrder dbOrder = liteOrderDao.findBySource(fileName);
                            if(dbOrder == null){
                                log.info("监控到新的Order文件,准备处理:" + file.getAbsolutePath());
                                try{
                                    //没有执行过的任务
                                    LiteOrder liteOrder = null;
                                    if(fileName.toLowerCase().endsWith(".xml")){
                                        liteOrder = readXml(file);
                                    }if(fileName.toLowerCase().endsWith(".txt")){
                                        //阳光电源SAP
                                        liteOrder = readTxt(file);
                                    }else {
                                        liteOrder = readCsv(file);
                                    }
                                    if(liteOrder != null){
                                        liteOrder.setSource(fileName);
                                        dbOrder = liteOrderDao.findByOrderNo(liteOrder.getOrderNo());
                                        if(dbOrder == null){
                                            log.info("新增加订单:" + liteOrder.getOrderNo());
                                            liteOrder = liteOrderDao.createWithItems(liteOrder);
                                            TaskService.liteOrderMap.put(liteOrder.getOrderNo(), liteOrder);
                                        }else{
                                            log.info("数据库中已存在工单号为["+liteOrder.getOrderNo()+"],忽略文件:" + file.getAbsolutePath());
                                        }
                                        resultFile = new File(localDir+File.separator + "sucess",backupFileName);
                                    }else{
                                        resultFile = new File(localDir+File.separator + "error",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);
        }
    }

    /**
     * 读取 XML 文件(匈牙利)
     * @param xmlFile
     * @return
     */
    private LiteOrder readXml(File xmlFile){
        List<LiteOrderItem> items = Lists.newArrayList();
        try {
            List<String> xmlLines = Files.readAllLines(xmlFile.toPath(), Charset.defaultCharset());
            for (String xmlLine : xmlLines) {
                List<String> reorders = XmlUtil.getElementsByNode("Reorder", xmlLine);
                for (String reorder : reorders) {
                    String partNumber = XmlUtil.getNodeAttribute("Reorder", "Component", reorder);
                    if(Strings.isNotBlank(partNumber)){
                        LiteOrderItem item = new LiteOrderItem();
                        item.setPn(partNumber);
                        item.setNeedNum(1);
                        items.add(item);
                    }
                }
            }
        } catch (Exception e) {
            log.error("读取订单 XML 文件["+xmlFile.getAbsolutePath()+"]出错");
            return null;
        }

        String fileName = xmlFile.getName();
        return new LiteOrder(fileName, items);
    }


    /**
     * 读取阳光电源TXT 文件
     * @param txtFile
     * @return
     */
    private LiteOrder readTxt(File txtFile){
        List<LiteOrderItem> items = Lists.newArrayList();
        try {
            List<String> lines = null;
            try{
                lines = Files.readAllLines(txtFile.toPath(),Charset.forName("GBK"));
            }catch (Exception e){
                log.error("文件["+txtFile.getAbsolutePath()+"]读取出错,尝试切换编码读取");
                lines = Files.readAllLines(txtFile.toPath(),Charset.defaultCharset());
            }
            String linesStr = String.join("\n",lines);
            //判断是否是阳光电源的 TXT文件
            if(linesStr.contains("订单") && linesStr.contains("项目")){
                String orderNo = "";
                for (String line : lines) {
                    if(line.contains("订单:")){
                        orderNo = line.substring(3).trim();
                    }else if(line.contains("|")){
                        String[] infos = line.split("\\|");
                        if(infos.length >= 6){
                            if(line.contains("项目")){
                                continue;
                            }
                            LiteOrderItem item = new LiteOrderItem();
                            item.setPn(infos[2].trim());
                            int needNum = Float.valueOf(infos[5].replaceAll(",","").trim()).intValue();
                            item.setNeedNum(needNum);
                            items.add(item);
                        }else{
                            return null;
                        }
                    }
                }
                return new LiteOrder(orderNo, items);
            }

        } catch (Exception e) {
            log.error("读取订单 Txt 文件["+txtFile.getAbsolutePath()+"]出错",e);
        }
        return null;
    }

    /**
     * 读取 CSV 订单文件(两列:PN,num)
     * @param csvFile
     * @return
     */
    private LiteOrder readCsv(File csvFile){
        List<LiteOrderItem> items = Lists.newArrayList();
        try {
            CsvReader csvRead = new CsvReader(csvFile.getAbsolutePath());
            csvRead.setSkipEmptyRecords(true);//忽略空行
            csvRead.setTrimWhitespace(true);//去除空格
            csvRead.readHeaders();

            int columnCount = csvRead.getHeaderCount();

            int reelIdIndex = csvRead.getIndex("RI");
            if(reelIdIndex != -1 || columnCount > 22){
                while(csvRead.readRecord()){
                    String[] lineValues = csvRead.getValues();
                    String reelId = "";
                    if(columnCount > 22){
                        //只有V列包含Tower时才进行出库
                        String needOutStr = lineValues[21];
                        if(needOutStr.toUpperCase().contains("TOWER")){
                            reelId = lineValues[14];
                            if(reelId.contains(",")){
                                reelId = reelId.split(";")[0];
                                log.info("ReelId has more vlues, only use ["+reelId+"],ignore others.");
                            }
                        }else{
                            log.warn("行[reelId="+reelId + "]的V列["+needOutStr+"]不包含TOWER,此行忽略");
                        }

                    }else{
                        reelId = lineValues[reelIdIndex];
                    }
                    if(reelId.isEmpty()){
                        log.warn("行[reelId="+reelId + "]中RI 为空,此行忽略");
                    }else{
                        int num = 1;
                        LiteOrderItem item = new LiteOrderItem();
                        item.setReelId(reelId);
                        item.setPn("");
                        item.setNeedNum(num);
                        items.add(item);
                    }
                }
            }else{
                int partNumberIndex = csvRead.getIndex("PN");
                if (partNumberIndex == -1){
                    log.info("未包含PN列");
                    return null;
                }
                int qtyIndex = csvRead.getIndex("NUM","QTY");
                if (qtyIndex == -1){
                    log.info("未包含【NUM】列");
                    return null;
                }
                int feederIndex = csvRead.getIndex("FEEDER");
                while(csvRead.readRecord()){
                    String[] lineValues = csvRead.getValues();
                    String partNumber = lineValues[partNumberIndex];

                    if(partNumber.isEmpty()){
                        log.warn("行[partNumber="+partNumber + "]中PN 为空,此行忽略");
                    }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];
                        }
                        LiteOrderItem item = new LiteOrderItem();
                        item.setPn(partNumber);
                        item.setNeedNum(num);
                        item.setFeederInfo(feeder);
                        items.add(item);
                    }
                }
            }

            String fileName = csvFile.getName();
            return new LiteOrder(fileName, items);
        } catch (Exception e) {
            log.error("读取订单 CSV文件["+csvFile.getAbsolutePath()+"]出错",e);
        }
        return null;
    }

}