package com.nantian.cloud.jljc.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nantian.cloud.jljc.dto.AuditorDto;
import com.nantian.cloud.jljc.dto.TReportEnergyOutDto;
import com.nantian.cloud.jljc.entity.*;
import com.nantian.cloud.jljc.service.*;
import com.nantian.sc.cloud.common.core.util.R;
import com.nantian.sc.cloud.common.log.annotation.SysLog;
import com.nantian.sc.cloud.common.security.service.ScUser;
import com.nantian.sc.cloud.common.security.util.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;


/**
 * 报表1-2-1能源产出表
 *
 * @date 2020-11-04
 */
@Slf4j
@CrossOrigin
@RestController
@AllArgsConstructor
@RequestMapping("/tReportEnergyOut")
@Api(value = "tReportEnergyOut", tags = "报表1-2-1能源产出表")
public class TReportEnergyOutController {

    final private TReportEnergyOutService tReportEnergyOutService;
    final private TReportEnergysTructureService tReportEnergysTructureService;
    final private TReportEnterpriseService tReportEnterpriseService;
    final private TReportService tReportService;
    final private EnergyInfoService energyInfoService;
    final private TReportParaService tReportParaService;
    private final EcAbnormalVolatilityService ecAbnormalVolatilityService;
    private final EcAbnormalVolatilityInfoService ecAbnormalVolatilityInfoService;
    final private TReportFinancialService tReportFinancialService;
    final private EcAbnormalVolatilityInfoController volatilityInfoController;
    private final EpcEnergyAccuracyAnalysisService epcEnergyAccuracyAnalysisService;
    private final EnterpriseInfoService enterpriseInfoService;


    /**
     * 分页查询
     */
    @GetMapping("/page")
    @SysLog("查询报表1-2-1能源产出表")
    @ApiOperation(value = "查询报表1-2-1能源产出表", notes = "条件查询报表1-2-1能源产出表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "tReportEnergyOut", value = "报表1-2-1能源产出表", required = false, dataType = "json", paramType = "path"),
            @ApiImplicitParam(name = "page", value = "分页对象", required = false, dataType = "json", paramType = "path")
    })
    public R getcheckGaugesPage(Page page, TReportEnergyOut tReportEnergyOut) {
        tReportEnergyOut.setDelFlag("1"); //查询未删除数据
        //return R.ok(tReportEnergyOutService.getPageScope(page,tReportEnergyOut));
        //return R.ok(tReportEnergyOutService.page(page, Wrappers.query(tReportEnergyOut)));
        return R.ok(tReportEnergyOutService.page(page, Wrappers.query(tReportEnergyOut)));
    }

    /**
     * 通过id查询报表1-2-1能源产出表
     */
    @GetMapping("/getById")
    @SysLog("通过id查询报表1-2-1能源产出表")
    @ApiOperation(value = "通过id查询报表1-2-1能源产出表", notes = "通过id查询报表1-2-1能源产出表")
    @ApiImplicitParam(name = "id", value = "报表1-2-1能源产出表id", required = true, paramType = "path", dataType = "int")
    public R getById(Integer id) {
        return R.ok(tReportEnergyOutService.getById(id));
    }


    /**
     * 通过年份查询报表1-2-1能源产出表
     */
    @GetMapping("/getByYear")
    @SysLog("通过年份查询报表1-2-1能源产出表")
    @ApiOperation(value = "通过年份查询报表1-2-1能源产出表", notes = "通过年份查询报表1-2-1能源产出表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "year", value = "年份", required = true, paramType = "path"),
            @ApiImplicitParam(name = "enterpriseCode", value = "企业社会信用编码", required = true, paramType = "path")
    })
    public R getByYear(String year, String enterpriseCode) {
        if (year == null || "".equals(year)) {
            return R.failed("查询报表1-2-1能源产出表失败，年度不能为空");
        }
        if (enterpriseCode == null || "".equals(enterpriseCode)) {
            return R.failed("查询报表1-2-1能源产出表失败，企业社会信用编码不能为空");
        }
        List<TReportEnergyOut> outList = tReportEnergyOutService.comparison(enterpriseCode,year);
//        List<TReportEnergyOut> outList = tReportEnergyOutService.list(Wrappers.query(out));
        return R.ok(outList);
    }

    /**
     * 批量更新报表1-2-1能源产出表（企业端）
     */
    @Transactional
    @PostMapping("/upOut")
    @SysLog("批量更新报表1-2-1能源产出表（企业端）")
    @ApiOperation(value = "批量报表1-2-1能源产出表（企业端）（参数说明是键值对说明，参数s除外）", notes = "批量报表1-2-1能源产出表（企业端）（参数说明是键值对说明），参数s除外")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "report", value = "能源报表信息", required = true, dataType = "String"),
            @ApiImplicitParam(name = "data", value = "报表1-2-1能源产出表", required = true, dataType = "String")
    })
    public R upOut(@RequestBody String s) {

        log.error("批量更新报表1-2-1能源产出表：" + s);

        JSONObject json = JSONObject.parseObject(s);
        //获取能源报表信息
        TReport report = JSONObject.parseObject(json.getString("report"), TReport.class);
        if (report.getYear() == null || "".equals(report.getYear())) {
            return R.failed("更新报表1-2-1能源产出表失败，年度不能为空");
        }
        /*if (report.getEnterpriseCode() == null || "".equals(report.getEnterpriseCode())) {
            return R.failed("更新报表1-2-1能源产出表失败，企业编码不能为空不能为空");
        }*/

        ScUser u = SecurityUtils.getUser();
        String enterpriseCode = StringUtils.isNotEmpty(report.getEnterpriseCode()) ? report.getEnterpriseCode() : u.getEnterpriseCode();
        String data = json.getString("data");
        //获取能源消费表列表
        //List<TReportEnergyOut> outList = (List<TReportEnergyOut>) JSONArray.parseArray(data, TReportEnergyOut.class);
        List<TReportEnergyOutDto> dtoList = (List<TReportEnergyOutDto>) JSONArray.parseArray(data, TReportEnergyOutDto.class);
        List<TReportEnergyOut> outList = new ArrayList<>();
        if(dtoList!=null && dtoList.size()>0){
            for (TReportEnergyOutDto dto : dtoList) {
                TReportEnergyOut tmp = new TReportEnergyOut(dto.getId(),dto.getReportId(),dto.getEnergyCode(),dto.getEnergyCodeName(),dto.getUnit(),dto.getModulus(),
                        dto.getRefModulus(),dto.getProductionConsumption(),dto.getProConTotal(),dto.getThermalPower(),dto.getHeating(),
                        dto.getCoalWashing(),dto.getWastePower(), dto.getGasPower(), dto.getCoking(),dto.getOil(),dto.getGasification(),dto.getGasLiquefaction(),
                        dto.getCoalProducts(),dto.getConversionOutput(), dto.getConversionOutputRef(),dto.getRecycling(),dto.getRemark());
                outList.add(tmp);
            }
        }

        //获取报表信息id （有数据就返回id，无数据就新增记录后返回id）
        long reportId = tReportService.getTReportIdByType(enterpriseCode, report.getYear() + "", "2-1", u);
        //计算本年能源消费信息的能源   合计当量值和合计等价值
        //返回集合，下标  0：sumInfo合计当量值  1：sumEquInfo合计等价值
        List<TReportEnergyOut> sum = getSum(outList, reportId);
        outList.addAll(sum);

        //进行异常波动分析
        R map = getEcAbnormalVolatility(report, u, outList);
        if (map != null) return map;

        //批量更新报表1-2-1能源产出表信息
        //更新报表信息
        report.setId(reportId);
        report.setUserid(u.getId());
        report.setUpdateTime(new Date());
        report.setReportStatus("2");
        //boolean b = tReportService.updateById(report);


        TReport truReport = tReportService.getInfoByType(enterpriseCode, report.getYear() + "", "2");
        TReportEnergysTructure truQuery = new TReportEnergysTructure();
        truQuery.setDelFlag("1");
        truQuery.setReportId(truReport != null ? truReport.getId() : 0);
        List<TReportEnergysTructure> truList = tReportEnergysTructureService.list(Wrappers.query(truQuery));
        //计算能源消费合计量、加工投入合计量
        Double consumeSum = 0.0, proConTotal = 0.0;
        for (TReportEnergysTructure tructure : truList) {
            if("合计当量值".equals(tructure.getEnergyCodeName())){
                consumeSum = tructure.getConsumeSum();
            }
            for (TReportEnergyOut out : outList) {
                //报表2中没有库存和外购，但报表2-1有能源投入
                double proConTotalTmp = out.getProConTotal() != null ? out.getProConTotal() : (
                        (out.getThermalPower() != null ? out.getThermalPower() : 0)
                        + (out.getHeating() != null ? out.getHeating() : 0)
                        + (out.getCoalWashing() != null ? out.getCoalWashing() : 0)
                        + (out.getWastePower() != null ? out.getWastePower() : 0)
                        + (out.getGasPower() != null ? out.getGasPower() : 0)
                        + (out.getCoking() != null ? out.getCoking() : 0)
                        + (out.getOil() != null ? out.getOil() : 0)
                        + (out.getGasification() != null ? out.getGasification() : 0)
                        + (out.getGasLiquefaction() != null ? out.getGasLiquefaction() : 0)
                        + (out.getCoalProducts() != null ? out.getCoalProducts() : 0));
                if (tructure.getEnergyCodeName() != null && tructure.getEnergyCodeName().equals(out.getEnergyCodeName())
                        && (tructure.getStartInventory()+tructure.getObject()) == 0 && proConTotalTmp != 0  ) {
                    String modulus = out.getModulus() != null ? out.getModulus() : out.getRefModulus();
                    if (modulus != null && !"".equals(modulus)) {
                        String[] split = modulus.split("-");
                        //当量值
                        Double value = split.length > 0 ? Double.parseDouble(split[0]) : 0;
                        proConTotal += proConTotalTmp * value;
                    }else{
                        proConTotal += proConTotalTmp;
                    }
                }
            }
        }



        List<TReportEnergyOut> newOutList = new ArrayList<TReportEnergyOut>();
        //获取报表设置的企业信息
        TReportEnterprise enterprise = tReportEnterpriseService.getEnterpriseInfo(enterpriseCode, report.getYear() + "");
        for (TReportEnergyOut out : outList) {
            if ("原煤".equals(out.getEnergyCodeName())) {
                TReportEnergyOut rawCoal = getRawCoal(outList, u, reportId);
                newOutList.add(rawCoal);
            } else {
                //计算能源加工转换产出折标量（吨标准煤）
                if (out.getConversionOutput() != null && out.getConversionOutput() != 0) {
                    //采用折标系数不存在，就使用参考折标系数
                    String modulus = out.getModulus() != null ? out.getModulus() : out.getRefModulus();
                    if (modulus != null && !"".equals(modulus)) {
                        String[] split = modulus.split("-");
                        //当量值
                        Double value = split.length > 0 ? Double.parseDouble(split[0]) : 0;
                        if (out.getConversionOutput() != null && out.getConversionOutput() != 0) {
                            out.setConversionOutputRef(out.getConversionOutput() * value);
                        }
                    }
                }else{
                    out.setConversionOutputRef(0d);
                }
                hasOld(u, out, reportId);
                out.setReportId(reportId);
                out.setUserid(u.getId());
                out.setUpdateTime(new Date());
                newOutList.add(out);
            }

            if ("合计当量值".equals(out.getEnergyCodeName()) && enterprise != null) {
                if ("1".equals(enterprise.getProcessingLink())) { //该企业是加工转换企业
                    updateFinancial(report, u, enterpriseCode, out, consumeSum, proConTotal);
                }
            }

            if ("合计等价值".equals(out.getEnergyCodeName()) && enterprise != null) {
                if ("1".equals(enterprise.getProcessingLink())) { //该企业是加工转换企业
                    updateFinancialRef(report, u, enterpriseCode, out, "1", consumeSum, proConTotal);
                }
            }

            if ("合计当量值(参考指标系数计算)".equals(out.getEnergyCodeName()) && enterprise != null) {
                if ("1".equals(enterprise.getProcessingLink())) { //该企业是加工转换企业
                    updateFinancialRef(report, u, enterpriseCode, out, "2", consumeSum, proConTotal);
                }
            }

        }

        // return R.ok( tReportEnergyOutService.saveOrUpdateBatch(newOutList));
        boolean updateBatch = tReportEnergyOutService.saveOrUpdateBatch(newOutList);
        if (updateBatch) {
            //只有报表2-1信息更新成功，才能更新报表信息
            return R.ok(tReportService.updateById(report));
        } else {
            return R.failed();
        }
    }

    /**
     * 该企业是加工转换企业，设置财务信息的综合能源消费量、单位产值综合能耗（折标系数异常的，采用参考折标计算）
     */
    private boolean updateFinancialRef(TReport report, ScUser u, String enterpriseCode, TReportEnergyOut out, String type, Double consumeSum, Double proConTotal) {

        //根据报表信息id取值，有值为修改，否则新增
        //存在，先填写报表2，再填写报表1的情况
        long reportIdByType1 = tReportService.getTReportIdByType(enterpriseCode, report.getYear() + "", "1", u);
        TReportFinancial financial = new TReportFinancial();
        TReportFinancial oldFinancial = tReportFinancialService.getFinancialsByReportId(reportIdByType1);

        financial.setReportId(reportIdByType1);
        financial.setUserid(u.getId());
        financial.setUpdateTime(new Date());
        //获取企业信息
        EnterpriseInfo info = enterpriseInfoService.getInfoByCode(u.getEnterpriseCode());
        //企业端新增信息，添加deptid
        financial.setDeptId(info != null && info.getRegionCode()!=null ? Integer.parseInt(info.getRegionCode()) : u.getDeptId());
        financial.setDelFlag("1");

        //设置报表1 财务信息 综合能源消费量(万吨标准煤) = (报表2-1 工业生产消费的能源折标量合计 -能源加工转换产出折标量合计-回收利用折标量合计)/10000 回显
        //Double energyConsumption = (out.getProductionConsumption() - out.getConversionOutputRef() - out.getRecycling())/10000;
        //double energyConsumption = (out.getProductionConsumption() != null ? out.getProductionConsumption() : 0)
        //        - (out.getConversionOutputRef() != null ? out.getConversionOutputRef() : 0)
        //        - (out.getRecycling() != null ? out.getRecycling() : 0);

        //设置报表1 财务信息 综合能源消费量(万吨标准煤) = (报表2能源消费合计量折标后合计 - 报表2-1能源加工转换产出折标量合计 - 报表2-1回收利用折标量合计 + (报表2中没有库存和外购，但报表2-1有能源投入))/10000 回显
        double energyConsumption = consumeSum + proConTotal
                - (out.getConversionOutputRef() != null ? out.getConversionOutputRef() : 0)
                - (out.getRecycling() != null ? out.getRecycling() : 0);


        //计算财务信息的 单位产值综合能耗（可比价） 以及上年值的变化率
        double unitEnergyConsumption = 0;
        if (oldFinancial != null) {
            //有历史数据，属于修改
            financial.setId(oldFinancial.getId());

            //单位产值综合能耗(吨标准煤/万元) = 综合能源消费量(万吨标准煤) * 10000 / 工业总产值(万元)
            if (oldFinancial.getIndustrialYield() != null && energyConsumption != 0 && oldFinancial.getIndustrialYield() != 0) { //综合能源消费量的值来源于报表2
                //unitEnergyConsumption = (energyConsumption * 10000) / financial.getIndustrialYield();
                unitEnergyConsumption = energyConsumption / oldFinancial.getIndustrialYield();
            }
        }

        DecimalFormat df = new DecimalFormat(".00"); //保留2位小数
        DecimalFormat df2 = new DecimalFormat(".0000"); //保留4位小数
        if("1".equals(type)){ //等价值
            financial.setEnergyConsumptionEqu(Double.parseDouble(df2.format(energyConsumption != 0 ? energyConsumption / 10000 : 0)));
            financial.setUnitEnergyConsumptionEqu(Double.parseDouble(df.format(unitEnergyConsumption)));
        }else{
            financial.setEnergyConsumptionRef(Double.parseDouble(df2.format(energyConsumption != 0 ? energyConsumption / 10000 : 0)));
            financial.setUnitEnergyConsumptionRef(Double.parseDouble(df.format(unitEnergyConsumption)));
        }

        return tReportFinancialService.saveOrUpdate(financial);
    }

    /**
     * 该企业是加工转换企业，设置财务信息的综合能源消费量、单位产值综合能耗
     */
    private boolean updateFinancial(TReport report, ScUser u, String enterpriseCode, TReportEnergyOut out, Double consumeSum, Double proConTotal) {

        //根据报表信息id取值，有值为修改，否则新增
        //存在，先填写报表2，再填写报表1的情况
        long reportIdByType1 = tReportService.getTReportIdByType(enterpriseCode, report.getYear() + "", "1", u);
        TReportFinancial financial = new TReportFinancial();
        TReportFinancial oldFinancial = tReportFinancialService.getFinancialsByReportId(reportIdByType1);
        /*if (oldFinancial != null) { //修改
            financial.setId(oldFinancial.getId());
        }*/

        financial.setReportId(reportIdByType1);
        financial.setUserid(u.getId());
        financial.setUpdateTime(new Date());
        //financial.setDeptId(u.getDeptId());
        //获取企业信息
        EnterpriseInfo info = enterpriseInfoService.getInfoByCode(u.getEnterpriseCode());
        //企业端新增信息，添加deptid
        financial.setDeptId(info != null && info.getRegionCode()!=null ? Integer.parseInt(info.getRegionCode()) : u.getDeptId());
        financial.setDelFlag("1");

        //获取上年的财务信息
        TReport r = tReportService.getInfoByType(enterpriseCode, (report.getYear() - 1) + "", "1");
        TReportFinancial frontFinancial = new TReportFinancial();
        if (r != null) {
            TReportFinancial front = new TReportFinancial();
            front.setReportId(r.getId());
            front.setDelFlag("1");
            frontFinancial = tReportFinancialService.getOne(Wrappers.query(front));
        }

        //设置报表1 财务信息 综合能源消费量(万吨标准煤) = (报表2-1 工业生产消费的能源折标量合计 -能源加工转换产出折标量合计-回收利用折标量合计)/10000 回显
        //Double energyConsumption = (out.getProductionConsumption() - out.getConversionOutputRef() - out.getRecycling())/10000;
        //Double energyConsumption = (out.getProductionConsumption() != null ? out.getProductionConsumption() : 0)
        //        - (out.getConversionOutputRef() != null ? out.getConversionOutputRef() : 0)
        //        - (out.getRecycling() != null ? out.getRecycling() : 0);

        //设置报表1 财务信息 综合能源消费量(万吨标准煤) = (报表2能源消费合计量折标后合计 - 报表2-1能源加工转换产出折标量合计 - 报表2-1回收利用折标量合计 + (报表2中没有库存和外购，但报表2-1有能源投入))/10000 回显
        double energyConsumption = consumeSum + proConTotal
                - (out.getConversionOutputRef() != null ? out.getConversionOutputRef() : 0)
                - (out.getRecycling() != null ? out.getRecycling() : 0);

        //计算财务信息的 单位产值综合能耗（可比价） 以及上年值的变化率
        double energyConsumptionRate = 0, unitEnergyConsumption = 0, unitEnergyConsumption2 = 0, unitEnergyConsumptionRate = 0;
        if (oldFinancial != null) {
            //有历史数据，属于修改
            financial.setId(oldFinancial.getId());

            //单位产值综合能耗(吨标准煤/万元) = 综合能源消费量(万吨标准煤) * 10000 / 工业总产值(万元)
            if (oldFinancial.getIndustrialYield() != null && energyConsumption != 0 && oldFinancial.getIndustrialYield() != 0) { //综合能源消费量的值来源于报表2
                //unitEnergyConsumption = (energyConsumption * 10000) / financial.getIndustrialYield();
                unitEnergyConsumption = energyConsumption / oldFinancial.getIndustrialYield();
            }

            //有上年数据，计算变化率
            if (frontFinancial != null) {
                if (frontFinancial.getEnergyConsumption() != null && frontFinancial.getEnergyConsumption() != 0 && energyConsumption != 0) {
                    energyConsumptionRate = ((energyConsumption/10000) / frontFinancial.getEnergyConsumption() - 1) * 100;
                }
                if (frontFinancial.getEnergyConsumption() != null && frontFinancial.getIndustrialYield() != null
                        && frontFinancial.getEnergyConsumption() != 0 && frontFinancial.getIndustrialYield() != 0) { //综合能源消费量的值来源于报表2
                    unitEnergyConsumption2 = (frontFinancial.getEnergyConsumption() * 10000) / frontFinancial.getIndustrialYield();
                }
                if (unitEnergyConsumption != 0 && unitEnergyConsumption2 != 0) {
                    unitEnergyConsumptionRate = (unitEnergyConsumption / unitEnergyConsumption2 - 1) * 100;
                }
            }
        }

        DecimalFormat df = new DecimalFormat(".00"); //保留2位小数
        DecimalFormat df2 = new DecimalFormat(".0000"); //保留4位小数
        financial.setEnergyConsumption(Double.parseDouble(df2.format(energyConsumption != 0 ? energyConsumption / 10000 : 0)));
        financial.setEnergyConsumptionRate(Double.parseDouble(df2.format(energyConsumptionRate)));
        financial.setUnitEnergyConsumption(Double.parseDouble(df.format(unitEnergyConsumption)));
        financial.setUnitEnergyConsumptionRate(Double.parseDouble(df.format(unitEnergyConsumptionRate)));

        boolean b = tReportFinancialService.saveOrUpdate(financial);
        //精确性分析
        boolean c = epcEnergyAccuracyAnalysisService.getEpcEnergyAccuracyAnalysis(report,energyConsumption, df, u);

        return b && c;
    }

    /**
     * 若有原煤能源信息，需将其所有子能源数据累加存入原煤
     */
    private TReportEnergyOut getRawCoal(List<TReportEnergyOut> outList, ScUser u, long reportId) {
        double productionConsumption = 0, proConTotal = 0, thermalPower = 0, heating = 0, coalWashing = 0, wastePower = 0, gasPower = 0, coking = 0, oil = 0,
                gasification = 0, gasLiquefaction = 0, coalProducts = 0, conversionOutput = 0, conversionOutputRef = 0, recycling = 0;

        for (TReportEnergyOut out : outList) {
            if ("无烟煤".equals(out.getEnergyCodeName())
                    || "炼焦烟煤".equals(out.getEnergyCodeName())
                    || "一般烟煤".equals(out.getEnergyCodeName())
                    || "褐煤".equals(out.getEnergyCodeName())) {

                productionConsumption += out.getProductionConsumption() != null ? out.getProductionConsumption() : 0;
                proConTotal += out.getProConTotal() != null ? out.getProConTotal() : 0;
                thermalPower += out.getThermalPower() != null ? out.getThermalPower() : 0;
                heating += out.getHeating() != null ? out.getHeating() : 0;
                coalWashing += out.getCoalWashing() != null ? out.getCoalWashing() : 0;
                wastePower += out.getWastePower() != null ? out.getWastePower() : 0;
                gasPower += out.getGasPower() != null ? out.getGasPower() : 0;
                coking += out.getCoking() != null ? out.getCoking() : 0;
                oil += out.getOil() != null ? out.getOil() : 0;
                gasification += out.getGasification() != null ? out.getGasification() : 0;
                gasLiquefaction += out.getGasLiquefaction() != null ? out.getGasLiquefaction() : 0;
                coalProducts += out.getCoalProducts() != null ? out.getCoalProducts() : 0;
                conversionOutput += out.getConversionOutput() != null ? out.getConversionOutput() : 0;
                recycling += out.getRecycling() != null ? out.getRecycling() : 0;

                //采用折标系数不存在，就使用参考折标系数
                String modulus = out.getModulus() != null ? out.getModulus() : out.getRefModulus();
                if (modulus != null && !"".equals(modulus)) {
                    String[] split = modulus.split("-");
                    //当量值
                    Double value = split.length > 0 ? Double.parseDouble(split[0]) : 0;
                    if (out.getConversionOutput() != null && out.getConversionOutput() != 0) {
                        conversionOutputRef += out.getConversionOutput() * value;
                    }
                }
            }
        }

        EnergyInfo energyInfo = new EnergyInfo();
        energyInfo.setDelFlag("1");
        energyInfo.setEnergyName("原煤");
        EnergyInfo info = energyInfoService.getOne(Wrappers.query(energyInfo));

        //conversionOutputRef = conversionOutput;
        TReportEnergyOut rawCoal = new TReportEnergyOut("原煤", "吨", productionConsumption, proConTotal, thermalPower,
                heating, coalWashing, wastePower, gasPower, coking, oil, gasification, gasLiquefaction, coalProducts, conversionOutput, conversionOutputRef, recycling);

        if (info != null) {
            rawCoal.setEnergyCode(Integer.parseInt(info.getCode()));
        }
        hasOld(u, rawCoal, reportId);
        rawCoal.setReportId(reportId);
        rawCoal.setUpdateTime(new Date());
        rawCoal.setUserid(u.getId());
        return rawCoal;
    }

    /**
     * 判断是否有历史数据
     */
    private void hasOld(ScUser u, TReportEnergyOut tructure, long reportId) {
        TReportEnergyOut old = new TReportEnergyOut();
        old.setReportId(reportId);
        old.setDelFlag("1");
        old.setEnergyCodeName(tructure.getEnergyCodeName());
        TReportEnergyOut o = tReportEnergyOutService.getOne(Wrappers.query(old));
        if (o != null) { //有历史数据为修改
            tructure.setId(o.getId());
        } else {
            //tructure.setDeptId(u.getId());
            //获取企业信息
            EnterpriseInfo info = enterpriseInfoService.getInfoByCode(u.getEnterpriseCode());
            //企业端新增信息，添加deptid
            tructure.setDeptId(info != null && info.getRegionCode()!=null ? Integer.parseInt(info.getRegionCode()) : u.getDeptId());
            tructure.setDelFlag("1");
        }
    }


    /**
     * 计算本年能源消费信息的能源合计值
     */
    public List<TReportEnergyOut> getSum(List<TReportEnergyOut> outList, long reportId) {
        double productionConsumption = 0, proConTotal = 0, thermalPower = 0, heating = 0, coalWashing = 0, wastePower = 0, gasPower = 0, coking = 0, oil = 0,
                gasification = 0, gasLiquefaction = 0, coalProducts = 0, conversionOutput = 0, conversionOutputRef = 0, recycling = 0;
        double productionConsumption2 = 0, proConTotal2 = 0, thermalPower2 = 0, heating2 = 0, coalWashing2 = 0, wastePower2 = 0, gasPower2 = 0, coking2 = 0, oil2 = 0,
                gasification2 = 0, gasLiquefaction2 = 0, coalProducts2 = 0, conversionOutput2 = 0, conversionOutputRef2 = 0, recycling2 = 0;
        double productionConsumption3 = 0, proConTotal3 = 0, thermalPower3 = 0, heating3 = 0, coalWashing3 = 0, wastePower3 = 0, gasPower3 = 0, coking3 = 0, oil3 = 0,
                gasification3 = 0, gasLiquefaction3 = 0, coalProducts3 = 0, conversionOutput3 = 0, conversionOutputRef3 = 0, recycling3 = 0;
        for (TReportEnergyOut out : outList) {

            if (!"原煤".equals(out.getEnergyCodeName())) {
                //采用折标系数不存在，就使用参考折标系数
                String modulus = out.getModulus() != null ? out.getModulus() : out.getRefModulus();
                if (modulus != null && !"".equals(modulus)) {
                    String[] split = modulus.split("-");
                    //当量值
                    Double value = split.length > 0 ? Double.parseDouble(split[0]) : 0;
                    //等价值不存在，就取当量值
                    Double equvalue = Double.parseDouble((split.length <= 1) ? value + "" : split[1]);
                    if("33".equals(out.getEnergyCode())){ //电力等价折标系数
                        equvalue = 3.05d;
                    }

                    //求合计 当量值
                    productionConsumption += (out.getProductionConsumption() != null ? out.getProductionConsumption() * value : 0);
                    proConTotal += (out.getProConTotal() != null ? out.getProConTotal() * value : 0);
                    thermalPower += (out.getThermalPower() != null ? out.getThermalPower() * value : 0);
                    heating += (out.getHeating() != null ? out.getHeating() * value : 0);
                    coalWashing += (out.getCoalWashing() != null ? out.getCoalWashing() * value : 0);
                    wastePower += (out.getWastePower() != null ? out.getWastePower() * value : 0);
                    gasPower += (out.getGasPower() != null ? out.getGasPower() * value : 0);
                    coking += (out.getCoking() != null ? out.getCoking() * value : 0);
                    oil += (out.getOil() != null ? out.getOil() * value : 0);
                    gasification += (out.getGasification() != null ? out.getGasification() * value : 0);
                    gasLiquefaction += (out.getGasLiquefaction() != null ? out.getGasLiquefaction() * value : 0);
                    coalProducts += (out.getCoalProducts() != null ? out.getCoalProducts() * value : 0);
                    conversionOutput += (out.getConversionOutput() != null ? out.getConversionOutput() * value : 0);
                    recycling += (out.getRecycling() != null ? out.getRecycling() * value : 0);

                    //求合计 等价值
                    productionConsumption2 += (out.getProductionConsumption() != null ? out.getProductionConsumption() * equvalue : 0);
                    proConTotal2 += (out.getProConTotal() != null ? out.getProConTotal() * equvalue : 0);
                    thermalPower2 += (out.getThermalPower() != null ? out.getThermalPower() * equvalue : 0);
                    heating2 += (out.getHeating() != null ? out.getHeating() * equvalue : 0);
                    coalWashing2 += (out.getCoalWashing() != null ? out.getCoalWashing() * equvalue : 0);
                    wastePower2 += (out.getWastePower() != null ? out.getWastePower() * equvalue : 0);
                    gasPower2 += (out.getGasPower() != null ? out.getGasPower() * equvalue : 0);
                    coking2 += (out.getCoking() != null ? out.getCoking() * equvalue : 0);
                    oil2 += (out.getOil() != null ? out.getOil() * equvalue : 0);
                    gasification2 += (out.getGasification() != null ? out.getGasification() * equvalue : 0);
                    gasLiquefaction2 += (out.getGasLiquefaction() != null ? out.getGasLiquefaction() * equvalue : 0);
                    coalProducts2 += (out.getCoalProducts() != null ? out.getCoalProducts() * equvalue : 0);
                    conversionOutput2 += (out.getConversionOutput() != null ? out.getConversionOutput() * equvalue : 0);
                    recycling2 += (out.getRecycling() != null ? out.getRecycling() * equvalue : 0);

                    //折标系数异常的，采用参考折标计算，当量值
                    double temp = 0;
                    if (out.getRefModulus() != null) {
                        String[] refsplit = out.getRefModulus().split("-");
                        temp = refsplit.length > 0 ? Double.parseDouble(refsplit[0]) : 0;
                    }
                    Double refvalue = value != 0 && value < 20 ? value : temp;
                    productionConsumption3 += (out.getProductionConsumption() != null ? out.getProductionConsumption() * refvalue : 0);
                    proConTotal3 += (out.getProConTotal() != null ? out.getProConTotal() * refvalue : 0);
                    thermalPower3 += (out.getThermalPower() != null ? out.getThermalPower() * refvalue : 0);
                    heating3 += (out.getHeating() != null ? out.getHeating() * refvalue : 0);
                    coalWashing3 += (out.getCoalWashing() != null ? out.getCoalWashing() * refvalue : 0);
                    wastePower3 += (out.getWastePower() != null ? out.getWastePower() * refvalue : 0);
                    gasPower3 += (out.getGasPower() != null ? out.getGasPower() * refvalue : 0);
                    coking3 += (out.getCoking() != null ? out.getCoking() * refvalue : 0);
                    oil3 += (out.getOil() != null ? out.getOil() * refvalue : 0);
                    gasification3 += (out.getGasification() != null ? out.getGasification() * refvalue : 0);
                    gasLiquefaction3 += (out.getGasLiquefaction() != null ? out.getGasLiquefaction() * refvalue : 0);
                    coalProducts3 += (out.getCoalProducts() != null ? out.getCoalProducts() * refvalue : 0);
                    conversionOutput3 += (out.getConversionOutput() != null ? out.getConversionOutput() * refvalue : 0);
                    recycling3 += (out.getRecycling() != null ? out.getRecycling() * refvalue : 0);
                }
            }
        }

        conversionOutputRef = conversionOutput;
        TReportEnergyOut sumInfo = new TReportEnergyOut("合计当量值", "吨标准煤", productionConsumption, proConTotal, thermalPower,
                heating, coalWashing, wastePower, gasPower, coking, oil, gasification, gasLiquefaction, coalProducts, conversionOutput, conversionOutputRef, recycling);

        conversionOutputRef2 = conversionOutput2;
        TReportEnergyOut sumEquInfo = new TReportEnergyOut("合计等价值", "吨标准煤", productionConsumption2, proConTotal2, thermalPower2,
                heating2, coalWashing2, wastePower2, gasPower2, coking2, oil2, gasification2, gasLiquefaction2, coalProducts2, conversionOutput2, conversionOutputRef2, recycling2);

        conversionOutputRef3 = conversionOutput3;
        TReportEnergyOut sumRefInfo = new TReportEnergyOut("合计当量值(参考指标系数计算)", "吨标准煤", productionConsumption3, proConTotal3, thermalPower3,
                heating3, coalWashing3, wastePower3, gasPower3, coking3, oil3, gasification3, gasLiquefaction3, coalProducts3, conversionOutput3, conversionOutputRef3, recycling3);

        TReportEnergyOut o = tReportEnergyOutService.getOutByReportIdAndName(reportId, "合计当量值");
        if (o != null) { //有历史数据为修改
            sumInfo.setId(o.getId());
        }

        TReportEnergyOut oEqu = tReportEnergyOutService.getOutByReportIdAndName(reportId, "合计等价值");
        if (oEqu != null) { //有历史数据为修改
            sumEquInfo.setId(oEqu.getId());
        }

        TReportEnergyOut oRef = tReportEnergyOutService.getOutByReportIdAndName(reportId, "合计当量值(参考指标系数计算)");
        if (oRef != null) { //有历史数据为修改
            sumRefInfo.setId(oRef.getId());
        }

        List<TReportEnergyOut> sumList = new ArrayList<>();
        sumList.add(sumInfo);
        sumList.add(sumEquInfo);
        sumList.add(sumRefInfo);
        return sumList;
    }


    /**
     * 进行异常波动分析
     */
    private R getEcAbnormalVolatility(TReport report, ScUser u, List<TReportEnergyOut> outList) {
        //获取上年的报表信息
        String frontYear = (report.getYear() - 1) + "";
        String enterpriseCode = StringUtils.isNotEmpty(report.getEnterpriseCode()) ? report.getEnterpriseCode() : u.getEnterpriseCode();
        TReport frontReport = tReportService.getInfoByType(enterpriseCode, frontYear, "2-1");
        if (frontReport != null) {
            //获取上一年能源消费信息
            TReportEnergyOut front = new TReportEnergyOut();
            front.setReportId(frontReport.getId());
            front.setDelFlag("1");
            List<TReportEnergyOut> frontOutList = tReportEnergyOutService.list(Wrappers.query(front));
            if (frontOutList.size() > 0) { //上年数据存在，进行异常波动分析
                boolean flage = false; //波动标志默认为，false，不波动
                //取出异常波动 预警区间
                TReportPara tReportPara = new TReportPara();
                tReportPara.setType("1");
               /* List<TReportPara> paras = tReportParaService.list(Wrappers.query(tReportPara));
                for (TReportPara para : paras) {*/
                TReportPara para = tReportParaService.list(Wrappers.query(tReportPara)).get(1);
                if (para != null && (para.getUplimt() != null || para.getDownlimt() != null)) {
                    //取出本年的异常波动表
                    EcAbnormalVolatility ecAbnormalVolatility = new EcAbnormalVolatility();
                    ecAbnormalVolatility.setYear(report.getYear() + "");
                    ecAbnormalVolatility.setDelFlag("1");
                    ecAbnormalVolatility.setEpc(u.getEnterpriseCode());
                    EcAbnormalVolatility volatility = ecAbnormalVolatilityService.getOne(Wrappers.query(ecAbnormalVolatility));
                    //取出本年的异常波动详情表
                    /*EcAbnormalVolatilityInfo ecAbnormalVolatilityInfo = new EcAbnormalVolatilityInfo();
                    ecAbnormalVolatilityInfo.setAbnormalVolatilityId(volatility != null ? volatility.getId() : 0);
                    ecAbnormalVolatilityInfo.setDelFlag("1");
                    ecAbnormalVolatilityInfo.setDataTable("表2-1");*/
                    //进行异常波动分析
                    DecimalFormat df = new DecimalFormat(".00"); //保留两位小数
                    Map<String, Object> map = new HashMap();
                    map.put("dataTable", "表2-1");

                    //本年能源消费信息
                    for (TReportEnergyOut out : outList) {
                        boolean addState = true; //新增标志默认为，true，是新增项
                        //上年能源消费信息
                        for (TReportEnergyOut frontOut : frontOutList) {
                            if (out.getEnergyCodeName().equals(frontOut.getEnergyCodeName())) {
                                addState = false;  //该条产品，不是新增项

                                //报表2-1目前只比较，能源合计的值
                                if ("合计当量值".equals(out.getEnergyCodeName())) {

                                    //工业生产消费量合计值已在表2中进行波动分析

                                    VolatilityTmpController.VolatilityTmp volatilityTmp = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getThermalPower(),
                                            frontOut.getThermalPower(),
                                            //(out.getThermalPower() / frontOut.getThermalPower() - 1) * 100,
                                            "加工转换投入火力发电折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入火力发电折标量合计",
                                            "吨标准煤");
                                    volatilityTmp.invoke();
                                    if (volatilityTmp.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp2 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getHeating(),
                                            frontOut.getHeating(),
                                            //(out.getHeating() / frontOut.getHeating() - 1) * 100,
                                            "加工转换投入供热折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入供热折标量合计",
                                            "吨标准煤");
                                    volatilityTmp2.invoke();
                                    if (volatilityTmp2.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp2.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp3 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getCoalWashing(),
                                            frontOut.getCoalWashing(),
                                            //(out.getCoalWashing() / frontOut.getCoalWashing() - 1) * 100,
                                            "加工转换投入原煤入洗折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入原煤入洗折标量合计",
                                            "吨标准煤");
                                    volatilityTmp3.invoke();
                                    if (volatilityTmp3.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp3.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp4 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getCoking(),
                                            frontOut.getCoking(),
                                            //(out.getCoking() / frontOut.getCoking() - 1) * 100,
                                            "加工转换投入炼焦折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入炼焦折标量合计",
                                            "吨标准煤");
                                    volatilityTmp4.invoke();
                                    if (volatilityTmp4.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp4.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp5 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getOil(),
                                            frontOut.getOil(),
                                            //(out.getOil() / frontOut.getOil() - 1) * 100,
                                            "加工转换投入炼油及煤制油折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入炼油及煤制油折标量合计",
                                            "吨标准煤");
                                    volatilityTmp5.invoke();
                                    if (volatilityTmp5.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp5.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp6 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getGasification(),
                                            frontOut.getGasification(),
                                            //(out.getGasification() / frontOut.getGasification() - 1) * 100,
                                            "加工转换投入制气折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入制气折标量合计",
                                            "吨标准煤");
                                    volatilityTmp6.invoke();
                                    if (volatilityTmp6.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp6.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp7 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getGasLiquefaction(),
                                            frontOut.getGasLiquefaction(),
                                            //(out.getGasLiquefaction() / frontOut.getGasLiquefaction() - 1) * 100,
                                            "加工转换投天然气液化折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投天然气液化折标量合计",
                                            "吨标准煤");
                                    volatilityTmp7.invoke();
                                    if (volatilityTmp7.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp7.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp8 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getCoalProducts(),
                                            frontOut.getCoalProducts(),
                                            //(out.getCoalProducts() / frontOut.getCoalProducts() - 1) * 100,
                                            "加工转换投加工煤制品折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投加工煤制品折标量合计",
                                            "吨标准煤");
                                    volatilityTmp8.invoke();
                                    if (volatilityTmp8.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp8.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp9 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getConversionOutputRef(),
                                            frontOut.getConversionOutputRef(),
                                            //(out.getConversionOutputRef() / frontOut.getConversionOutputRef() - 1) * 100,
                                            "能源加工转换产出折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "能源加工转换产出折标量合计",
                                            "吨标准煤");
                                    volatilityTmp9.invoke();
                                    if (volatilityTmp9.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp9.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp10 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getGasPower(),
                                            frontOut.getGasPower(),
                                            //(out.getGasPower() / frontOut.getGasPower() - 1) * 100,
                                            "加工转换投入煤气发电折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入煤气发电折标量合计",
                                            "吨标准煤");
                                    volatilityTmp10.invoke();
                                    if (volatilityTmp10.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp10.isFlage(); //更新超期标志

                                    VolatilityTmpController.VolatilityTmp volatilityTmp11 = new VolatilityTmpController.VolatilityTmp(
                                            ecAbnormalVolatilityInfoService,
                                            u, flage, para, volatility, df, map,
                                            null,
                                            "表2-1",
                                            out.getWastePower(),
                                            frontOut.getWastePower(),
                                            //(out.getWastePower() / frontOut.getWastePower() - 1) * 100,
                                            "加工转换投入余热发电折标量合计，超出波动范围。若确定数值，请填写变化情况说明！",
                                            "加工转换投入余热发电折标量合计",
                                            "吨标准煤");
                                    volatilityTmp11.invoke();
                                    if (volatilityTmp11.is()) { //超出波动范围，且未填写波动说明，返回错误信息
                                        return R.failed(map);
                                    }
                                    flage = volatilityTmp11.isFlage(); //更新超期标志

                                }

                            }
                        }

                        //遍历完上年数据，无相同名称的能源，属于新增
                        //报表2已经判断完了，报表2-1不用重复判断
                        //if (addState) { }
                    }

                    //表2-1没有数据超出异常范围，判断是否记录了其他异常波动信息，若无主表信息需要删除
                    if (!flage && volatility != null) {
                        upVolatility(u, volatility);
                    }


                }
            }
        }
        return null;
    }

    /**
     * 没有超出波动范围，却有波动记录，需要删除波动记录
     */
    private void deleteVolatilityInfo(ScUser u, EcAbnormalVolatilityInfo volatilityInfo) {
        volatilityInfo.setDelFlag("4");
        volatilityInfo.setUserid(u.getId());
        volatilityInfo.setUpdateTime(new Date());
        boolean delete = ecAbnormalVolatilityInfoService.updateById(volatilityInfo);
    }

    /**
     * 判断是否记录了其他异常波动信息，若无主表信息需要删除
     */
    private void upVolatility(ScUser u, EcAbnormalVolatility volatility) {

        //其他报表的异常波动详情表信息
        EcAbnormalVolatilityInfo volatilityInfoOther = new EcAbnormalVolatilityInfo();
        volatilityInfoOther.setAbnormalVolatilityId(volatility != null ? volatility.getId() : 0);
        volatilityInfoOther.setDelFlag("1");
        List<EcAbnormalVolatilityInfo> volatilityInfoOtherList = ecAbnormalVolatilityInfoService.list(Wrappers.query(volatilityInfoOther));
        if (!(volatilityInfoOtherList.size() > 0)) {
            //其他报表的异常波动详情信息不存在，删除主表
            volatility.setDelFlag("4");
            volatility.setUpdateTime(new Date());
            volatility.setUserid(u.getId());
            ecAbnormalVolatilityService.updateById(volatility);
        }
    }


    /**
     * 判断报表是否已经上报
     */
    @GetMapping("/hasSubmit")
    @SysLog("判断报表是否已经上报")
    @ApiOperation(value = "判断报表是否已经上报", notes = "判断报表是否已经上报")
    @ApiImplicitParam(name = "TReport", value = "能源报表信息", required = true, dataType = "String")
    public R hasSubmit(String year, String enterpriseCode) {

        if (year == null || "".equals(year)) {
            return R.failed("年度不能为空");
        }
        if(StringUtils.isEmpty(enterpriseCode)){
            enterpriseCode = SecurityUtils.getUser().getEnterpriseCode();
        }
        //获取能源报表信息
        TReport report = tReportService.getInfoByType(enterpriseCode, year, "2-1");
        return R.ok(report);
    }

    /**
     * 提交报表1-2-1能源产出表
     */
    @PostMapping("/submit")
    @SysLog("提交报表1-2-1能源产出表")
    @ApiOperation(value = "提交报表1-2-1能源产出表", notes = "提交报表1-2-1能源产出表")
    @ApiImplicitParam(name = "TReport", value = "能源报表信息", required = true, dataType = "String")
    public R save(@RequestBody TReport tReport) {
        if (tReport.getYear() == null || "".equals(tReport.getYear())) {
            return R.failed("提交报表1-2-1能源产出表失败，年度不能为空");
        }
        ScUser u = SecurityUtils.getUser();
        //获取报表信息id
        //long reportId = tReportService.getTReportIdByType(u.getEnterpriseCode(), tReport.getYear()+"", "2-1", u);
        String enterpriseCode = StringUtils.isEmpty(tReport.getEnterpriseCode()) ? u.getEnterpriseCode() : tReport.getEnterpriseCode();
        TReport oldReport = tReportService.getInfoByType(enterpriseCode, tReport.getYear() + "", "2-1");
        if (oldReport == null) {
            return R.failed("请先保存能源产出表再上报！");
        }

        TReportEnergyOut out = new TReportEnergyOut();
        out.setReportId(oldReport.getId());
        out.setDelFlag("1");
        List<TReportEnergyOut> outList = tReportEnergyOutService.list(Wrappers.query(out));
        if (outList.size() <= 0) {
            return R.failed("请先保存能源产出表再上报！");
        }

        tReport.setId(oldReport.getId());
        tReport.setUpdateTime(new Date());
        tReport.setUserid(u.getId());
        tReport.setReportStatus("3");
        tReport.setAuditStatus("1");
        tReport.setAuditStatus2("1");
        tReport.setAuditStatus3("1");
        return R.ok(tReportService.updateById(tReport));
    }


    /**
     * 企业端预览报表1-2-1能源产出表
     */
    @GetMapping("/preview")
    @SysLog("企业端预览报表1-2-1能源产出表")
    @ApiOperation(value = "企业端预览报表1-2-1能源产出表", notes = "企业端预览报表1-2-1能源产出表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "year", value = "年份", required = false, dataType = "json", paramType = "path"),
            @ApiImplicitParam(name = "enterpriseCode", value = "企业编码", required = false, dataType = "json", paramType = "path")
    })
    public R getByReportId(String year, String enterpriseCode) {

        if (year == null || "".equals(year)) {
            return R.failed("预览报表1-2-1能源产出表失败，年度不能为空");
        }
        if (StringUtils.isEmpty(enterpriseCode)) {
            enterpriseCode = SecurityUtils.getUser().getEnterpriseCode();
        }
        //企业端 flag为false
        return previewReport(year, enterpriseCode, false);

    }

    /**
     * 政府端预览报表1-2-1能源产出表
     */
    @GetMapping("/previewGov")
    @SysLog("政府端预览报表1-2-1能源产出表")
    @ApiOperation(value = "政府端预览报表1-2-1能源产出表", notes = "政府端预览报表1-2-1能源产出表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "year", value = "年份", required = false, dataType = "json", paramType = "path"),
            @ApiImplicitParam(name = "enterpriseCode", value = "企业编码", required = false, dataType = "json", paramType = "path")
    })
    public R getByReportIdGov(String year, String enterpriseCode) {

        if (year == null || "".equals(year)) {
            return R.failed("预览报表1-2-1能源产出表失败，年度不能为空");
        }
        if (enterpriseCode == null || "".equals(enterpriseCode)) {
            return R.failed("预览报表1-2-1能源产出表失败，企业社会信用编码不能为空");
        }
        //政府端 flag为true
        return previewReport(year, enterpriseCode, true);

    }

    /**
     * 预览报表1-2-1信息
     */
    private R previewReport(String year, String enterpriseCode, boolean flag) {
        //获取报表1-2-1的能源报表信息
        //TReport report = tReportService.getById(reportId);
        TReport report = tReportService.getInfoByType(enterpriseCode, year, "2-1");
        if (report == null) {
            return R.ok();
        }

        //获取企业信息
        TReportEnterprise enterprise = tReportEnterpriseService.getEnterpriseInfo(enterpriseCode, year);


        //获取完整的能源产出表信息（39项）
        List<TReportEnergyOut> outList = tReportEnergyOutService.getAllOutByReportId(report.getId());
        //处理原煤数据
        TReportEnergyOut rawCoal = getRawCoal(outList, SecurityUtils.getUser(), report.getId());
        outList.set(0,rawCoal);

        //获取能源合计信息
        TReportEnergyOut outSum = tReportEnergyOutService.getOutByReportIdAndName(report.getId(), "合计当量值");
        if (outSum == null) {
            //计算本年能源消费信息的能源合计值，并追加到列表尾部
            //返回集合，下标  0：sumInfo合计当量值  1：sumEquInfo合计等价值
            List<TReportEnergyOut> sumList = getSum(outList, report.getId());
            TReportEnergyOut out = (sumList.size() > 0 ? sumList.get(0) : new TReportEnergyOut());
            out.setEnergyCodeName("能源合计");
            outList.add(out);
        } else {
            outSum.setEnergyCodeName("能源合计"); //表2-1预览，合计当量值名称为能源合计
            outList.add(outSum);
        }

        //获取当前年度财务信息
        TReport fReport = tReportService.getInfoByType(report.getEnterpriseCode(), year, "1");
        TReportFinancial financial = tReportFinancialService.getFinancialsByReportId(fReport != null ? fReport.getId() : 0);
        //本年综合能源消费量（当量值）(万吨标准煤)
        double energyConsumption = 0;
        if (financial != null) {
            energyConsumption = (financial.getEnergyConsumption() != null ? financial.getEnergyConsumption() : 0);
        }

        //获取上年度财务信息
        Integer prevYear = Integer.parseInt(year) - 1;
        TReport fprevReport = tReportService.getInfoByType(report.getEnterpriseCode(), prevYear + "", "1");
        TReportFinancial prevFinancial = tReportFinancialService.getFinancialsByReportId(fprevReport != null ? fprevReport.getId() : 0);
        //上年综合能源消费量（当量值）
        double prevEnergyConsumption = 0;
        if (prevFinancial != null) {
            prevEnergyConsumption = (prevFinancial.getEnergyConsumption() != null ? prevFinancial.getEnergyConsumption() : 0);
        }

        Map<String, Object> map = new HashMap();
        map.put("enterprise", enterprise);
        map.put("report", report);
        map.put("out", outList);
        map.put("energyConsumption", big(energyConsumption));
        map.put("prevEnergyConsumption", big(prevEnergyConsumption));

        if (flag) { //政府端，要追加异常波动分析
            R<List<EcAbnormalVolatilityInfo>> volatilityInfo = volatilityInfoController.listByReport(year, enterpriseCode, "表2-1");
            List<EcAbnormalVolatilityInfo> volatility = new ArrayList<>();
            if (volatilityInfo != null) {
                if (volatilityInfo.getCode() == 0 && volatilityInfo.getData().size() > 0) {
                    volatility.addAll(volatilityInfo.getData());
                }
            }
            R<List<EcAbnormalVolatilityInfo>> volatilityInfo2 = volatilityInfoController.listByReport(year, enterpriseCode, "表2");
            if (volatilityInfo2 != null) {
                if (volatilityInfo2.getCode() == 0 && volatilityInfo2.getData().size() > 0) {
                    for (EcAbnormalVolatilityInfo info2 : volatilityInfo2.getData()) {
                        if ("T".equals(info2.getAddState())) {
                            //报表1-2-1没有重复判断新增项，新增项波动说明需要从报表1-2中取出
                            volatility.add(info2);
                        }
                    }
                }
            }
            map.put("volatility", volatility);
        }


        return R.ok(map);
    }

    private static String big(double d) {
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        return nf.format(d);
    }

    /**
     * 审核报表1-2-1能源产出表
     */
    @PostMapping("/auditor")
    @SysLog("审核报表1-2-1能源产出表")
    @ApiOperation(value = "审核报表1-2-1能源产出表", notes = "审核报表1-2-1能源产出表")
    @ApiImplicitParam(name = "auditorDto", value = "报表审核对象", required = true, dataType = "json", paramType = "path")
    public R updateByAuditor(@RequestBody AuditorDto auditorDto) {
        ScUser u = SecurityUtils.getUser();
        if (auditorDto.getId() == null) {
            return R.failed("报表id为空，审核报表1-2-1能源产出表失败！");
        }
        TReport tReport = new TReport();
        tReport.setId(auditorDto.getId());
        tReport.setUpdateTime(new Date());
        tReport.setUserid(u.getId());
        tReport.setAuditStatus(auditorDto.getAuditStatus());
        tReport.setAuditRemark(auditorDto.getAuditRemark());
        boolean b = tReportService.updateById(tReport);
        return b ? R.ok("2".equals(auditorDto.getAuditStatus()) ? "已审核" : "已退回") : R.failed("审核失败");
    }

}
