package com.steerinfo.ems.trmcalpointvalue.service.impl;

import com.steerinfo.framework.mapper.IBaseMapper;
import com.steerinfo.framework.service.impl.BaseServiceImpl;
import com.steerinfo.ems.trmcalpointvalue.model.TRmCalpointValue;
import com.steerinfo.auth.utils.JwtUtil;
import com.steerinfo.ems.cordasconfiguration.mapper.CordasConfigurationMapper;
import com.steerinfo.ems.cordasconfiguration.model.CordasConfiguration;
import com.steerinfo.ems.emscalpointvalue.mapper.EmsCalpointValueMapper;
import com.steerinfo.ems.emscalpointvalue.model.EmsCalpointValue;
import com.steerinfo.ems.formula.service.IFormulaService;
import com.steerinfo.ems.mesemsdieseloil.service.IMesEmsDieseloilService;
import com.steerinfo.ems.trmcalpoint.mapper.TRmCalpointMapper;
import com.steerinfo.ems.trmcalpoint.model.TRmCalpoint;
import com.steerinfo.ems.trmcalpointexvalue.model.TRmCalpointExValue;
import com.steerinfo.ems.trmcalpointexvalue.service.ITRmCalpointExValueService;
import com.steerinfo.ems.trmcalpointvalue.mapper.TRmCalpointValueMapper;
import com.steerinfo.ems.trmcalpointvalue.service.ITRmCalpointValueService;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * TRmCalpointValue服务实现：
 * @author generator
 * @version 1.0-SNAPSHORT 2019-10-17 03:55
 * 类描述
 * 修订历史：
 * 日期：2019-10-17
 * 作者：generator
 * 参考：
 * 描述：TRmCalpointValue服务实现
 * @see null
 * @Copyright 湖南视拓信息技术股份有限公司. All rights reserved.
 */
@Service(value = "tRmCalpointValueService")
public class TRmCalpointValueServiceImpl extends BaseServiceImpl<TRmCalpointValue, HashMap<String, Object>> implements ITRmCalpointValueService {
	
	private static final Logger logger = LoggerFactory.getLogger(TRmCalpointValueServiceImpl.class);

	@Autowired
    private JdbcTemplate jdbcTemplate;
	
    @Autowired
    private TRmCalpointValueMapper tRmCalpointValueMapper;
    
    @Autowired
    private TRmCalpointMapper tRmCalpointMapper;
    
    @Autowired
    private IFormulaService formulaService;
    
    @Autowired
    private CordasConfigurationMapper cordasConfigurationMapper;
    
    @Autowired
    private EmsCalpointValueMapper emsCalpointValueMapper;
    
    @Autowired
    ITRmCalpointExValueService tRmCalpointExValueService;
    
    @Autowired
    IMesEmsDieseloilService mesEmsDieseloilService;

    @Override
    protected IBaseMapper<TRmCalpointValue, HashMap<String, Object>> getMapper() {
        return tRmCalpointValueMapper;
    }

	@Override
	//@Transactional(rollbackFor=Exception.class)
	public void statData(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int dm = calendar.get(Calendar.DAY_OF_MONTH);
		int dy = calendar.get(Calendar.DAY_OF_YEAR);
		String today = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
		String thisMonth = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
		String thisYear = calendar.get(Calendar.YEAR) + "";
		String lastYear = (calendar.get(Calendar.YEAR)-1) + "";
		calendar.add(Calendar.DAY_OF_YEAR, -1); // 减1天获得昨日日期
		String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
		calendar.add(Calendar.DAY_OF_YEAR, 1); 
		calendar.add(Calendar.MONTH, -1); // 减1月获得上月
		String lastMonth = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
		
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("useflag", "1");
		// 查询需要统计的计量点信息
		List<TRmCalpoint> l = tRmCalpointMapper.selectCalpoints(m);
		if(l!=null && l.size()>0){
			for(TRmCalpoint tRmCalpoint : l){
				String itemtype = tRmCalpoint.getItemtype(); // 类型 AUTO:自动，MANUAL:手抄，VIRTUAL:虚拟
				String mintimegranid = tRmCalpoint.getMintimegranid()==null? "DAY" : tRmCalpoint.getMintimegranid();
				// 最小粒度日时间粒度数据
				if(mintimegranid.equalsIgnoreCase("DAY") || mintimegranid.equalsIgnoreCase("SHIFT")){
					// 手动提前生成时间粒度
					String dclk = itemtype.equalsIgnoreCase("MANUAL")?today:yesterday;
					restatCalData(tRmCalpoint, dclk, "DAY", "系统");
				}
				// 月时间粒度数据，每月统计上月数据
				if (dm == 1 && !mintimegranid.equalsIgnoreCase("YEAR")) {
					// 手动提前生成时间粒度
					String mclk = itemtype.equalsIgnoreCase("MANUAL")?thisMonth:lastMonth;
					restatCalData(tRmCalpoint, mclk, "MONTH", "系统");
				}
				// 年时间粒度数据，每年第一天统计去年数据
				if (dy == 1) {
					// 手动提前生成时间粒度
					String yclk = itemtype.equalsIgnoreCase("MANUAL")?thisYear:lastYear;
					restatCalData(tRmCalpoint, yclk, "YEAR", "系统");
				}
			}
			logger.info(new SimpleDateFormat("yyyy-MM-dd").format(date) + " 计量点定时统计数据任务执行完毕~");
		}
	}

	@Override
	public TRmCalpointValue modifyAndCompute(TRmCalpointValue tRmCalpointValue) {
		tRmCalpointValueMapper.updateByPrimaryKeySelective(tRmCalpointValue);
		String itemid = tRmCalpointValue.getItemid();
		String clock = tRmCalpointValue.getClock();
		String timegranid = tRmCalpointValue.getTimegranid();
		// 重新计算
		formulaService.reCalculate(itemid, clock, timegranid, clock);
		return tRmCalpointValueMapper.selectByPrimaryKey(tRmCalpointValue.getId());
	}

	@Override
	public void statDataShift(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, -8); // 减8小时获得需要统计的上一个班的时间
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH");
		int dh = cal.get(Calendar.HOUR_OF_DAY);
		if(dh%8==0){
			logger.info("节点时间不统计数据，以防数据出错");
			return;
		}
		// 统计日
		String statTim = new SimpleDateFormat("yyyy-MM-dd ").format(cal.getTime());
		// clock 格式：yyyy-MM-dd HH
		String clock = statTim+String.format("%02d", (dh/8)*8+8);
		// 期初时间
		String starth = statTim+String.format("%02d", (dh/8)*8);
		// 期末时间
		String endh = "";
		try {
			endh = sf.format(sf.parse(clock));
		} catch (Exception e) {
			logger.error("日期格式错误");
			return;
		}
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("useflag", "1");
		m.put("mintimegranid", "SHIFT");
		// 查询需要统计的计量点信息
		List<TRmCalpoint> l = tRmCalpointMapper.selectCalpoints(m);
		if(l!=null && l.size()>0){
			for(TRmCalpoint tRmCalpoint : l){
				String itemtype = tRmCalpoint.getItemtype(); // 类型 AUTO:自动，MANUAL:手抄，VIRTUAL:虚拟
				String itemid = tRmCalpoint.getItemid();
				String itemname = tRmCalpoint.getItemname();
				String tagTable = tRmCalpoint.getTagTable()==null? "" :tRmCalpoint.getTagTable().trim(); // 小时表
				String tagCol = tRmCalpoint.getTagCol()==null? "" :tRmCalpoint.getTagCol().trim(); // 小时表字段
				String energytypeid = tRmCalpoint.getEnergytypeid(); // 能介大类
				String tagBadStr = tRmCalpoint.getTagBadSymbol()==null? "-1" : tRmCalpoint.getTagBadSymbol();
				Double mod = tRmCalpoint.getTagModulus() == null? 1d : tRmCalpoint.getTagModulus().doubleValue(); // 倍率
				Double tagBad = -1d; // 异常点标签(读表异常时候插入的值)
				try {
					tagBad = Double.parseDouble(tagBadStr);
				} catch (NumberFormatException e) {
					logger.error("计量点" + itemid + "的tag_bad_symbol值格式应该为负数，当前值为：" + tagBadStr);
					tagBad = -1d;
				}
				if(itemtype.equalsIgnoreCase("AUTO") && (tagTable.isEmpty() || tagCol.isEmpty())){
					logger.error("计量点的数据表与数据列信息不完整！itemid:" + itemid);
					// 班时间粒度该项目数据是否已经存在
					String sql = "select count(1) from T_RM_CALPOINT_VALUE where clock = ? and timegranid='SHIFT' and itemid = ?";
					int c = jdbcTemplate.queryForObject(sql, new Object[]{clock,itemid}, Integer.class);
					if(c>0){
						logger.error(clock + "-itemid:" + itemid + " 已存在数据。");
					}else{
						TRmCalpointValue t = new TRmCalpointValue();
						t.setClock(clock);
						t.setTimegranid("SHIFT");
						t.setItemid(itemid);
						t.setItemname(itemname);
						t.setApportvalue(BigDecimal.ZERO); // 最终值
						t.setActualvalue(BigDecimal.ZERO); // 计算值
						t.setCorrectvalue(BigDecimal.ZERO); // 修正值
						t.setMintvalue(BigDecimal.ZERO);
						t.setMendvalue(BigDecimal.ZERO);
						t.setSumvalue(BigDecimal.ZERO);
						t.setBz("-1：请配置数据表与数据列");
						t.setRecTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
						t.setUpman("系统");
						tRmCalpointValueMapper.insertSelective(t);
						//throw new RuntimeException("请先在计量点信息维护中配置计量点的数据表与数据列！");
						continue;
					}
				}
				Short digits = tRmCalpoint.getDigits() == null ? 4 : tRmCalpoint.getDigits();
				Short digits2 = tRmCalpoint.getMeterScale() == null ? 4 : tRmCalpoint.getMeterScale(); // 准点值精度
				Double qc = 0d; // 仪表期初值
				Double qm = 0d; // 仪表期末值
				
				// 班时间粒度该项目数据是否已经存在
				String sql = "select count(1) from T_RM_CALPOINT_VALUE where clock = ? and timegranid='SHIFT' and itemid = ?";
				int c = jdbcTemplate.queryForObject(sql, new Object[]{clock,itemid}, Integer.class);
				if(c>0){
					logger.error(clock + "-itemid:" + itemid + " 已存在数据。");
				}else{
					TRmCalpointValue t = new TRmCalpointValue();
					t.setClock(clock);
					t.setTimegranid("SHIFT");
					t.setItemid(itemid);
					t.setItemname(itemname);
					t.setApportvalue(BigDecimal.ZERO); // 最终值
					t.setCorrectvalue(BigDecimal.ZERO); // 修正值
					t.setActualvalue(BigDecimal.ZERO); // 计算值
					if(itemtype.equalsIgnoreCase("AUTO") && !tagTable.equalsIgnoreCase("MES_EMS_DIESELOIL")){
						// 获取仪表期初、期末值
						sql = "select nvl(round("+tagCol+", "+digits2+"),0) from "+tagTable + "_ORG where clock = ?";
						try {
							qc = jdbcTemplate.queryForObject(sql, new Object[]{starth}, Double.class);
							if(qc!=null && Math.abs(qc) > Integer.MAX_VALUE){
								t.setBz("仪表期初值异常：" + qc);
								qc = tagBad;
							}
						} catch(DataAccessException e) {
							logger.error(starth + "-itemid:" + itemid + " 没有仪表期初值。");
							qc = tagBad;
						}
						try {
							qm = jdbcTemplate.queryForObject(sql, new Object[]{endh}, Double.class);
							if(qm!=null && Math.abs(qm) > Integer.MAX_VALUE){
								t.setBz("仪表期末值异常：" + qm);
								qm = tagBad;
							}
						} catch(DataAccessException e) {
							logger.error(endh + "-itemid:" + itemid + " 没有仪表期末值。");
							qm = tagBad;
						}
						t.setMintvalue(qc==null?null:new BigDecimal(Double.toString(qc)));
						t.setMendvalue(qm==null?null:new BigDecimal(Double.toString(qm)));
						if(qm == tagBad || qc == tagBad || qc == 0d || new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc))).doubleValue()<0
								|| !energytypeid.equalsIgnoreCase("E")){
							sql = "select nvl(round(sum("+tagCol+")*"+mod+", "+digits+"),0) from "+tagTable+" where clock >= ? and clock<?";
							Double d = 0d;
							try {
								d = jdbcTemplate.queryForObject(sql, new Object[]{starth,endh}, Double.class);
								if(d!=null && Math.abs(d) > Integer.MAX_VALUE){
									t.setBz("仪表数值异常：" + d);
									d = 0d;
								}
							}catch(Exception e) {
								e.printStackTrace();
								logger.error(endh + "-itemid:" + itemid + " 取值错误, tagTable-" + tagTable + ",tagCol-" + tagCol);
								continue;
							}
							t.setApportvalue(d==null?null:new BigDecimal(Double.toString(d))); // 最终值
							t.setActualvalue(d==null?null:new BigDecimal(Double.toString(d))); // 计算值
						}else{
							// 仪表期末值 - 仪表期初值
							BigDecimal ap = new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc))).multiply(new BigDecimal(mod)).setScale(digits, BigDecimal.ROUND_HALF_UP);
							t.setApportvalue(ap); // 最终值
							t.setActualvalue(ap); // 计算值
						}
					}else if(itemtype.equalsIgnoreCase("MANUAL")){ // 手动
						// 当前小时数
						int h = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
						// clock 格式：yyyy-MM-dd HH，手动计量点提前生成数据
						String clk = new SimpleDateFormat("yyyy-MM-dd ").format(new Date())+String.format("%02d", (h/8)*8+8);
						t.setClock(clk);
					}else if(itemtype.equalsIgnoreCase("VIRTUAL")){
						// 获得计算公式
						String formula = formulaService.getFormula(itemid,clock);
						// 根据公式获取计算值
						Double dval = formulaService.getValByFormula(formula, "SHIFT", clock, digits, 0);
						if(dval < 0){
							logger.error(clock + "-itemid:" + itemid + " 计算公式错误。");
						}
						t.setApportvalue(new BigDecimal(Double.toString(dval))); // 最终值
						t.setActualvalue(new BigDecimal(Double.toString(dval))); // 计算值
					}
					t.setRecTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
					t.setUpman("系统");
					tRmCalpointValueMapper.insertSelective(t);
				}
			}
		}
		logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date) + " 计量点班粒度定时统计数据任务执行完毕~");
	}

	@Override
	public String restatAllData(String clock, String timegranid) {
		String opuser = JwtUtil.getUseridByToken();
		// 班粒度，只重新计算当月班数据
		if(timegranid.equalsIgnoreCase("SHIFT")){
			Date startDay = new Date();
			Date endDay = new Date();
			SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH");
			try {
				startDay = sf.parse(clock);
			} catch (Exception e) {
				return "日期格式错误";
			}
			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.HOUR_OF_DAY, -1);
			cal.add(Calendar.MINUTE, -1);
			
			// 当月，统计最后时间为昨天
			if(new SimpleDateFormat("yyyy-MM").format(cal.getTime()).equals(clock.substring(0, 7))){
				endDay = cal.getTime();
			}else{
				// 非当月，统计到下月初
				Calendar c = Calendar.getInstance();
				c.setTime(startDay);
				c.set(Calendar.DAY_OF_MONTH, 1);
				c.add(Calendar.MONTH, 1);
				c.set(Calendar.HOUR_OF_DAY, 0);
				endDay = c.getTime();
			}
			while(!startDay.after(endDay)){
				// 统计结束时间 
				String clk = sf.format(startDay);
				int st = Integer.valueOf(clk.substring(11));
				// 0点数据转成班记录24点，clock
				if(st == 0){
					clk = sf.format(new Date(startDay.getTime() - 1000l)).substring(0, 11) + 24;
				}
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("useflag", "1");
				m.put("mintimegranid", "SHIFT");
				// 查询需要统计的计量点信息
				List<TRmCalpoint> l = tRmCalpointMapper.selectCalpoints(m);
				if(l!=null && l.size()>0){
					for(TRmCalpoint tRmCalpoint : l){
						restatCalData(tRmCalpoint, clk, "SHIFT", opuser);
					}
				}
				startDay = new Date(startDay.getTime() + 8*3600*1000L);
			}
		}else if(timegranid.equalsIgnoreCase("DAY")){ // 重新计算日、月、年粒度数据
			Date startDay = null; // 计算开始日期
			Date endDay = null; // 计算结束日期
			try {
				startDay = new SimpleDateFormat("yyyy-MM-dd").parse(clock);
			} catch (ParseException e) {
				return "日期格式错误";
			}
			// 最后可以统计的日期
			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.HOUR_OF_DAY, -1);
			cal.add(Calendar.MINUTE, -1);
			// 当月，统计最后时间为昨天
			if(new SimpleDateFormat("yyyy-MM").format(cal.getTime()).equals(clock.substring(0, 7))){
				endDay = cal.getTime();
			}else{
				// 非当月，统计到月底
				Calendar c = Calendar.getInstance();
				c.setTime(startDay);
				c.set(Calendar.DAY_OF_MONTH, 1);
				c.add(Calendar.MONTH, 1);
				c.add(Calendar.DAY_OF_YEAR, -1);
				endDay = c.getTime();
			}
			// 统计开始日期
			Calendar sta = Calendar.getInstance();
			sta.setTime(startDay);
			// 月粒度统计
			int startMonth = sta.get(Calendar.MONTH)+1;
			int endMonth = 12;
			// 如果是今年，计算最后月份为上月
			if(sta.get(Calendar.YEAR) ==  cal.get(Calendar.YEAR)){
				endMonth = cal.get(Calendar.MONTH);
			}
			// 查询需要统计的计量点信息,最小粒度为班和日的
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("useflag", "1");
			m.put("mintimegranid", "SHIFT");
			List<TRmCalpoint> l = tRmCalpointMapper.selectCalpoints(m);
			m.put("mintimegranid", "DAY");
			l.addAll(tRmCalpointMapper.selectCalpoints(m));
			// 重新计算日数据
			while(!startDay.after(endDay)){
				String clk = new SimpleDateFormat("yyyy-MM-dd").format(startDay);
				for(TRmCalpoint tRmCalpoint : l){
					restatCalData(tRmCalpoint, clk, "DAY", opuser);
				}
				startDay = new Date(startDay.getTime() + 3600*24*1000L);
			}
			// 重新计算月数据，主要修改月累积值
			while(startMonth <= endMonth){
				String clk = sta.get(Calendar.YEAR) + "-" + startMonth;
				if(startMonth < 10){
					clk = sta.get(Calendar.YEAR) + "-0" + startMonth;
				}
				for(TRmCalpoint tRmCalpoint : l){
					restatCalData(tRmCalpoint, clk, "MONTH", opuser);
				}
				startMonth++;
			}
			// 不是今年，重新计算年数据
			if(sta.get(Calendar.YEAR) !=  cal.get(Calendar.YEAR)){
				String clk = sta.get(Calendar.YEAR) + "";
				for(TRmCalpoint tRmCalpoint : l){
					restatCalData(tRmCalpoint, clk, "YEAR", opuser);
				}
			}
		}else if(timegranid.equalsIgnoreCase("MONTH")){
			Date startDay = null; // 计算开始日期
			try {
				startDay = new SimpleDateFormat("yyyy-MM").parse(clock);
			} catch (ParseException e) {
				return "日期格式错误";
			}
			// 最后可以统计的日期
			Calendar cal = Calendar.getInstance();
			cal.add(Calendar.HOUR_OF_DAY, -1);
			cal.add(Calendar.MINUTE, -1);
			// 统计开始日期
			Calendar sta = Calendar.getInstance();
			sta.setTime(startDay);
			// 月粒度统计
			int startMonth = sta.get(Calendar.MONTH)+1;
			int endMonth = 12;
			// 如果是今年，计算最后月份为上月
			if(sta.get(Calendar.YEAR) ==  cal.get(Calendar.YEAR)){
				endMonth = cal.get(Calendar.MONTH);
			}
			// 查询需要统计的计量点信息,最小粒度为班、日和年的
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("useflag", "1");
			m.put("mintimegranid", "SHIFT");
			List<TRmCalpoint> l = tRmCalpointMapper.selectCalpoints(m);
			m.put("mintimegranid", "DAY");
			l.addAll(tRmCalpointMapper.selectCalpoints(m));
			m.put("mintimegranid", "MONTH");
			l.addAll(tRmCalpointMapper.selectCalpoints(m));
			// 重新计算月数据，主要修改月累积值
			while(startMonth <= endMonth){
				String clk = sta.get(Calendar.YEAR) + "-" + startMonth;
				if(startMonth < 10){
					clk = sta.get(Calendar.YEAR) + "-0" + startMonth;
				}
				for(TRmCalpoint tRmCalpoint : l){
					restatCalData(tRmCalpoint, clk, "MONTH", opuser);
				}
				startMonth++;
			}
			// 不是今年，重新计算年数据
			if(sta.get(Calendar.YEAR) !=  cal.get(Calendar.YEAR)){
				String clk = sta.get(Calendar.YEAR) + "";
				for(TRmCalpoint tRmCalpoint : l){
					restatCalData(tRmCalpoint, clk, "YEAR", opuser);
				}
			}
		}else if(timegranid.equalsIgnoreCase("YEAR")){
			// 只计算最小粒度为年的
			// 查询需要统计的计量点信息,最小粒度年的
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("useflag", "1");
			m.put("mintimegranid", "YEAR");
			List<TRmCalpoint> l = tRmCalpointMapper.selectCalpoints(m);
			for(TRmCalpoint tRmCalpoint : l){
				restatCalData(tRmCalpoint, clock, "YEAR", opuser);
			}
		}
		return "";
	}

	@Override
	public String restatCalData(TRmCalpoint tRmCalpoint, String clock, String timegranid, String updateUser) {
		String res= "";
		String mintimegranid = tRmCalpoint.getMintimegranid()==null?"DAY":tRmCalpoint.getMintimegranid(); // 最小时间粒度
		String itemtype = tRmCalpoint.getItemtype(); // 类型 AUTO:自动，MANUAL:手抄，VIRTUAL:虚拟
		String itemid = tRmCalpoint.getItemid();
		String itemname = tRmCalpoint.getItemname();
		String energytypeid = tRmCalpoint.getEnergytypeid(); // 能介大类
		String tagTable = tRmCalpoint.getTagTable()==null? "" :tRmCalpoint.getTagTable().trim(); // 小时表
		String tagCol = tRmCalpoint.getTagCol()==null? "" :tRmCalpoint.getTagCol().trim(); // 小时表字段
		String tagBadStr = tRmCalpoint.getTagBadSymbol()==null? "-1" : tRmCalpoint.getTagBadSymbol();
		Short digits = tRmCalpoint.getDigits() == null ? 4 : tRmCalpoint.getDigits();
		Short digits2 = tRmCalpoint.getMeterScale() == null ? 4 : tRmCalpoint.getMeterScale(); // 准点值精度
		Double qc = 0d; // 仪表期初值
		Double qm = 0d; // 仪表期末值
		Double mod = tRmCalpoint.getTagModulus() == null? 1d : tRmCalpoint.getTagModulus().doubleValue(); // 倍率
		Double tagBad = -1d; // 异常点标签(读表异常时候插入的值)
		Double maxval = 0d;
		Double minval = 0d;
		updateUser = updateUser==null || updateUser.isEmpty()?JwtUtil.getUseridByToken():updateUser;
		try {
			tagBad = Double.parseDouble(tagBadStr);
		} catch (NumberFormatException e) {
			logger.error("计量点" + itemid + "的tag_bad_symbol值格式应该为负数，当前值为：" + tagBadStr);
			tagBad = -1d;
		}
		try {
			maxval = tRmCalpoint.getMaxVal()==null || tRmCalpoint.getMaxVal().isEmpty()?0:Double.valueOf(tRmCalpoint.getMaxVal());
			minval = tRmCalpoint.getMinVal()==null || tRmCalpoint.getMinVal().isEmpty()?0:Double.valueOf(tRmCalpoint.getMinVal());
		} catch (NumberFormatException e) {
			logger.error("计量点" + itemid + "的最大值最小值格式错误，当前最大值为：" + tRmCalpoint.getMaxVal() + ",最小值为："+ tRmCalpoint.getMinVal());
			maxval = 0d;
			minval = 0d;
		}
		HashMap<String, Object> id = new HashMap<String, Object>();
		id.put("clock", clock);
		id.put("timegranid", timegranid);
		id.put("itemid", itemid);
		String sql = "";
		// 如果有人工录入数据，以人工录入数据为准
		HashMap<String, Object> cid = new HashMap<String, Object>();
		cid.put("clock", clock);
		cid.put("itemid", itemid);
		EmsCalpointValue ecv = emsCalpointValueMapper.selectByPrimaryKey(cid);
		// 获取原数据
		TRmCalpointValue t = tRmCalpointValueMapper.selectByPrimaryKey(id);
		// 自动上传计量点
		if(itemtype.equalsIgnoreCase("AUTO")){
			if(tagTable.equalsIgnoreCase("MES_EMS_DIESELOIL")){ // 柴油特殊处理，只重新计算年数据
				if(!timegranid.equalsIgnoreCase("YEAR")){
					mesEmsDieseloilService.reCalData2(clock, tRmCalpoint);
					return "";
				}else{
					BigDecimal acb = BigDecimal.ZERO;// 计算值
					// 年计算值等于月最终值之和
					sql = "select round(sum(apportvalue), "+digits+") apportvalue "
							+ "from T_RM_CALPOINT_VALUE where itemid = ? and timegranid='MONTH' and clock like ?||'%'";
					Double actval = jdbcTemplate.queryForObject(sql, new Object[]{itemid,clock}, Double.class);
					acb = actval==null?BigDecimal.ZERO:new BigDecimal(Double.toString(actval)).setScale(digits, BigDecimal.ROUND_HALF_UP);
					if(t!=null){
						t.setActualvalue(acb);
						if(t.getCorrectvalue()!=null){
							t.setApportvalue(acb.add(t.getCorrectvalue().setScale(digits, BigDecimal.ROUND_HALF_UP)));
						}else{
							t.setApportvalue(acb);
						}
						t.setUpman(updateUser);
						t.setUptime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
						tRmCalpointValueMapper.updateByPrimaryKeySelective(t);
					}else{
						// 数据不存在，新增
						t = new TRmCalpointValue();
						t.setActualvalue(acb); // 计算值
						t.setClock(clock);
						t.setTimegranid(timegranid);
						t.setItemid(itemid);
						t.setItemname(itemname);
						t.setApportvalue(acb); // 最终值
						t.setCorrectvalue(BigDecimal.ZERO); // 修正值
						t.setCrman(updateUser);
						t.setRecTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
						tRmCalpointValueMapper.insertSelective(t);
					}
				}
				return res;
			}
			String qck = ""; // 期初仪表时间点
			String qmk = ""; // 期末仪表时间点
			if(timegranid.equalsIgnoreCase("SHIFT")){
				Date end = new Date();
				SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH");
				try {
					end = sf.parse(clock);
				} catch (Exception e) {
					return "日期格式错误";
				}
				qmk = sf.format(end);
				Calendar ca = Calendar.getInstance();
				ca.setTime(end);
				ca.add(Calendar.HOUR_OF_DAY, -8);
				qck = sf.format(ca.getTime());
			}else if(timegranid.equalsIgnoreCase("DAY")){
				qck = clock + " 00";
				SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH");
				Date end = new Date();
				try {
					end = sf.parse(qck);
				} catch (Exception e) {
					return "日期格式错误";
				}
				Calendar ca = Calendar.getInstance();
				ca.setTime(end);
				ca.add(Calendar.DAY_OF_YEAR, 1);
				qmk = sf.format(ca.getTime());
			}else if(timegranid.equalsIgnoreCase("MONTH")){
				qck = clock + "-01 00";
				SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH");
				Date end = new Date();
				try {
					end = sf.parse(qck);
				} catch (Exception e) {
					return "日期格式错误";
				}
				Calendar ca = Calendar.getInstance();
				ca.setTime(end);
				ca.add(Calendar.MONTH, 1);
				qmk = sf.format(ca.getTime());
			}else if(timegranid.equalsIgnoreCase("YEAR")){
				qck = clock + "-01-01 00";
				SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH");
				Date end = new Date();
				try {
					end = sf.parse(qck);
				} catch (Exception e) {
					return "日期格式错误";
				}
				Calendar ca = Calendar.getInstance();
				ca.setTime(end);
				ca.add(Calendar.YEAR, 1);
				qmk = sf.format(ca.getTime());
			}
			BigDecimal acb = BigDecimal.ZERO;// 计算值
			BigDecimal qcb = BigDecimal.ZERO;// 期初值
			BigDecimal qmb = BigDecimal.ZERO;// 期末值
			String bz = ""; // 备注
			if(!tagTable.isEmpty() && !tagCol.isEmpty()){
				// 获取仪表期初、期末值、计算值
				sql = "select nvl(round("+tagCol+", "+digits2+"),0) from "+tagTable + "_ORG where clock = ?";
				try {
					qc = jdbcTemplate.queryForObject(sql, new Object[]{qck}, Double.class);
					if(qc!=null && Math.abs(qc) > Integer.MAX_VALUE){
						bz = "仪表期初值异常：" + qc;
						qc = tagBad;
					}
				} catch(DataAccessException e) {
					logger.error(qck + "-itemid:" + itemid + " 没有仪表期初值。");
					qc = tagBad;
				}
				try {
					qm = jdbcTemplate.queryForObject(sql, new Object[]{qmk}, Double.class);
					if(qm!=null && Math.abs(qm) > Integer.MAX_VALUE){
						if(bz.length()>0){
							bz = bz + ", ";
						}
						bz += "仪表期末值异常：" + qm;
						qm = tagBad;
					}
				} catch(DataAccessException e) {
					res = qmk + "-itemid:" + itemid + " 没有仪表期末值。";
					logger.error(qmk + "-itemid:" + itemid + " 没有仪表期末值。");
					qm = tagBad;
				}
				// 计算值由小时表统计
				if(mintimegranid.equalsIgnoreCase(timegranid) || timegranid.equalsIgnoreCase("DAY") || timegranid.equalsIgnoreCase("SHIFT")){
					if (qm == tagBad || qc == tagBad || qc == 0 || new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc))).doubleValue() < 0
							|| !energytypeid.equalsIgnoreCase("E")) {
						sql = "select nvl(round(sum("+tagCol+")*"+mod+", "+digits+"),0) from "+tagTable+" where clock>=? and clock<?";
						Double d = 0d;
						try {
							d = jdbcTemplate.queryForObject(sql, new Object[]{qck,qmk}, Double.class);
							if(d!=null && Math.abs(d) > Integer.MAX_VALUE){
								bz = "仪表数值异常：" + d;
								d = 0d;
							}
						}catch(Exception e) {
							d = 0d;
							e.printStackTrace();
							res = clock + ",itemid:" + itemid + " 取值错误, tagTable：" + tagTable + ",tagCol：" + tagCol;
							logger.error(clock + ",itemid:" + itemid + " 取值错误, tagTable：" + tagTable + ",tagCol：" + tagCol);
						}
						acb = d==null?null:new BigDecimal(Double.toString(d));
					}else{
						// 仪表期末值 - 仪表期初值
						acb = new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc))).multiply(new BigDecimal(mod)).setScale(digits, BigDecimal.ROUND_HALF_UP);
					}
				}else{
					// 计算值由子时间粒度数据统计
					if(timegranid.equalsIgnoreCase("MONTH")){
						// 月计算值等于日最终值之和
						sql = "select round(sum(apportvalue), "+digits+") apportvalue "
								+ "from T_RM_CALPOINT_VALUE where itemid = ? and timegranid='DAY' and clock like ?||'%'";
						Double actval = jdbcTemplate.queryForObject(sql, new Object[]{itemid,clock}, Double.class);
						acb = actval==null?BigDecimal.ZERO:new BigDecimal(Double.toString(actval)).setScale(digits, BigDecimal.ROUND_HALF_UP);
					}else if(timegranid.equalsIgnoreCase("YEAR")){
						// 年计算值等于月最终值之和
						sql = "select round(sum(apportvalue), "+digits+") apportvalue "
								+ "from T_RM_CALPOINT_VALUE where itemid = ? and timegranid='MONTH' and clock like ?||'%'";
						Double actval = jdbcTemplate.queryForObject(sql, new Object[]{itemid,clock}, Double.class);
						acb = actval==null?BigDecimal.ZERO:new BigDecimal(Double.toString(actval)).setScale(digits, BigDecimal.ROUND_HALF_UP);
					}
				}
			}else{
				res = "计量点的数据表与数据列信息不完整！itemid:"+itemid;
				logger.error("计量点的数据表与数据列信息不完整！itemid:"+itemid);
				bz = "-1：请配置数据表与数据列";
			}
			// 期初与期末
			qcb = qc==null?null:new BigDecimal(Double.toString(qc));
			qmb = qm==null?null:new BigDecimal(Double.toString(qm));
			if (t != null) {
				t.setMintvalue(qcb);
				t.setMendvalue(qmb);
				t.setBz(bz);
				t.setActualvalue(acb);
				// 最终值=计算值+修正值
				if (acb != null && t.getCorrectvalue() != null) {
					t.setApportvalue(acb.add(t.getCorrectvalue()));
				} else if (acb != null) {
					t.setApportvalue(acb);
				} else if (t.getCorrectvalue() != null) {
					t.setApportvalue(t.getCorrectvalue());
				} else {
					t.setApportvalue(BigDecimal.ZERO);
				}
				if(ecv!=null && ecv.getApportvalue()!=null){
					t.setBz(ecv.getBz()!=null?ecv.getBz():"人工录入，自动修改");
					t.setApportvalue(ecv.getApportvalue().setScale(digits, BigDecimal.ROUND_HALF_UP));
					t.setCorrectvalue(t.getApportvalue().subtract(t.getActualvalue()==null?BigDecimal.ZERO:t.getActualvalue()));
				}
				t.setUpman(updateUser);
				t.setUptime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				tRmCalpointValueMapper.updateByPrimaryKeySelective(t);
			} else {
				// 数据不存在，新增
				t = new TRmCalpointValue();
				t.setMintvalue(qcb);
				t.setMendvalue(qmb);
				t.setBz(bz);
				t.setActualvalue(acb); // 计算值
				t.setCorrectvalue(BigDecimal.ZERO); // 修正值
				t.setApportvalue(acb); // 最终值
				if(ecv!=null && ecv.getApportvalue()!=null){
					t.setBz(ecv.getBz()!=null?ecv.getBz():"人工录入，自动修改");
					t.setApportvalue(ecv.getApportvalue().setScale(digits, BigDecimal.ROUND_HALF_UP));
					t.setCorrectvalue(t.getApportvalue().subtract(t.getActualvalue()==null?BigDecimal.ZERO:t.getActualvalue()));
				}
				t.setClock(clock);
				t.setTimegranid(timegranid);
				t.setItemid(itemid);
				t.setItemname(itemname);
				t.setCrman(updateUser);
				t.setRecTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				tRmCalpointValueMapper.insertSelective(t);
			}
			// 超标异常记录,当前只记录日数据，且最大最小值不都为0的计量点
			if (timegranid.equalsIgnoreCase("DAY") && (maxval+minval>0) && (t.getApportvalue().doubleValue()>maxval || t.getApportvalue().doubleValue()<minval)) {
				TRmCalpointExValue cev = new TRmCalpointExValue();
				cev.setApportvalue(t.getApportvalue());
				cev.setMaxvalue(new BigDecimal(Double.toString(maxval)));
				cev.setMinvalue(new BigDecimal(Double.toString(minval)));
				cev.setClock(clock);
				cev.setItemid(itemid);
				cev.setCreatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				cev.setExtype("0");
				tRmCalpointExValueService.add(cev);
			}
		}else if(itemtype.equalsIgnoreCase("MANUAL")){// 手动
			BigDecimal acb = BigDecimal.ZERO;// 计算值
			// 手抄数据计算值获取，非基础数据用粒度累加，已有的基础数据用基础数据。
			if(!mintimegranid.equalsIgnoreCase(timegranid)){
				// 计算值由子时间粒度数据统计
				if(timegranid.equalsIgnoreCase("MONTH")){
					// 月计算值等于日最终值之和
					HashMap<String, Object> maps = new HashMap<>();
			        maps.put("itemid", itemid);
			        maps.put("clock", clock);
			        maps.put("timegranid", "DAY");
					acb = new BigDecimal(Double.toString(this.getSumvalue(maps))).setScale(digits, BigDecimal.ROUND_HALF_UP);
				}else if(timegranid.equalsIgnoreCase("YEAR")){
					// 年计算值等于月最终值之和
					HashMap<String, Object> maps = new HashMap<>();
			        maps.put("itemid", itemid);
			        maps.put("clock", clock);
			        maps.put("timegranid", "MONTH");
			        acb = new BigDecimal(Double.toString(this.getSumvalue(maps))).setScale(digits, BigDecimal.ROUND_HALF_UP);
				}
			}else{
				if(t!= null){
					acb = t.getActualvalue();
				}
			}
			if (t!= null) {
				t.setActualvalue(acb);
				// 最终值=计算值+修正值
				if (t.getCorrectvalue() != null) {
					t.setApportvalue(acb.add(t.getCorrectvalue()).setScale(digits, BigDecimal.ROUND_HALF_UP));
				} else {
					t.setApportvalue(acb.setScale(digits, BigDecimal.ROUND_HALF_UP));
				}
				// 外挂数据更新
				if(ecv!=null && ecv.getApportvalue()!=null){
					t.setBz(ecv.getBz()!=null?ecv.getBz():"人工录入，自动修改");
					t.setApportvalue(ecv.getApportvalue().setScale(digits, BigDecimal.ROUND_HALF_UP));
					t.setCorrectvalue(t.getApportvalue().subtract(t.getActualvalue()==null?BigDecimal.ZERO:t.getActualvalue()));
				}
				t.setUpman(updateUser);
				t.setUptime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				tRmCalpointValueMapper.updateByPrimaryKeySelective(t);
			}else{
				// 数据不存在，新增
				t = new TRmCalpointValue();
				t.setClock(clock);
				t.setTimegranid(timegranid);
				t.setItemid(itemid);
				t.setItemname(itemname);
				t.setCorrectvalue(BigDecimal.ZERO); // 修正值
				t.setActualvalue(acb); // 计算值
				t.setCorrectvalue(BigDecimal.ZERO); // 修正值
				t.setApportvalue(acb.setScale(digits, BigDecimal.ROUND_HALF_UP)); // 最终值
				if(ecv!=null && ecv.getApportvalue()!=null){
					t.setBz(ecv.getBz()!=null?ecv.getBz():"人工录入，自动修改");
					t.setApportvalue(ecv.getApportvalue().setScale(digits, BigDecimal.ROUND_HALF_UP));
					t.setCorrectvalue(t.getApportvalue().subtract(t.getActualvalue()==null?BigDecimal.ZERO:t.getActualvalue()));
				}
				t.setCrman(updateUser);
				t.setRecTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				tRmCalpointValueMapper.insertSelective(t);
			}
		}else if(itemtype.equalsIgnoreCase("VIRTUAL")){// 虚拟
			BigDecimal acb = BigDecimal.ZERO;// 计算值
			try {
				if(!mintimegranid.equalsIgnoreCase(timegranid)){
					// 计算值由子时间粒度数据统计
					if(timegranid.equalsIgnoreCase("MONTH")){
						// 月计算值等于日最终值之和
						sql = "select round(sum(apportvalue), "+digits+") apportvalue "
								+ "from T_RM_CALPOINT_VALUE where itemid = ? and timegranid='DAY' and clock like ?||'%'";
						Double actval = jdbcTemplate.queryForObject(sql, new Object[]{itemid,clock}, Double.class);
						acb = actval==null?BigDecimal.ZERO:new BigDecimal(Double.toString(actval)).setScale(digits, BigDecimal.ROUND_HALF_UP);
					}else if(timegranid.equalsIgnoreCase("YEAR")){
						// 年计算值等于月最终值之和
						sql = "select round(sum(apportvalue), "+digits+") apportvalue "
								+ "from T_RM_CALPOINT_VALUE where itemid = ? and timegranid='MONTH' and clock like ?||'%'";
						Double actval = jdbcTemplate.queryForObject(sql, new Object[]{itemid,clock}, Double.class);
						acb = actval==null?BigDecimal.ZERO:new BigDecimal(Double.toString(actval)).setScale(digits, BigDecimal.ROUND_HALF_UP);
					}
				} else{
					// 获得计算公式
					String formula = formulaService.getFormula(itemid,clock);
					// 根据公式获取计算值,不会为null,负数为错误信息
					Double dval = formulaService.getValByFormula(formula, timegranid, clock, digits, 0);
					if(dval == null || dval < 0){
						res = clock + "-itemid:" + itemid + " 计算公式错误。";
						logger.error(clock + "-itemid:" + itemid + " 计算公式错误。");
					}
					acb = new BigDecimal(Double.toString(dval));
				}
				if(t!=null){
					t.setActualvalue(acb);
					// 最终值=计算值+修正值
					if (t.getCorrectvalue() != null) {
						t.setApportvalue(acb.add(t.getCorrectvalue()).setScale(digits, BigDecimal.ROUND_HALF_UP));
					} else {
						t.setApportvalue(acb.setScale(digits, BigDecimal.ROUND_HALF_UP));
					}
					if(ecv!=null && ecv.getApportvalue()!=null){
						t.setBz(ecv.getBz()!=null?ecv.getBz():"人工录入，自动修改");
						t.setApportvalue(ecv.getApportvalue().setScale(digits, BigDecimal.ROUND_HALF_UP));
						t.setCorrectvalue(t.getApportvalue().subtract(t.getActualvalue()==null?BigDecimal.ZERO:t.getActualvalue()));
					}
					t.setUpman(updateUser);
					t.setUptime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
					tRmCalpointValueMapper.updateByPrimaryKeySelective(t);
				}else{
					t = new TRmCalpointValue();
					t.setClock(clock);
					t.setTimegranid(timegranid);
					t.setItemid(itemid);
					t.setItemname(itemname);
					t.setApportvalue(acb); // 最终值
					t.setCorrectvalue(BigDecimal.ZERO); // 修正值
					t.setActualvalue(acb); // 计算值
					if(ecv!=null && ecv.getApportvalue()!=null){
						t.setBz(ecv.getBz()!=null?ecv.getBz():"人工录入，自动修改");
						t.setApportvalue(ecv.getApportvalue().setScale(digits, BigDecimal.ROUND_HALF_UP));
						t.setCorrectvalue(t.getApportvalue().subtract(t.getActualvalue()==null?BigDecimal.ZERO:t.getActualvalue()));
					}
					t.setCrman(updateUser);
					t.setRecTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
					tRmCalpointValueMapper.insertSelective(t);
				}
			} catch (Exception e) {
				res = "虚拟计算错误：itemid-" + itemid + ",clock-" + clock;
				logger.error("虚拟计算错误：itemid-" + itemid + ",clock-" + clock);
				e.printStackTrace();
			}
		}
		return res;
	}

	@Override
	public List<Map<String, Object>> getCalpointValue(HashMap<String, Object> parmas) {
		List<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
		String[] ids = parmas.get("ids").toString().split(",");
		String start = parmas.get("start").toString();
		String end = parmas.get("end").toString();
		// 期初时间
		String qc_clk = "";
		// 期末时间
		String qm_clk = "";
		// 期末时间处理,如果是今天之前,期末为第二天0点,比如1月27日期末时间为1月28日0点.
		String qm_clk2 = "";
		try {
			qc_clk = new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd").parse(start));
			qm_clk = new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyy-MM-dd").parse(end));
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(end));
			calendar.add(Calendar.DAY_OF_YEAR, 1);
			qm_clk2 = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
		for(int i=0;i<ids.length;i++){
			String itemid = ids[i];
			String ten = "1";
			TRmCalpoint tRmCalpoint = tRmCalpointMapper.selectByPrimaryKey(itemid);
			String energytypeid = tRmCalpoint.getEnergytypeid(); // 能介大类
			String tagTable = tRmCalpoint.getTagTable(); // 小时表
			String tagCol = tRmCalpoint.getTagCol(); // 小时表字段
			Double mod = tRmCalpoint.getTagModulus() == null? 1d : tRmCalpoint.getTagModulus().doubleValue(); // 倍率
			Short digits = tRmCalpoint.getDigits() == null ? 4 : tRmCalpoint.getDigits();
			Short digits2 = tRmCalpoint.getMeterScale() == null ? 4 : tRmCalpoint.getMeterScale(); // 准点值精度
			Double tagBad = -1d; // 异常点标签(读表异常时候插入的值)
			Double qc = 0d; // 仪表期初值
			Double qc2 = 0d; // 当日仪表期初值
			Double qm = 0d; // 仪表期末值
			// 获取仪表期初、期末值
			String sqlqc = "select nvl(round("+tagCol+", "+digits2+"),0) from "+tagTable + "_ORG where clock = ?";
			String sql2 = "select qm from (select nvl(round("+tagCol+", "+digits2+"),0) qm from "+tagTable + "_ORG where clock>= ? and clock<= ? order by clock desc) where rownum=1";
			if(tagTable != null && tagCol!=null && !tagTable.trim().isEmpty() && !tagCol.trim().isEmpty()){
				try {
					qc = jdbcTemplate.queryForObject(sqlqc, new Object[]{qc_clk + " 00"}, Double.class);
					if(qc!=null && Math.abs(qc) > Integer.MAX_VALUE){
						logger.error("仪表数值异常：" + qc);
						qc = 0d;
					}
				} catch(DataAccessException e) {
					logger.error(qc_clk + "-itemid:" + itemid + " 没有仪表期初值。");
					qc = tagBad;
				}
				try {
					qm = jdbcTemplate.queryForObject(sql2, new Object[]{qm_clk + " 00", qm_clk2 + " 00"}, Double.class);
					if(qm!=null && Math.abs(qm) > Integer.MAX_VALUE){
						logger.error("仪表数值异常：" + qm);
						qm = 0d;
					}
				} catch(DataAccessException e) {
					logger.error(qm_clk + "-itemid:" + itemid + " 没有仪表期末值。");
					qm = tagBad;
				}
			}
			Double ap = 0d; // 计算值
			Double ap1 = 0d; // 计算值,当日
			// 今日之前的数据
			String sql3 = "select nvl(round(sum(apportvalue), "+digits2+"),0) from T_RM_CALPOINT_VALUE where timegranid='DAY' and itemid=? and clock>=? and clock<?";
			// 今日数据额外计算
			if(end.equals(new SimpleDateFormat("yyyy-MM-dd").format(new Date()))){
				// 今日之前的计算值
				try {
					ap = jdbcTemplate.queryForObject(sql3, new Object[]{itemid, start, end}, Double.class);
					if(ap!=null && Math.abs(ap) > Integer.MAX_VALUE){
						logger.error("仪表数值异常：" + ap);
						ap = 0d;
					}
				} catch(DataAccessException e) {
					ap = tagBad;
				}
				// 当日期初
				try {
					qc2 = jdbcTemplate.queryForObject(sqlqc, new Object[]{end + " 00"}, Double.class);
					if(qc2!=null && Math.abs(qc2) > Integer.MAX_VALUE){
						qc2 = 0d;
					}
				} catch(DataAccessException e) {
					qc2 = tagBad;
				}
				// 查询计量点十分钟表配置信息
				CordasConfiguration c = cordasConfigurationMapper.selectByPrimaryKey(itemid);
				if(c!=null && c.getTimingtable()!=null && !c.getTimingtable().isEmpty() && c.getTimingcolum()!=null){
					String timingtable = c.getTimingtable();
					String timingcolum = c.getTimingcolum();
					String sqlqm = "select qm from (select nvl(round("+timingcolum+", "+digits2+"),0) qm from "+timingtable + " where to_char(tim, 'YYYY-MM-DD')=? order by tim desc) where rownum=1";
					try {
						qm = jdbcTemplate.queryForObject(sqlqm, new Object[]{end}, Double.class);
						if(qm!=null && Math.abs(qm) > Integer.MAX_VALUE){
							logger.error("仪表数值异常：" + qm);
							qm = 0d;
						}
					} catch(DataAccessException e) {
						logger.error(end + "-itemid:" + itemid + " 没有十分钟仪表期末值。");
						qm = tagBad;
					}
					// 有清零数据计算值用小时值累加 + 十分钟累加，其他期初期末数据正常用期末-期初
					if(qm == tagBad || qc2 == tagBad || qc2 == 0d || new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc2))).doubleValue()<0 
							|| !energytypeid.equalsIgnoreCase("E")){
						// 获取最后1小时的时间clock
						String sh = "select clock from (select clock from "+tagTable+" where substr(clock,0,10)=? order by clock desc) where rownum=1";
						String clk = jdbcTemplate.queryForObject(sh, new Object[]{end}, String.class);
						// 小时数据累加
						String sql = "select nvl(round(sum("+tagCol+")*"+mod+", "+digits+"),0) from "+tagTable+" where substr(clock,0,10) = ?";
						try {
							ap1 = jdbcTemplate.queryForObject(sql, new Object[]{end}, Double.class);
							if(ap1!=null && Math.abs(ap1) > Integer.MAX_VALUE){
								ap1 = 0d;
							}
						}catch(Exception e) {
							ap1 = 0d;
						}
						// 计算10分钟数据,累加
						String sql10 = "select nvl("+timingcolum+",0) zj,case when lag("+timingcolum+") over(order by tim) is null then 0 "
								+ "else ("+timingcolum+" - lag("+timingcolum+") over(order by tim)) end jj "
								+ "from "+timingtable+" where to_char(tim, 'YYYY-MM-DD hh24')>? order by tim";
						List lt = jdbcTemplate.queryForList(sql10, new Object[]{clk});
						Double ap3 = 0d; // 10分钟累计值
						if(lt!=null && lt.size()>0){
							for(int j=0; j<lt.size();j++){
								Map mt = (Map)lt.get(j);
								Double zj = Double.valueOf(mt.get("ZJ").toString());
								Double jj = Double.valueOf(mt.get("JJ").toString());
								if(jj >= 0){
									ap3 = new BigDecimal(Double.toString(ap3)).add(new BigDecimal(Double.toString(jj))).doubleValue();
								}else{
									logger.error(clk + "-表:" + timingtable +"-列:" + timingcolum + " 读表累计值变小。");
									ap3 = new BigDecimal(Double.toString(ap3)).add(new BigDecimal(Double.toString(zj))).doubleValue();
								}
							}
						}
						ap3 = new BigDecimal(Double.toString(ap3)).multiply(new BigDecimal(mod)).setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
						ap1 = new BigDecimal(Double.toString(ap1)).add(new BigDecimal(Double.toString(ap3))).setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
					}else{
						// 仪表期末值 - 仪表期初值
						ap1 = new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc2))).multiply(new BigDecimal(mod)).setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
					}
				}else{
					ten = "0";
					// 有清零数据计算值用小时值累加，其他期初期末数据正常用期末-期初
					if(qm == tagBad || qc2 == tagBad || qc2 == 0d || new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc2))).doubleValue()<0 
							|| !energytypeid.equalsIgnoreCase("E")){
						String sql = "select nvl(round(sum("+tagCol+")*"+mod+", "+digits+"),0) from "+tagTable+" where substr(clock,0,10) = ?";
						try {
							ap1 = jdbcTemplate.queryForObject(sql, new Object[]{end}, Double.class);
							if(ap1!=null && Math.abs(ap1) > Integer.MAX_VALUE){
								ap1 = 0d;
							}
						}catch(Exception e) {
							ap1 = 0d;
						}
					}else{
						// 仪表期末值 - 仪表期初值
						ap1 = new BigDecimal(Double.toString(qm)).subtract(new BigDecimal(Double.toString(qc2))).multiply(new BigDecimal(mod)).setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
					}
				}
				ap = new BigDecimal(Double.toString(ap1)).add(new BigDecimal(Double.toString(ap))).setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
			}else{
				try {
					ap = jdbcTemplate.queryForObject(sql3, new Object[]{itemid, start, qm_clk2}, Double.class);
					if(ap!=null && Math.abs(ap) > Integer.MAX_VALUE){
						logger.error("仪表数值异常：" + ap);
						ap = 0d;
					}
				} catch(DataAccessException e) {
					ap = tagBad;
				}
			}
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("itemid", itemid);
			m.put("qc", new BigDecimal(Double.toString(qc)).toPlainString());
			m.put("qm", new BigDecimal(Double.toString(qm)).toPlainString());
			m.put("ap", new BigDecimal(Double.toString(ap)).toPlainString());
			m.put("ten", ten);
			l.add(m);
		}
		return l;
	}

	@Override
	public String restatCalpData(String itemid, String clock, String timegranid, String opuser) {
		TRmCalpoint tRmCalpoint = tRmCalpointMapper.selectByPrimaryKey(itemid);
		return restatCalData(tRmCalpoint, clock, timegranid,opuser);
	}
	
	@Override
    public Double getSumvalue(HashMap<String, Object> params) {
        return tRmCalpointValueMapper.getSumvalue(params);
    }
}
