package com.sw.mes.sap.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.stream.Collectors;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.common.utils.MD5Utils;
import com.google.gson.Gson;
import com.sw.mes.base.factory.init.entity.CrystalMaterialRelation;
import com.sw.mes.base.factory.init.service.CrystalMaterialRelationService;
import com.sw.mes.base.system.entity.DictionaryItem;
import com.sw.mes.base.system.service.DictionaryItemService;
import com.sw.mes.core.annotation.Jinko;
import com.sw.mes.core.base.BaseServiceImpl;
import com.sw.mes.core.context.BaseContextHandler;
import com.sw.mes.core.dto.sap.ReportSapChargItemDto;
import com.sw.mes.core.dto.sap.ReportSapGoodsmvtDto;
import com.sw.mes.core.enums.EnumValuesFactory;
import com.sw.mes.core.response.Result;
import com.sw.mes.core.response.ResultCode;
import com.sw.mes.core.response.ResultGenerator;
import com.sw.mes.core.utils.DateUtil;
import com.sw.mes.sap.dao.ReportSapGoodsmvtDao;
import com.sw.mes.sap.dto.statistics.StatisticsDto;
import com.sw.mes.sap.entity.LogSapStock;
import com.sw.mes.sap.entity.ReportSapGoodsmvt;
import com.sw.mes.sap.entity.WarehouseLocation;
import com.sw.mes.sap.service.LogSapStockService;
import com.sw.mes.sap.service.ReportSapGoodsmvtService;
import com.sw.mes.sap.service.SAPOutputServiceService;
import com.sw.mes.sap.service.WarehouseLocationService;
import com.sw.mes.sap.task.SapGoodsmvtQueueCache;
import com.sw.mes.utils.CodeUtil;
import com.sw.mes.utils.StringUtils;
import com.sw.mes.yb.plan.entity.PlanProductionOrderBom;
import com.sw.mes.yb.plan.entity.ProductionOrder;
import com.sw.mes.yb.plan.service.PlanProductionOrderBomService;
import com.sw.mes.yb.plan.service.ProductionOrderService;
import com.xxl.job.core.handler.annotation.XxlJob;

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * MES报工SAP货物移动接口Service业务层处理
 *
 * @author liru
 * @date 2024-01-06
 */
@Slf4j
@Service
@Transactional
@Jinko(value="MES报工SAP货物移动接口Service业务层处理",author = "liru")
public class ReportSapGoodsmvtServiceImpl extends BaseServiceImpl<ReportSapGoodsmvt> implements ReportSapGoodsmvtService
{
    private ReportSapGoodsmvtDao dao;

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private SAPOutputServiceService sAPOutputServiceService;
    @Autowired
    private ProductionOrderService productionOrderService;
    @Autowired
    private DictionaryItemService dictionaryItemService;
    
    @Autowired
    private PlanProductionOrderBomService planProductionOrderBomService;
    @Autowired
    private LogSapStockService logSapStockService;

	@Autowired
	private CrystalMaterialRelationService crystalMaterialRelationService;
	@Autowired
	private WarehouseLocationService warehouseLocationService;
//	@Autowired
//	private SapGoodsmvtDataAsyncService sapGoodsmvtDataAsyncService;
	

    @Autowired
    public void setDao(ReportSapGoodsmvtDao dao) {
        super.setBaseDao(dao);
        this.dao=dao;
    }
    
    @Override
    public void superSaveOrUpdate(ReportSapGoodsmvt reportSapGoodsmvt) {
    	super.saveOrUpdate(reportSapGoodsmvt);
    }
    
    
    
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveOrUpdate(ReportSapGoodsmvt reportSapGoodsmvt) {
    	boolean isInsert = true;
    	log.info("保存上报数据：" + JSONObject.toJSONString(reportSapGoodsmvt));
    	if(reportSapGoodsmvt.getId()!=null) {
    		isInsert = false;
    		ReportSapGoodsmvt source = get(reportSapGoodsmvt.getId());
    		if(!StringUtils.equals(source.getMatnr(), reportSapGoodsmvt.getMatnr()) || !StringUtils.equals(source.getCharg(), reportSapGoodsmvt.getCharg()) || !StringUtils.equals(source.getAufnr(), reportSapGoodsmvt.getAufnr())) {
    			reportSapGoodsmvt.setZuuid(null);
    		}
    		
    	}else {
    		reportSapGoodsmvt.setStatus(false);
    		reportSapGoodsmvt.setCreateDate(new Date());
    		
    		//验证库存地点是否在SAP中维护
    		if(StringUtils.isNotBlank(reportSapGoodsmvt.getWerks()) && StringUtils.isNotBlank(reportSapGoodsmvt.getLgort())){
    			//未存在SAP库位同步记录中的库位名称,不记录报工数据
    			WarehouseLocation warehouseLocation = warehouseLocationService.findByWerksAndLgort(reportSapGoodsmvt.getWerks(), reportSapGoodsmvt.getLgort());
    			if(warehouseLocation==null) {
    				log.info("报工任务过滤库存地点非SAP维护库位信息",JSON.toJSONString(reportSapGoodsmvt));
    				return;
    			}
    		}
    		
    		//验证收货库区是否在SAP中维护
    		if(StringUtils.isNotBlank(reportSapGoodsmvt.getUmwrk()) &&  StringUtils.isNotBlank(reportSapGoodsmvt.getUmlgo())){
    			//未存在SAP库位同步记录中的库位名称,不记录报工数据
    			WarehouseLocation warehouseLocation = warehouseLocationService.findByWerksAndLgort(reportSapGoodsmvt.getUmwrk(), reportSapGoodsmvt.getLgort());
    			if(warehouseLocation==null) {
    				log.info("报工任务过滤目标库区非SAP维护库位信息",JSON.toJSONString(reportSapGoodsmvt));
    				return;
    			}
    		}
    		
    	}
    	
    	ProductionOrder order = productionOrderService.findByAufnr(reportSapGoodsmvt.getAufnr());
    	if(order!=null) {
	    	reportSapGoodsmvt.setVbeln(order.getSalesorder());//销售订单
	    	reportSapGoodsmvt.setPosnr(order.getKdpos());//销售订单行
	    	reportSapGoodsmvt.setEbeln(order.getZCollectNo());//采购订单 - 组合号   待确认 
	    	reportSapGoodsmvt.setEbelp(order.getZCollectItm());//采购订单行 - 组合行号   待确认
	    	reportSapGoodsmvt.setWerks(order.getWerks());
	    	
	    	//计划内物料上报
	    	if(StringUtils.isBlank(reportSapGoodsmvt.getRsnum()) && StringUtils.isNotBlank(reportSapGoodsmvt.getMatnr()) && (reportSapGoodsmvt.getBwart().equals("261") || reportSapGoodsmvt.getBwart().equals("262"))) {
		    	PlanProductionOrderBom bom = planProductionOrderBomService.findByOrderIdAndMatnr(order.getId(), reportSapGoodsmvt.getMatnr());
		    	if(bom!=null) {
		    		reportSapGoodsmvt.setRsnum(order.getComment()); //SAP预留  -  RSNUM - Comment
		    		reportSapGoodsmvt.setRspos(bom.getRspos());//bom 行号
		    	}
	    	}
    	}
        //初始化默认数据
    	if(reportSapGoodsmvt.getBudat()==null) {
	    	Date currentDate = new Date();
	        reportSapGoodsmvt.setBudat(currentDate);
    	}
    	
    	reportSapGoodsmvt.setErnam(BaseContextHandler.getUsername());
    	
    	super.saveOrUpdate(reportSapGoodsmvt);
    	
    	//自动报工 开启新事物 提交现有事物
        autoSendReportSapGoodsmvt(reportSapGoodsmvt, isInsert);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
	public void autoSendReportSapGoodsmvt(ReportSapGoodsmvt reportSapGoodsmvt, boolean isInsert) {
		//新建时自动报工
        if(isInsert) {
			try {
				DictionaryItem switchValue = dictionaryItemService.findByThemeValueAndNameAndEnable("AutoReportSwitch",reportSapGoodsmvt.getBwart(),true);
				if (StringUtils.isNotBlank(switchValue.getValue()) && switchValue.getValue().equalsIgnoreCase("true")) {
					if(StringUtils.isBlank(switchValue.getExtendValue1()) ||  (StringUtils.isNotBlank(switchValue.getExtendValue1()) && switchValue.getExtendValue1().contains(reportSapGoodsmvt.getProcName()))) {
						if(reportSapGoodsmvt.getAsyn()) {//程序异步处理
							//spring 管理单线程队列异步执行发送SAP信息
							//sapGoodsmvtDataAsyncService.sapGoodsmvtDataHandler(this,reportSapGoodsmvt.getId());
							//添加异步处理缓存中
							SapGoodsmvtQueueCache.getInstance().addCache(reportSapGoodsmvt.getId());
						}else {//手动同步处理
							List<Result> results = sendReportWord(new Long[] { reportSapGoodsmvt.getId() },"AUTO");
							for (Result result : results) {
								if(result.getCode().equals(ResultCode.FAIL.getCode())) {
									log.error("自动报工失败:{}", result.getMessage());
								}
							}
						}
					}
				}
			}catch (Exception e){
				e.printStackTrace();
				log.error("新建时自动报工异常：", e);
			}
        }
	}
    
    
    /**
     * 验证规则:
     * 1.验证 (移动类型 验证订单 物料 批次 库存地点 目标库存地点 发货工厂 收货工厂 收货批次号 数量 单位 SAP预留 SAP预留行项目 成本中心) 是否重复
     * 2.根据校验值查询是否存在相同数据,取最后一条
     * 3.验证时间是否在1分钟以内, 间隔时间1分钟以上允许上报
     */
    private boolean validateDoubleSend(ReportSapGoodsmvt reportSapGoodsmvt) {
		//1.验证 (移动类型 验证订单 物料 批次 库存地点 目标库存地点 发货工厂 收货工厂 收货批次号 数量 单位 SAP预留 SAP预留行项目 成本中心) 是否重复
    	String aufnr = reportSapGoodsmvt.getAufnr();
    	String bwart = reportSapGoodsmvt.getBwart();
    	String matnr = reportSapGoodsmvt.getMatnr();
    	String charg = reportSapGoodsmvt.getCharg();
    	String lgort = reportSapGoodsmvt.getLgort();
    	String umlgo = reportSapGoodsmvt.getUmlgo();
    	String werks = reportSapGoodsmvt.getWerks();
    	String umcha = reportSapGoodsmvt.getUmcha();
    	String menge = reportSapGoodsmvt.getMenge();
    	String meins = reportSapGoodsmvt.getMeins();
    	String rsnum = reportSapGoodsmvt.getRsnum();
    	String rspos = reportSapGoodsmvt.getRspos();
    	String kostl = reportSapGoodsmvt.getKostl();
    	String crystalNo = reportSapGoodsmvt.getCrystalNo();
    	
    	StringBuilder sb = new StringBuilder();
    	sb.append(aufnr).append(bwart).append(matnr).append(charg).append(lgort).append(umlgo).append(werks).append(umcha).append(menge).append(meins).append(rsnum).append(rspos).append(kostl).append(crystalNo);
    	
    	String md5Value = MD5Utils.md5Hex(sb.toString(), "UTF-8");
    	
    	reportSapGoodsmvt.setMd5value(md5Value);
    	
    	//2. 根据校验值查询是否存在相同数据,取最后一条
    	ReportSapGoodsmvt oldMvt = findLastByMd5Value(md5Value);
    	if(oldMvt!=null) {
    		//3. 验证时间是否在5分钟以内, 间隔时间5分钟以上允许上报
    		if(Math.abs(reportSapGoodsmvt.getCreateDate().getTime() -  oldMvt.getCreateDate().getTime()) <= 1000*60) {
    			return true;
    		}
    	}
    	
		return false;
	}

	@XxlJob("checkNotAutoSendSap")
    @Override
    public void checkNotAutoSendSap() {
    	log.info("==================开始检查未自动报工数据======================");
    	List<DictionaryItem> items = dictionaryItemService.findItemByThemeValueAndExtendValue1IsNotNull("AutoReportSwitch",true);
    	for (DictionaryItem dictionaryItem : items) {
    		if (StringUtils.isNotBlank(dictionaryItem.getValue()) && dictionaryItem.getValue().equalsIgnoreCase("true")) {
    			String bwart = dictionaryItem.getName();//移动类型 非数字格式过滤
    			if(!StringUtils.isNumeric(bwart)) {
    				continue;
    			}
    			//配置自动上报工序名称
    			String[] procNames = dictionaryItem.getExtendValue1().split(",");
    			for (String procName : procNames) {
					if(StringUtils.isNotBlank(procName)) {
						log.info("******正在检查工序:["+procName+"]["+bwart+"]未成功报工记录...");
						
						List<ReportSapGoodsmvt> notSendLogs = findByBwartAndProcNameAndStatus(bwart,procName,false);
						
						for (ReportSapGoodsmvt reportSapGoodsmvt : notSendLogs) {
							try {
								//只上报已请求失败的数据
								if(StringUtils.isNotBlank(reportSapGoodsmvt.getZuuid())) {
									List<Result> results = sendReportWord(new Long[] { reportSapGoodsmvt.getId() },"TIMER");
									for (Result result : results) {
										if(result.getCode().equals(ResultCode.FAIL.getCode())) {
											log.info("记录ID:"+reportSapGoodsmvt.getId()+",["+procName+"]["+bwart+"]定时报工失败:"+result.getMessage());
										}else {
											log.info("记录ID:"+reportSapGoodsmvt.getId()+",["+procName+"]["+bwart+"]定时报工成功:"+result.getMessage());
										}
									}
								}
							}catch (Exception e) {
							}
						}
						
						log.info("已完成检查工序:["+procName+"]["+bwart+"]未成功报工记录..."+(notSendLogs.size()>0?"存在未报工记录"+notSendLogs.size():""));
					}
				}
    		}
		}
    	log.info("==================本次检查未自动报工数据结束======================");
    }

	@Override
	public BigDecimal findSumWeightByProcNameAndBwartAndOrderNo(String procName, String bwart, String orderNo) {
		return dao.findSumWeightByProcNameAndBwartAndOrderNo(procName,bwart,orderNo);
	}
	

	@Override
    public List<Result> sendReportWord(Long[] ids,String sendType) {
    	List<Result> results = new ArrayList<Result>();
    	
        List<ReportSapGoodsmvtDto> dtolist = new ArrayList<>();
        

        //过滤异常请求记录
        filterException(ids, results, dtolist);
        
        for (ReportSapGoodsmvtDto reportSapGoodsmvtDto : dtolist) {
        	//设置手自动
        	reportSapGoodsmvtDto.setSendType(sendType);
        	
        	//最后一天8点后结算次月第一天时间
        	budatCheck(reportSapGoodsmvtDto);
        	
        	//初始化异常数据中 预留行号
        	//initExceptionData(reportSapGoodsmvtDto);
        	
        	//同步sap库位报工前库存
        	synSapnumAgo(reportSapGoodsmvtDto);
        	
        	//请求SAP发送报工
        	Result result = requestSap(reportSapGoodsmvtDto);
        	
            results.add(result);
        }
		return results;
    }
    
	
	/**
	 * 最后一天8点后结算次月第一天时间
	 */
    private void budatCheck(ReportSapGoodsmvtDto reportSapGoodsmvtDto) {
    	Date budat = reportSapGoodsmvtDto.getBudat();
    	Date lastDate8H = DateUtil.getCurrentMonthLastDayEndTime8H();
    	
    	if(budat.getTime()>lastDate8H.getTime()) {
    		Calendar c = Calendar.getInstance();
    		c.setTime(budat);
    		c.add(Calendar.DATE, 1);
    		reportSapGoodsmvtDto.setBudat(budat);
    	}
	}



	/**
     * 初始化异常数据
     */
    private void initExceptionData(ReportSapGoodsmvtDto reportSapGoodsmvtDto) {
    	if(reportSapGoodsmvtDto.getId()!=null) {
	        if(StringUtils.isBlank(reportSapGoodsmvtDto.getRsnum()) && StringUtils.isNotBlank(reportSapGoodsmvtDto.getAufnr()) && StringUtils.isNotBlank(reportSapGoodsmvtDto.getMatnr()) && (reportSapGoodsmvtDto.getBwart().equals("261") || reportSapGoodsmvtDto.getBwart().equals("262"))) {
	        	ProductionOrder order = productionOrderService.findByAufnr(reportSapGoodsmvtDto.getAufnr());
	        	if(order!=null) {
	        		reportSapGoodsmvtDto.setVbeln(order.getSalesorder());//销售订单
	        		reportSapGoodsmvtDto.setPosnr(order.getKdpos());//销售订单行
	        		reportSapGoodsmvtDto.setEbeln(order.getZCollectNo());//采购订单 - 组合号   待确认 
	        		reportSapGoodsmvtDto.setEbelp(order.getZCollectItm());//采购订单行 - 组合行号   待确认
	        		reportSapGoodsmvtDto.setWerks(order.getWerks());
	    	    	
	    	    	PlanProductionOrderBom bom = planProductionOrderBomService.findByOrderIdAndMatnr(order.getId(), reportSapGoodsmvtDto.getMatnr());
	    	    	if(bom!=null) {
	    	    		reportSapGoodsmvtDto.setRsnum(order.getComment()); //SAP预留  -  RSNUM - Comment
	    	    		reportSapGoodsmvtDto.setRspos(bom.getRspos());//bom 行号
	    	    	}
	        	}
	        }
    	}
	}


	/**
     * 请求SAP发送报工
     */
	private Result requestSap(ReportSapGoodsmvtDto reportSapGoodsmvtDto) {
		List<ReportSapGoodsmvtDto> dataList = new ArrayList<ReportSapGoodsmvtDto>();
		dataList.add(reportSapGoodsmvtDto);
		
		String zuuid = CodeUtil.getUniqueCode(reportSapGoodsmvtDto.getId());
		Date cDate = new Date();
		JSONArray array = new JSONArray();
		JSONArray items = JSONArray.parseArray(JSONArray.toJSONString(dataList));
		JSONObject IT_DATA = new JSONObject();
		
		if(StringUtils.isBlank(reportSapGoodsmvtDto.getZuuid())) {
			IT_DATA.put("ZUUID", zuuid);
		} else {
			IT_DATA.put("ZUUID", reportSapGoodsmvtDto.getZuuid());
			zuuid = reportSapGoodsmvtDto.getZuuid();
		}
		
		if(reportSapGoodsmvtDto.getBudat()!=null) {
			IT_DATA.put("BUDAT", DateUtil.formatDate(reportSapGoodsmvtDto.getBudat(),DateUtil.shortFormat2));
		}else {
			IT_DATA.put("BUDAT", DateUtil.formatDate(cDate,DateUtil.shortFormat2));
		}
		
		
		if(reportSapGoodsmvtDto.getBldat()!=null) {
			IT_DATA.put("BLDAT", DateUtil.formatDate(reportSapGoodsmvtDto.getBldat(),DateUtil.shortFormat2));
		}else {
			IT_DATA.put("BLDAT", DateUtil.formatDate(cDate,DateUtil.shortFormat2));
		}
		
		IT_DATA.put("ERNAM", reportSapGoodsmvtDto.getErnam());
		IT_DATA.put("GOODS_ITEMS", items);
		array.add(IT_DATA);

		String MBLNR = "";
		Result result = null;
		String errorInfo = null;
		
		boolean status = false;
		
		try {
			//reportSapGoodsmvtDto参数只为设置uuid
		    JSONObject jsonObject = sAPOutputServiceService.sendWorkGoodsMvtToSap(array,reportSapGoodsmvtDto);
		    
		    JSONObject ES_BC_INFO = jsonObject.getJSONObject("ES_BC_INFO");
		    String resultState = ES_BC_INFO.getString("TYPE");
		    if(StringUtils.isNotBlank(resultState) && resultState.equals("E")){
		    	String msg = ES_BC_INFO.getString("MSG");
		    	try {
		        	JSONArray ET_RETURN = jsonObject.getJSONArray("ET_RETURN");
		        	for (int i = 0; i < ET_RETURN.size(); i++) {
		        		JSONObject returnObj = ET_RETURN.getJSONObject(i);
		        		msg = returnObj.getString("MSGTX");
					}
		    	}catch (Exception e) {
		    		result = ResultGenerator.fail("ID("+reportSapGoodsmvtDto.getId()+"),msg:请求成功,没有返回值(ET_RETURN)"+e.getMessage());
				}
		    	
		    	result = ResultGenerator.fail("ID("+reportSapGoodsmvtDto.getId()+"),msg:"+msg);
		    	errorInfo = msg;
		    }else if(StringUtils.isNotBlank(resultState) && resultState.equals("W")){//重复修正报工数据返回结果处理
		    	try {
		    		JSONArray ET_RETURN = jsonObject.getJSONArray("ET_RETURN");
			    	for (int i = 0; i < ET_RETURN.size(); i++) {
			    		JSONObject returnObj = ET_RETURN.getJSONObject(i);
			    		MBLNR = returnObj.getString("MBLNR");
					}
		    	}catch (Exception e) {
				}
		    }else {
		    	JSONArray ET_RETURN = jsonObject.getJSONArray("ET_RETURN");
		    	for (int i = 0; i < ET_RETURN.size(); i++) {
		    		JSONObject returnObj = ET_RETURN.getJSONObject(i);
		    		MBLNR = returnObj.getString("MBLNR");
				}
		    	status = true;
		    }
		} catch (Exception e) {
		    log.error("requestSap error:",e);
		    errorInfo = e.getMessage();
		    status = false;
		    result = ResultGenerator.fail("ID("+reportSapGoodsmvtDto.getId()+"),msg:"+e.getMessage());
		}
		
		//上报成功后修改状态
		if(status) {
			errorInfo = "";//成功后清除异常原因
			reportSapGoodsmvtDto.setMblnr(MBLNR);
			
		    if(reportSapGoodsmvtDto.getBudat()==null) {
		    	reportSapGoodsmvtDto.setBudat(cDate);
		    }
		    
		    if(reportSapGoodsmvtDto.getBldat()==null) {
		    	reportSapGoodsmvtDto.setBldat(cDate);
		    }
		    //reportSapGoodsmvtDto.setErnam(BaseContextHandler.getUsername());
		    result = ResultGenerator.success(reportSapGoodsmvtDto.getId());
		}
		reportSapGoodsmvtDto.setZuuid(zuuid);
		reportSapGoodsmvtDto.setStatus(status);
		reportSapGoodsmvtDto.setErrorInfo(errorInfo);
		
		//同步Sap报工后库存
		synSapnumAfter(reportSapGoodsmvtDto);
		
		super.saveOrUpdate(fromDto(reportSapGoodsmvtDto));
		return result;
	}


    /**
     * 过滤异常请求记录
     */
	private void filterException(Long[] ids, List<Result> results, List<ReportSapGoodsmvtDto> dtolist) {
		for (Long id : ids) {
            ReportSapGoodsmvt reportSapGoodsmvt = get(id);
            
            //开关控制是否允许重复上报
            String switchValue = dictionaryItemService.findValueByThemeValueAndItemName("AutoReportSwitch","DoubleSwitch");
            
            if(reportSapGoodsmvt==null) {
            	log.error("filterException: id:{}, reportSapGoodsmvt:{}, switchValue:{}",id,reportSapGoodsmvt,switchValue);
            }
            log.info("filterException: id:{}, reportSapGoodsmvt:{}, switchValue:{}",id,reportSapGoodsmvt,switchValue);
            
            if (StringUtils.isNotBlank(switchValue) && switchValue.equalsIgnoreCase("false") && (reportSapGoodsmvt.getStatus()!=null && reportSapGoodsmvt.getStatus()==true)) {
            	Result result = ResultGenerator.fail("ID("+reportSapGoodsmvt.getId()+"),msg:此记录已上报，禁止重复上报");
            	results.add(result);
            	continue;
            }
            
            //开关控制验证工单是否关闭
            String orderCloseValidate = dictionaryItemService.findValueByThemeValueAndItemName("AutoReportSwitch","OrderCloseValidate");
            if (StringUtils.isNotBlank(orderCloseValidate) && orderCloseValidate.equalsIgnoreCase("true")) {
            	ProductionOrder order = productionOrderService.findByAufnr(reportSapGoodsmvt.getAufnr());
            	if(!order.getProductionStatus()) {
            		Result result = ResultGenerator.fail("ID("+reportSapGoodsmvt.getId()+"),msg:工单["+order.getAufnr()+"]已关闭");
                	results.add(result);
                	continue;
            	}
            }
            
            //101，102，531，532的时候校验同一个工单已上报（101，102主产品收货重量+531，532副产品收货重量）/261，262的消耗重量<=99.99%数据字典 开关卡控
            DictionaryItem inputOutputRatioValidate = dictionaryItemService.findNameByThemeValueAndItemName("AutoReportSwitch","InputOutputRatioValidate");//投入产出比验证开关
            if (inputOutputRatioValidate!=null && StringUtils.isNotBlank(inputOutputRatioValidate.getValue()) && inputOutputRatioValidate.getValue().equalsIgnoreCase("true")) {
            	
            	if(StringUtils.equals(reportSapGoodsmvt.getBwart(), "101") || StringUtils.equals(reportSapGoodsmvt.getBwart(), "531")) {
            		Double _sum101102531532 = dao.getSumAufnrAndInBwart(reportSapGoodsmvt.getAufnr(),Arrays.asList(new String[] {"101","102","531","532"}));
            		Double _sum261262 = dao.getSumAufnrAndInBwart(reportSapGoodsmvt.getAufnr(),Arrays.asList(new String[] {"261","262"}));
            		
            		_sum101102531532 = _sum101102531532==null?0:_sum101102531532;
            		_sum261262 = _sum261262==null?0:_sum261262;
            		
            		double value = 0;
            		
            		if(_sum261262>0) {
            			value = _sum101102531532/_sum261262;
            		}
            		
            		value = (double)Math.round(value*100 * 100)/100;
            		double limit = Double.valueOf(inputOutputRatioValidate.getExtendValue1());
            		
            		if(value>limit) {
            			Result result = ResultGenerator.fail(reportSapGoodsmvt.getAufnr()+"工单投入产出比>"+limit+"%");
                    	results.add(result);
                    	
                    	reportSapGoodsmvt.setErrorInfo(reportSapGoodsmvt.getAufnr()+"工单投入产出比>"+limit+"%");
                    	super.saveOrUpdate(reportSapGoodsmvt);
                    	continue;
            		}
            	}
            }
            
            
            
            //开关控制是否验证顺序过账
            String sequenceSwitch = dictionaryItemService.findValueByThemeValueAndItemName("AutoReportSwitch","SequenceSwitch");
            if (StringUtils.isNotBlank(sequenceSwitch) && !sequenceSwitch.equalsIgnoreCase("false") && StringUtils.isNotBlank(reportSapGoodsmvt.getCrystalNo())) {
            	List<ReportSapGoodsmvt> sequenceLogs =  findByCrystalNo(reportSapGoodsmvt.getCrystalNo());
            	
            	boolean isExistNotReport = false;
            	for (ReportSapGoodsmvt log : sequenceLogs) {
            		
            		
					if(log.getBudat()!=null && reportSapGoodsmvt.getBudat()!=null && log.getStatus()==false && log.getBudat().getTime()<=reportSapGoodsmvt.getBudat().getTime()) {
						if(log.getId()==reportSapGoodsmvt.getId()) {
							break;
						}
						
						Result result = ResultGenerator.fail("ID("+reportSapGoodsmvt.getId()+"),msg:存在移动类型:"+log.getBwart()+" 晶编:"+log.getCrystalNo()+" 未报工的"+log.getProcName()+"记录");
		            	results.add(result);
		            	
		            	isExistNotReport = true;
		            	break;
					}
				}
            	
            	if(isExistNotReport) {
            		continue;
            	}
            }
            
            ReportSapGoodsmvtDto dto = toEagerDto(reportSapGoodsmvt);
            dtolist.add(dto);
        }
	}


    /**
     * 同步Sap报工后库存
     */
	private void synSapnumAfter(ReportSapGoodsmvtDto reportSapGoodsmvtDto) {
		try {
			//发送后SAP物料库存
			//同步SAP库存
			LogSapStock stock = logSapStockService.synSapStock(reportSapGoodsmvtDto.getLgort(), reportSapGoodsmvtDto.getMatnr(), reportSapGoodsmvtDto.getCharg());
			if(stock!=null) reportSapGoodsmvtDto.setLgortSapnumAfter(stock.getLabst());
			//发送后SAP物料目标库存
			stock =  logSapStockService.synSapStock(reportSapGoodsmvtDto.getUmlgo(), reportSapGoodsmvtDto.getMatnr(), reportSapGoodsmvtDto.getCharg());
			if(stock!=null) reportSapGoodsmvtDto.setUmlgoSapnumAfter(stock.getLabst());
		}catch (Exception e) {
		}
	}


    /**
     * 同步sap库位报工前库存
     */
	private void synSapnumAgo(ReportSapGoodsmvtDto reportSapGoodsmvtDto) {
		try {
			LogSapStock stock =  logSapStockService.findByLgortAndMatnrAndCharg(reportSapGoodsmvtDto.getLgort(), reportSapGoodsmvtDto.getMatnr(), reportSapGoodsmvtDto.getCharg());
			if(stock!=null) reportSapGoodsmvtDto.setLgortSapnumAgo(stock.getLabst());
		
			stock =  logSapStockService.findByLgortAndMatnrAndCharg(reportSapGoodsmvtDto.getUmlgo(), reportSapGoodsmvtDto.getMatnr(), reportSapGoodsmvtDto.getCharg());
			if(stock!=null) reportSapGoodsmvtDto.setUmlgoSapnumAgo(stock.getLabst());
		}catch (Exception e) {
		}
	}

    @Override
    public List<ReportSapGoodsmvt> findByCrystalNo(String crystalNo) {
    	return dao.findByCrystalNo(crystalNo);
	}



	@Override
    public ReportSapGoodsmvt findByCrystalNoAndBwart(String crystalNo, String bwart) {
        if (StringUtils.isNotBlank(crystalNo) && StringUtils.isNotBlank(bwart)) {
            return dao.findByCrystalNoAndBwart(crystalNo, bwart);
        }
        return null;
    }

	@Override
    public List<ReportSapGoodsmvt> findByProcNameAndOrderNoAndBwart(String procName, String orderNo, List<String> bwart) {
        if (StringUtils.isNotBlank(procName) && StringUtils.isNotBlank(orderNo)) {
            return dao.findByProcNameAndOrderNoAndBwart("%" + procName + "%", orderNo, bwart);
        }
        return null;
    }

	@Override
    public List<ReportSapGoodsmvt> findByProcNameAndOrderNoAndBwartAndLotNo(String procName, String orderNo, List<String> bwart, String lotNo) {
        if (StringUtils.isNotBlank(procName) && StringUtils.isNotBlank(orderNo)) {
            return dao.findByProcNameAndOrderNoAndBwartAndLotNo("%" + procName + "%", orderNo, bwart, lotNo);
        }
        return null;
    }

    @Override
    public List<ReportSapGoodsmvt> groupMaterialCostAtSap() {
        List<Map<String, Object>> resultMap = dao.groupByMatnr();
        List<ReportSapGoodsmvt> list = new ArrayList<>(resultMap.size());
        for (Map<String, Object> map : resultMap) {
            ReportSapGoodsmvt goodsmvt = new ReportSapGoodsmvt();
            BigInteger bigInteger = (BigInteger) map.get("id");
            goodsmvt.setId(bigInteger.longValue());
            goodsmvt.setMatnr(map.get("code").toString());
            goodsmvt.setMenge(map.get("quantity").toString());
            goodsmvt.setProcName((String) map.get("procName"));
            list.add(goodsmvt);
        }
        return list;
    }


	@Override
	public ReportSapGoodsmvt findByCrystalNoAndBwartAndProcName(String crystalNo, String bwart,String procName) {
		if (StringUtils.isNotBlank(crystalNo) && StringUtils.isNotBlank(bwart) && StringUtils.isNotBlank(procName)) {
			return dao.findByCrystalNoAndBwartAndProcName(crystalNo, bwart,procName);
		}
		return null;
	}

	@Override
	public ReportSapGoodsmvt findByCrystalNoAndBwartAndProcName1(String crystalNo, String procName) {
		if (StringUtils.isNotBlank(crystalNo) && StringUtils.isNotBlank(procName)) {
			return dao.findByCrystalNoAndBwartAndProcName1(crystalNo, procName);
		}
		return null;
	}


    public ReportSapGoodsmvtDto toEagerDto(ReportSapGoodsmvt entity) {
        ReportSapGoodsmvtDto dto = modelMapper.map(entity, ReportSapGoodsmvtDto.class);
        dto.setChargItems(JSONArray.parseArray(entity.getChargItem(), ReportSapChargItemDto.class));
        return dto;
    }
    
    public ReportSapGoodsmvt fromDto(ReportSapGoodsmvtDto dto) {
        ReportSapGoodsmvt reportSapGoodsmvt = modelMapper.map(dto, ReportSapGoodsmvt.class);
        reportSapGoodsmvt.setChargItem(new Gson().toJson(dto.getChargItems()));
        return reportSapGoodsmvt;
    }



	@Override
	public List statisticYbcshdb(StatisticsDto dto) {
		return dao.statisticYbcshdb(dto);
	}

	@Override
	public Integer modifyAufnrByCrystalNo(String procName, List<String> crystalNoList,Integer status) {
		Assert.notNull(crystalNoList, "单晶不能为空！");
		Assert.notNull(procName, "工序不能为空！");

		List<ReportSapGoodsmvt> byCrystalNoAndProcName = dao.findByCrystalNoAndProcName(procName, crystalNoList,status);
		Integer countNo = 0;
		for (ReportSapGoodsmvt reportSapGoodsmvt : byCrystalNoAndProcName){
			if (StringUtils.isBlank(reportSapGoodsmvt.getCrystalNo())){
				continue;
			}
			CrystalMaterialRelation bySectionNoAndDeviceType = crystalMaterialRelationService.findBySectionNoAndDeviceType(reportSapGoodsmvt.getCrystalNo(), EnumValuesFactory.DeviceCategory.开方机.getKey());
			if (null != bySectionNoAndDeviceType && StringUtils.isNotBlank(bySectionNoAndDeviceType.getOrderNo())){
				reportSapGoodsmvt.setAufnr(bySectionNoAndDeviceType.getOrderNo());
				reportSapGoodsmvt.setRemark("批量修改SAP订单号");
				this.saveOrUpdate(reportSapGoodsmvt);
				countNo++;
			}
		}
		return countNo;
	}

	
	@Override
	public String importSAPExcel(MultipartFile file) {
		return handleDataFromExcel(file);
	}

	@Override
	public String importExcel(MultipartFile file) {
		return getDataFromExcel(file);
	}
	
	
	private String getDataFromExcel(MultipartFile file) {
		int size = 0;
		Map<String,Field> propertys = new LinkedHashMap<String, Field>();
		Field[] fields = ReportSapGoodsmvtDto.class.getDeclaredFields();
		for (Field field : fields) {
			ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
			if(excelProperty!=null) {
				propertys.put(field.getName(), field);
			}
		}
		
        InputStream fis = null;
        Workbook workBook;
        
        Cell cell = null;
        try {
            //获取一个绝对地址的流
            fis = file.getInputStream();
            //得到工作簿
            String fileName = file.getOriginalFilename();
            assert fileName != null;
            String name = ".xlsx";
            if (fileName.contains(name)) {
                workBook = new XSSFWorkbook(fis);
            } else {
                workBook = new HSSFWorkbook(fis);
            }
            //得到一个工作表
            Sheet sheet = workBook.getSheetAt(0);
            //获得表头
            Row rowHead = sheet.getRow(0);
            //判断表头是否正确
            if (rowHead.getPhysicalNumberOfCells() != size) {
                return "单元格数量不匹配";
            }
            //获得数据的总行数
            int totalRowNum = sheet.getLastRowNum();
            if(totalRowNum < 2) {
            	return "不允许导入空白数据,请编辑后重新导入";
            }
            
            List<ReportSapGoodsmvtDto> dtoList = new ArrayList<ReportSapGoodsmvtDto>();
            //获得所有数据
            for (int i = 1; i <= totalRowNum; i++) {
            	ReportSapGoodsmvtDto dto = new ReportSapGoodsmvtDto();
                //获得第i行对象
                Row row = sheet.getRow(i);
                if (row == null) {
                    break;
                }
                //获得获得第i行第0列的 String类型对象
                int colunmNum = 0;
                for (Map.Entry<String, Field> entry : propertys.entrySet()) {
                	String fieldName = entry.getKey();
                	Field fieldObj = entry.getValue();
                	
                	cell = row.getCell((short) colunmNum++);
                	if (null == cell) {
                		if(fieldObj.getType() == Integer.class) {
                			String value = cell.getStringCellValue();
                			BeanUtil.setFieldValue(dto, fieldName, Integer.parseInt(value));
                		}else if(fieldObj.getType() == Long.class) {
                			String value = cell.getStringCellValue();
                			BeanUtil.setFieldValue(dto, fieldName, Long.parseLong(value));
                		}else if(fieldObj.getType() == String.class) {
                			String value = cell.getStringCellValue();
                			BeanUtil.setFieldValue(dto, fieldName, value);
                		}else if(fieldObj.getType() == Date.class) {
                			Date value = cell.getDateCellValue();
                			BeanUtil.setFieldValue(dto, fieldName, value);
                		}else if(fieldObj.getType() == List.class) {
                			String value = cell.getStringCellValue();
                			List<ReportSapChargItemDto> items = JSON.parseArray(value).toJavaList(ReportSapChargItemDto.class);
                			BeanUtil.setFieldValue(dto, fieldName, items);
                		}else if(fieldObj.getType() == Boolean.class) {
                			Boolean value = cell.getBooleanCellValue();
                			BeanUtil.setFieldValue(dto, fieldName, value);
                		}else if(fieldObj.getType() == Boolean.class) {
                			Boolean value = cell.getBooleanCellValue();
                			BeanUtil.setFieldValue(dto, fieldName, value);
                		}
                	}
            	}
                dtoList.add(dto);
            }
            
            List<ReportSapGoodsmvt> reportSapGoodsmvtses = dtoList.stream().map(reportSapGoodsmvt -> fromDto(reportSapGoodsmvt)).collect(Collectors.toList());
            saveAll(reportSapGoodsmvtses);
        } catch (Exception e) {
            return e.getMessage();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "导入成功";
    }
	
	
	private String handleDataFromExcel(MultipartFile file) {
		InputStream fis = null;
        Workbook workBook;
        Cell cell = null;
        
        try {
            //获取一个绝对地址的流
            fis = file.getInputStream();
            //得到工作簿
            String fileName = file.getOriginalFilename();
            assert fileName != null;
            String name = ".xlsx";
            if (fileName.contains(name)) {
                workBook = new XSSFWorkbook(fis);
            } else {
                workBook = new HSSFWorkbook(fis);
            }
            //得到一个工作表
            Sheet sheet = workBook.getSheetAt(0);
            //获得表头
            Row rowHead = sheet.getRow(1);
            //判断表头是否正确
//            if (rowHead.getPhysicalNumberOfCells() != size) {
//                return "单元格数量不匹配";
//            }
            //获得数据的总行数
            int totalRowNum = sheet.getLastRowNum();
            if(totalRowNum < 2) {
            	return "不允许导入空白数据,请编辑后重新导入";
            }
            
            //List<ReportSapGoodsmvtDto> dtoList = new ArrayList<ReportSapGoodsmvtDto>();
            //获得所有数据
            for (int i = 2; i <= totalRowNum; i++) {
                //获得第i行对象
                Row row = sheet.getRow(i);
                if (row == null) {
                    break;
                }
                //获得获得第i行第0列的 String类型对象
                
                cell = row.getCell(0);
                String zuuid = cell.getStringCellValue();//外部系统KEY  zuuid

                cell = row.getCell(1);
                //CellType type = cell.getCellTypeEnum();
                
                
                double hs = cell.getNumericCellValue();//行数
                
                cell = row.getCell(2);
                String xxlx = cell.getStringCellValue();//消息类型
                
                cell = row.getCell(3);
                Date budat = cell.getDateCellValue();//过账日期
                
                cell = row.getCell(4);
                Date createDate = cell.getDateCellValue();//创建日期
                
                cell = row.getCell(5);
                
                double createTimeDouble = cell.getNumericCellValue();//创建时间
                
                long milliseconds = (long) (createTimeDouble * 24 * 60 * 60 * 1000);
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(milliseconds);
                calendar.setTimeZone(TimeZone.getTimeZone("Asia/ShangHai"));
                calendar.add(Calendar.HOUR_OF_DAY, 16);
                
                
                Date createTime = calendar.getTime();
                
                //System.out.println(DateUtil.formatDate(calendar.getTime(),DateUtil.longFormat));
                
                
                
//                // Excel时间起点为1900年，java.time起点为1970年，所以需要调整
//                LocalDateTime dateTime = LocalDateTime.of(1900, 1, 1, 0, 0);
//                dateTime = dateTime.plusDays((long) createTime);
//                System.out.println("转换后的日期和时间: " + dateTime);
//                // 如果需要考虑时区，可以进一步转换为ZonedDateTime
//                // ZoneId zoneId = ZoneId.systemDefault(); // 使用系统默认时区
//                // ZonedDateTime zonedDateTime = dateTime.atZone(zoneId);
//                
                

                cell = row.getCell(6);
                Date bldat = cell.getDateCellValue();//凭证日期
                
                cell = row.getCell(7);
                String ernam = cell.getStringCellValue();//创建人
                
                cell = row.getCell(8);
                String xblnr = cell.getStringCellValue();//参考

                cell = row.getCell(9);
                String frbnr = cell.getStringCellValue();//提货单
                
                cell = row.getCell(10);
                String bwart = cell.getStringCellValue();//移动类型
                
                
                cell = row.getCell(11);
                String kostl = cell.getStringCellValue();//成本中心
                
                cell = row.getCell(12);
                String aufnr = cell.getStringCellValue();//订单 SAP生产订单
                
                cell = row.getCell(13);
                String vbeln = cell.getStringCellValue();//采购凭证 销售订单

                cell = row.getCell(14);
                String posnr = cell.getStringCellValue();//项目

                cell = row.getCell(15);
                String ebeln = cell.getStringCellValue();//销售和分销凭证
                
                
                cell = row.getCell(16);
                String ebelp = cell.getStringCellValue();//项目(SD)
                
                cell = row.getCell(17);
                String rsnum = cell.getStringCellValue();//预留

                
                cell = row.getCell(18);
                String rspos = cell.getStringCellValue();//预定的项目编号
                
                cell = row.getCell(19);
                String werks = cell.getStringCellValue();//工厂
                
                cell = row.getCell(20);
                String lgort = cell.getStringCellValue();//存储地点
                
                cell = row.getCell(21);
                String matnr = cell.getStringCellValue();//存储地点
                
                
                cell = row.getCell(22);
                String charg = cell.getStringCellValue();//批次
                
                cell = row.getCell(23);
                double menge = cell.getNumericCellValue();//数量
                
                cell = row.getCell(24);
                String meins = cell.getStringCellValue();//基本计量单位

                cell = row.getCell(25);
                String umwrk = cell.getStringCellValue();//接收工厂
                
                cell = row.getCell(26);
                String umlgo = cell.getStringCellValue();//收货库存地点
                
                cell = row.getCell(27);
                String umcha = cell.getStringCellValue();//收货批次
                
                cell = row.getCell(28);
                String sgtxt = cell.getStringCellValue();//文本
                
                
                cell = row.getCell(29);
                String zfcpFlag = cell.getStringCellValue();//副产品标识

                cell = row.getCell(30);
                String other1 = cell.getStringCellValue();//次数（发料、产出等）
                
                
                cell = row.getCell(31);
                String czlx = cell.getStringCellValue();//操作类型
                
                
                cell = row.getCell(32);
                String mblnr = cell.getStringCellValue();//物料凭证
                
                cell = row.getCell(33);
                String wlpznf = cell.getStringCellValue();//物料凭证的年份
                
                cell = row.getCell(34);
                String xxwb = cell.getStringCellValue();//消息文本




                
                if(StringUtils.isNotBlank(xxlx) && (xxlx.equals("S") || xxlx.equals("W"))) {
                	//成功
                	ReportSapGoodsmvt mvt = findByMblnr(mblnr);
                	if(mvt == null) {
                		mvt = new ReportSapGoodsmvt();
                	}
                	mvt.setStatus(true);
                	mvt.setSapmblnr(mblnr);
                	
                	mvt.setZuuid(zuuid);
                	
                	Date time = DateUtil.toDate(createTime, "HH:mm:ss");
//                	Date time = new Date();
                	Calendar timeCa = Calendar.getInstance();
                	timeCa.setTime(time);
                	
                	
                	Calendar ca = Calendar.getInstance();
                	ca.setTime(budat);
                	ca.set(Calendar.HOUR_OF_DAY, timeCa.get(Calendar.HOUR_OF_DAY));
                	ca.set(Calendar.MINUTE, timeCa.get(Calendar.MINUTE));
                	ca.set(Calendar.SECOND, timeCa.get(Calendar.SECOND));
                	
                	mvt.setBudat(ca.getTime());
                	
                	ca.setTime(bldat);
                	ca.set(Calendar.HOUR_OF_DAY, timeCa.get(Calendar.HOUR_OF_DAY));
                	ca.set(Calendar.MINUTE, timeCa.get(Calendar.MINUTE));
                	ca.set(Calendar.SECOND, timeCa.get(Calendar.SECOND));
                	
                	mvt.setBldat(ca.getTime());
                	
                	
                	mvt.setErnam(ernam);
                	mvt.setXblnr(xblnr);
                	mvt.setFrbnr(frbnr);
                	mvt.setBwart(bwart);
                	mvt.setKostl(kostl);
                	mvt.setAufnr(aufnr);
                	mvt.setVbeln(vbeln);
                	mvt.setPosnr(posnr);
                	mvt.setEbeln(ebeln);
                	mvt.setEbelp(ebelp);
                	mvt.setRsnum(rsnum);
                	mvt.setRspos(rspos);
                	mvt.setWerks(werks);
                	mvt.setLgort(lgort);
                	mvt.setMatnr(matnr);
                	mvt.setCharg(charg);
                	mvt.setMenge(String.format("%.3f", menge));
                	mvt.setMeins(meins);
                	mvt.setUmwrk(umwrk);
                	mvt.setUmlgo(umlgo);
                	mvt.setUmcha(umcha);
                	mvt.setSgtxt(sgtxt);
                	mvt.setZfcpFlag(zfcpFlag);
                	mvt.setOther1(other1);
                	mvt.setRemark(xxwb);
                	mvt.setMblnr(mblnr);
                	
                	ca.setTime(createDate);
                	ca.set(Calendar.HOUR_OF_DAY, timeCa.get(Calendar.HOUR_OF_DAY));
                	ca.set(Calendar.MINUTE, timeCa.get(Calendar.MINUTE));
                	ca.set(Calendar.SECOND, timeCa.get(Calendar.SECOND));
                	
                	mvt.setCreateDate(ca.getTime());
                	mvt.setSendType("VERIFY");
                	
                	superSaveOrUpdate(mvt);
                }
                
            }

        } catch (Exception e) {
            return e.getMessage();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "导入成功";
	}
	
	
	public static Date convertDoubleToDate(double date) {
        // Excel的日期起始点是1900年，所以需要加上这个偏移量
        long days = (long) date;
        long milliseconds = (long) (date * 24 * 60 * 60 * 1000); // 25567是1900年1月1日
 
        // 小数部分代表过去的24小时，需要转换为毫秒数
        double fraction = date - days;
        long millisecondsInADay = 24 * 60 * 60 * 1000;
        long additionalMillis = (long) (fraction * millisecondsInADay);
 
        milliseconds += additionalMillis;
 
        return new Date(milliseconds);
    }
	
	
	private ReportSapGoodsmvt findByMblnr(String mblnr) {
		List<ReportSapGoodsmvt> list = dao.findByMblnr(mblnr);
		if(list.size()>0) {
			return list.get(0);
		}
		return null;
	}

	private List<ReportSapGoodsmvt> findByBwartAndProcNameAndStatus(String bwart, String procName,Boolean status) {
		return dao.findByBwartAndProcNameAndStatus(bwart,procName,status);
	}



	@Override
	public List<Map<Object,Object>> ljStatistics() {
		List<Map<Object,Object>> list = dao.ljStatistics();
		return list;
	}



	@Override
	public List<Map<Object, Object>> djshStatistics(StatisticsDto dto) {
		List<Map<Object,Object>> list = dao.djshStatistics(dto.getStartDate(),dto.getEndDate(),dto.getAufnr(),dto.getMatnr(),dto.getCharg());
		return list;
	}



	@Override
	public List<Map<Object, Object>> jdxhStatistics(StatisticsDto dto) {
		List<Map<Object,Object>> list = dao.jdxhStatistics(dto.getStartDate(),dto.getEndDate(),dto.getAufnr(),dto.getMatnr(),dto.getCharg());
		return list;
	}



	@Override
	public List<Map<Object, Object>> jdshStatistics(StatisticsDto dto) {
		List<Map<Object,Object>> list = dao.jdshStatistics(dto.getStartDate(),dto.getEndDate(),dto.getAufnr(),dto.getMatnr(),dto.getCharg());
		return list;
	}



	@Override
	public List<Map<Object, Object>> dpxhStatistics(StatisticsDto dto) {
		List<Map<Object,Object>> list = dao.dpxhStatistics(dto.getStartDate(),dto.getEndDate(),dto.getAufnr(),dto.getMatnr(),dto.getCharg());
		return list;
	}



	@Override
	public ReportSapGoodsmvt findByZuuidOrMblnr(String mBLNR) {
		List<ReportSapGoodsmvt> list = dao.findByZuuidOrMblnr(mBLNR);
		if(list.size()>0) {
			return list.get(0);
		}
		return null;
	}

	private ReportSapGoodsmvt findLastByMd5Value(String md5Value) {
		return dao.findLastByMd5Value(md5Value);
	}

	@Override
	public Double getSumNoSendSapLog(String aufnr) {
		return dao.getSumNoSendSapLog(aufnr);
	}

	@Override
	public List<ReportSapGoodsmvt> findAllOrderMatnrChargLgort(String AUFNR) {
		return dao.findAllOrderMatnrChargLgort(AUFNR);
	}

	@Override
	public Long getChargLengthCount(String aUFNR) {
		return dao.getChargLengthCount(aUFNR);
	}

	@Override
	public Long getChargeOffMengeCount(String aUFNR) {
		return dao.getChargeOffMengeCount(aUFNR);
	}

	@Override
	public Long getRsnumNullCount(String aUFNR) {
		return dao.getRsnumNullCount(aUFNR);
	}

	@Override
	public ReportSapGoodsmvt getByMblnr(String mblnr) {
		List<ReportSapGoodsmvt> list = dao.findByMblnr(mblnr);
		if(list.size()>0) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public List<ReportSapGoodsmvt> findByBwartAndLgortAndMatnrAndChargAndMengeAndStatus(String bwart, String lgort, String matnr, String charg, String menge, boolean status) {
		return dao.findByBwartAndLgortAndMatnrAndChargAndMengeAndStatus(bwart,lgort,matnr,charg,menge,status);
	}
}
