package com.tofly.watermeter.custom.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.api.GdglinfoClient;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.core.util.Date8Util;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.ftp.config.FtpUtil;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.pojo.GdglinfoExtendDto;
import com.tofly.watermeter.config.ForeignConfig;
import com.tofly.watermeter.custom.dto.SupplyYhYfDto;
import com.tofly.watermeter.custom.entity.enums.ReadData;
import com.tofly.watermeter.custom.entity.meterRead.AuditQuality;
import com.tofly.watermeter.custom.entity.meterRead.ReadSearch;
import com.tofly.watermeter.custom.entity.meterRead.YhbhAndSl;
import com.tofly.watermeter.custom.entity.meterRead.readstatic.AuditMap;
import com.tofly.watermeter.custom.entity.webserverbean.*;
import com.tofly.watermeter.custom.service.ReadMeterService;
import com.tofly.watermeter.custom.service.websb.WebSBservice;
import com.tofly.watermeter.custom.util.Date7Utils;
import com.tofly.watermeter.custom.util.DateTimeUtil;
import com.tofly.watermeter.em.ApiCallEnum;
import com.tofly.watermeter.entity.*;
import com.tofly.watermeter.service.*;
import com.tofly.watermeter.util.CallAPIUtil;
import com.tofly.watermeter.util.service.CallAPIService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @author FlashWJL
 * @date 2021/4/15 13:38
 */
@Slf4j
@Service("customReadMeterService")
@AllArgsConstructor
public class ReadMeterServiceImpl implements ReadMeterService {

    private final QfcbqfmxService cbqfService;
    private final QfkhjbxxService khjbxxService;
    private final QfcbqfmxlsService qflsService;
    private final FileService fileService;
    private final BwrksbdatailService bwrksbdatailService;
    private final QfmidysxzbmEService qfmidysxzbmEService;
    private final QfmidysxzxfbmEService qfmidysxzxfbmEService;
    private final WebSBservice webSBservice;
    private final ReadmeterService readmeterService;
    private final ReadmeterhisService readmeterhisService;
    private final ReadmetereashisService readmetereashisService;
    private final GdglinfoClient gdglinfoClient;
    private final CallAPIService callAPIService;

    private final RedisTemplate redisTemplate;

    private final ForeignConfig foreignConfig;

    private static String TABLE_NAME = "TF_YWPN_GDINFO_W";

//    @Override
//    public IPage<AppRead> getReadDataApp(Page page, ReadSearch search) {
//        String yhbh = search.getYhbh();
//        String yhxm = search.getYhxm();
//        String yhdz = search.getYhdz();
//        String lxdh = search.getLxdh();
//        String sbbh = search.getSbbh();
//        //获取当前登录抄表人员ID
//        Long cbry = SecurityUtils.getUserId();
//        //查询对应抄表人员的区域段
////        List<Cbqydbm> cbqydbmList = cbqydbmService.list(Wrappers.<Cbqydbm>lambdaQuery().eq(Cbqydbm::getCbry, cbry)
////                .select(Cbqydbm::getQydbm, Cbqydbm::getCbzq));
//        List<Cbqydbm> cbqydbmList = null;
//
//        if (cbqydbmList.size() > 0) {
//            String qydbm = cbqydbmList.stream().map(k -> k.getQydbm().toString()).collect(Collectors.joining(","));
//            IPage<AppRead> appReadIPage = cbqfService.getReadDataApp(page, yhbh, yhxm, yhdz, lxdh, sbbh, qydbm);
//
//            return appReadIPage;
//        }
//        return null;
//    }

    @Override
    public List<Map> getStatisAudit(String yearMonth, String isGeneral) {
        return readmeterhisService.getStatisAudit(yearMonth, isGeneral);
    }

    /**
     * 定时同步历史用水数据
     * 初始同步从2018年1月1日开始到现在
     * 历史同步 以最大年月开始同步
     *
     * @param again 是否重新同步
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean getHistoryWaterData(Boolean again) {
        if (again != null && again) {
            //执行清理数据库表数据
            qflsService.truncateQfcbqfmxlsTable();
        }
        //开始同步数据
        Date date = qflsService.getObj(new QueryWrapper<Qfcbqfmxls>().select("MAX(MONTH_TIME) as COLLECTION_DATE")
                , (o) -> (Date) o);
        if (date == null) {
            date = cn.hutool.core.date.DateUtil.parse("2020-01-01");
        } else {
            qflsService.remove(new QueryWrapper<Qfcbqfmxls>().lambda().eq(Qfcbqfmxls::getMonthTime, date));
        }
        //加一个月
        //date = cn.hutool.core.date.DateUtil.offset(date, DateField.MONTH, 1);
//        Date dateTime = cn.hutool.core.date.DateUtil.beginOfMonth(cn.hutool.core.date.DateUtil.offset(new Date(), DateField.MONTH, 1));
        DateTime dateTime = cn.hutool.core.date.DateUtil.parse("2020-02-01 00:00:00", "yyyy-MM-dd HH:mm:ss");
        while (date.getTime() <= dateTime.getTime()) {
            Map<String,Object> param = new HashMap<>(3);
            param.put("READ_MONTH", cn.hutool.core.date.DateUtil.format(date, "yyyyMM"));
            int i = 1;
            Date yearonmonth1 = cn.hutool.core.date.DateUtil.offset(date, DateField.YEAR, -1);
            Date yearonmonth2 = cn.hutool.core.date.DateUtil.offset(date, DateField.YEAR, -2);
            Date yearonmonth3 = cn.hutool.core.date.DateUtil.offset(date, DateField.YEAR, -3);
            StringBuilder sb = new StringBuilder();
            sb.append("'").append(cn.hutool.core.date.DateUtil.format(yearonmonth1, "yyyy-MM")).append("' as YEARONYEAR1,'")
                    .append(cn.hutool.core.date.DateUtil.format(yearonmonth2, "yyyy-MM")).append("' as YEARONYEAR2,'")
                    .append(cn.hutool.core.date.DateUtil.format(yearonmonth3, "yyyy-MM")).append("' as YEARONYEAR3");
            log.info("拉取数据开始时间{}", cn.hutool.core.date.DateUtil.format(date, "yyyyMM"));
            Qfcbqfmxls qfcbqfmxls = null;
            while (true) {
                param.put("PAGE_NUM", i);
                param.put("PAGE_SIZE", 1000);
                log.info("执行查询第{}次", i);
                try {
//                    Map cbMap = CallAPIUtil.callAPIUtil(cbInfo, "api/Business/GetRead");
                    log.info("开始调用接口参数为：" + JSONObject.toJSONString(param));
                    Map apiResult = callAPIService.getApiResult(param, "/api/Business/GetReadAndFees");
                    if (CollectionUtil.isEmpty(apiResult)) {
                        log.info("获取Map数据为空");
                        break;
                    }
                    Map dataMap = JSONObject.parseObject(String.valueOf(apiResult.get("data")), Map.class);

                    if (CollectionUtil.isNotEmpty(dataMap)) {
                        List<Qfcbqfmxls> lists = JSONObject.parseArray(String.valueOf(dataMap.get("list")), Qfcbqfmxls.class);
                        //判断数据取完没有，如果没有取完则继续取
                        if (StringUtil.isNotNull(lists) && lists.size() > 0) {
                            qfcbqfmxls = handleQfcbqfmxls(date, yearonmonth1, yearonmonth2, yearonmonth3, sb, qfcbqfmxls, lists);
                            i++;
                        } else {
                            log.info("list 列表数据为空");
                            break;
                        }
                    } else {
                        break;
                    }
                } catch (Exception e) {
                    log.error("同步数据出现异常本次同步跳过同步时间{}，批次{},异常信息{}", cn.hutool.core.date.DateUtil.format(date, "yyyyMM"), i, e);
                    e.printStackTrace();
                    try {
                        Thread.sleep(1000 * 60);
                    } catch (Exception e1) {

                    }

                }
            }
            date = cn.hutool.core.date.DateUtil.offset(date, DateField.MONTH, 1);
        }
        log.info("执行完成退出");
        return null;
    }

    private Qfcbqfmxls handleQfcbqfmxls(Date date, Date yearonmonth1, Date yearonmonth2, Date yearonmonth3, StringBuilder sb, Qfcbqfmxls qfcbqfmxls, List<Qfcbqfmxls> lists) {
        //数据插入数据库
        Qfcbqfmxls delxls = null;
        List<Qfcbqfmxls> xlss = new ArrayList<>();
        int ct = 0;
        for (Qfcbqfmxls xls : lists) {
            if (qfcbqfmxls != null && qfcbqfmxls.getYhbh().equals(xls.getYhbh())) {
                if (ct == 0) {
                    delxls = qfcbqfmxls;
                } else {
                    xlss.add(qfcbqfmxls);
                }
                if (!qfcbqfmxls.getBcds().equals(xls.getBcds())) {
                    if (qfcbqfmxls.getBcds() > xls.getBcds() && xls.getScds() != 0) {
                        xls.setBcds(qfcbqfmxls.getBcds());
                    }
                }
                long xjjl = xls.getBcjjl() != null ? xls.getBcjjl() : 0;
                long qjjl = qfcbqfmxls.getBcjjl() != null ? qfcbqfmxls.getBcjjl() : 0;
                //根据水表类型判断 水量应该怎样处理 起度、止度
                if (!qfcbqfmxls.getScds().equals(xls.getScds())) {
                    if (qfcbqfmxls.getScds() < xls.getScds() || xls.getScds() == 0) {
                        xls.setScds(qfcbqfmxls.getScds());
                    }
                    xls.setBcjjl(xjjl + qjjl);
                } else {
                    if (qjjl > xjjl) {
                        xls.setBcjjl(qjjl);
                    }
                }

            }
            qfcbqfmxls = xls;
            xls.setCbsl(xls.getBcjjl());
            xls.setMonthTime(date);
            xls.setCbyf(cn.hutool.core.date.DateUtil.format(date, "yyyyMM"));
            ct++;
        }
        lists.removeAll(xlss);
        if (delxls != null) {
            qflsService.remove(new QueryWrapper<Qfcbqfmxls>().lambda()
                    .eq(Qfcbqfmxls::getYhbh, delxls.getYhbh()).eq(Qfcbqfmxls::getMonthTime, delxls.getMonthTime()));
        }

        saveQfcbqfmxls(lists, yearonmonth1, yearonmonth2, yearonmonth3, sb.toString());
        return qfcbqfmxls;
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveQfcbqfmxls(List<Qfcbqfmxls> lists, Date yearonmonth1, Date yearonmonth2, Date yearonmonth3, String column) {
        int pc = 20;
        int num = lists.size() / pc;
        for (int j = 0; j < num + 1; j++) {
            List<Qfcbqfmxls> cp = null;
            if (j < num) {
                cp = lists.subList(j * pc, (j + 1) * pc);
            } else {
                cp = lists.subList(j * pc, lists.size());
            }
            log.info("---------------------->" + cp.size());
            if (cp.size() > 0) {
                qflsService.saveQfcbqfmxls(cp, yearonmonth1, yearonmonth2, yearonmonth3, column);
            }
        }
    }

    @Override
    public boolean supplyQfcbqfmxls(List<SupplyYhYfDto> dtos) {
        //开始同步数据
        Date endTime = qflsService.getObj(new QueryWrapper<Qfcbqfmxls>().select("MAX(MONTH_TIME) as COLLECTION_DATE")
                , (o) -> {
                    return (Date) o;
                });
        for (SupplyYhYfDto dto : dtos) {
            Date date = cn.hutool.core.date.DateUtil.parse(dto.getCwyf(), "yyyyMM");
            if (endTime.getTime() > date.getTime()) {
                continue;
            }
            redisTemplate.opsForList().leftPush(foreignConfig.getQueueKey(), dto);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQfcbqfmxls(SupplyYhYfDto dto) {
        Date date = cn.hutool.core.date.DateUtil.parse(dto.getCwyf(), "yyyyMM");

        qflsService.remove(new QueryWrapper<Qfcbqfmxls>().lambda()
                .eq(Qfcbqfmxls::getYhbh, dto.getYhbh()).eq(Qfcbqfmxls::getMonthTime, date));
        CbInfo cbInfo = new CbInfo();
        cbInfo.setYHBH(dto.getYhbh());
        cbInfo.setCWYF(dto.getCwyf());
        cbInfo.setACTION("query");
        cbInfo.setPageSize(100);
        cbInfo.setPageIndex(1);

        try {
            Map cbMap = CallAPIUtil.callAPIUtil(cbInfo, "api/Business/GetRead");
            if (StringUtil.isNull(cbMap)) {
                log.info("获取Map数据为空");
                return;
            }
            String jsonString = JSONObject.toJSONString(cbMap.get("data"));
            if (StringUtil.isNotEmpty(jsonString) && jsonString.length() > 10) {
                List<Qfcbqfmxls> lists = JSONObject.parseArray(jsonString, Qfcbqfmxls.class);
                //判断数据取完没有，如果没有取完则继续取
                if (StringUtil.isNotNull(lists) && lists.size() > 0) {
                    Date yearonmonth1 = cn.hutool.core.date.DateUtil.offset(date, DateField.YEAR, -1);
                    Date yearonmonth2 = cn.hutool.core.date.DateUtil.offset(date, DateField.YEAR, -2);
                    Date yearonmonth3 = cn.hutool.core.date.DateUtil.offset(date, DateField.YEAR, -3);
                    StringBuilder sb = new StringBuilder();
                    sb.append("'").append(cn.hutool.core.date.DateUtil.format(yearonmonth1, "yyyy-MM")).append("' as YEARONYEAR1,'")
                            .append(cn.hutool.core.date.DateUtil.format(yearonmonth2, "yyyy-MM")).append("' as YEARONYEAR2,'")
                            .append(cn.hutool.core.date.DateUtil.format(yearonmonth3, "yyyy-MM")).append("' as YEARONYEAR3");
                    handleQfcbqfmxls(date, yearonmonth1, yearonmonth2, yearonmonth3, sb, null, lists);
                }
            }
        } catch (Exception e) {
            log.error("同步数据出现异常本次同步跳过同步时间{}，异常信息{}", cn.hutool.core.date.DateUtil.format(date, "yyyyMM"), e);
            e.printStackTrace();
            throw new RuntimeException("异常");
        }
    }

    @Override
    public String getNewCbsl(String yhbh) {
        Readmeterhis readmeterhis = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getYhbh, yhbh)
                .eq(Readmeterhis::getCbbz, "1").eq(Readmeterhis::getIssyn, "1")
                .orderByDesc(Readmeterhis::getCbrq).select(Readmeterhis::getYhbh, Readmeterhis::getCbsl)
                .first("SELECT *   FROM (").last(") WHERE ROWNUM = 1"));
        if (StringUtil.isNotNull(readmeterhis)) {
            return readmeterhis.getCbsl().toString();
        }
        return "0";
    }

    /**
     * 获取营收金额统计
     *
     * @param startMonth 开始月份
     * @param endMonth   结束月份
     * @return map
     */
    @Override
    public Map getRevenueStatistics(String startMonth, String endMonth) {
        Map<String, Object> params = new HashMap<>();
        params.put("month", startMonth);
        params.put("endMonth",endMonth);
        Map apiResult = callAPIService.getApiResult(params, "/api/v1/koi/homepage/income");
        if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(apiResult.get("statusCode")))){
            return JSONObject.parseObject(JSONObject.toJSONString(apiResult.get("data")), Map.class);
        }
        return null;
    }

    /**
     * 每月26号凌晨2点初生成抄表计划
     * 生成计划的同时需要将当前数据插入到抄表欠费历史表中记录
     *
     * @return
     */
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public boolean generateReadPlan() {
//        //获得当前月份
//        int month = Date8Util.getMonth();
//        //首先判断当月是单月（0）还是双月（1）
//        String sinAndDou = month % 2 == 0 ? "1" : "0";
//        //查找出本月需要抄表的水表
//        List<String> yhbhList = khjbxxService.list(Wrappers.<Qfkhjbxx>lambdaQuery()
//                .eq(Qfkhjbxx::getCbzq, sinAndDou).select(Qfkhjbxx::getYhbh))
//                .stream().map(Qfkhjbxx::getYhbh).collect(Collectors.toList());
//
//        //如果yhbhList长度大于1000，则无法使用in查询出来，会大于in的最大限制，所以需要进行分段
//        int size = yhbhList.size();
//        //向上取整，获得次数
//        int count = (int) Math.ceil(Double.valueOf(size) / 1000d);
//        //这里循环次数不多，估计就两三次
//        for (int i = 0; i < count; i++) {
//            //将上月的数据保存到抄表历史数据表中
//            List<Qfcbqfmxls> qflsList = new ArrayList<>();
//            int startIndex = 0 + i * 1000;
//            int endIndex = 1000 + i * 1000;
//            List<String> subYhbhList = new ArrayList<>();
//            //判断是否截取的最后一次数据，如果是最后一次数据，则不能使用endIndex这个参数去截取了，有可能会存在endIndex参数值超过索引最大值的情况
//            if (i < count - 1) {
//                //分段采取数据 0~999 ； 1000~1999 , 2000~2999 .....//这里subList方法无法截取最后一位，所以需要多写一位索引
//                subYhbhList = yhbhList.subList(startIndex, endIndex);
//            } else {
//                //分段采取最后的数据
//                subYhbhList = yhbhList.subList(startIndex, yhbhList.size());
//            }
//            //根据用户编号查询上月的抄表抄录数据
//            List<Qfcbqfmx> qfcbqfmxList = cbqfService.list(Wrappers.<Qfcbqfmx>lambdaQuery().in(Qfcbqfmx::getYhbh, subYhbhList));
//
//            qfcbqfmxList.forEach(k -> {
//                Qfcbqfmxls ls = new Qfcbqfmxls();
//                //Java自带UUID
//                UUID uuid = UUID.randomUUID();
//                ls.setLsbh(uuid.toString().replace("-", ""));
//                ls.setScds(k.getScds());
//                ls.setBcds(k.getBcds());
//                ls.setCbb(k.getCbb());
//                ls.setCbbz(k.getCbbz());
//                ls.setBcjjl(k.getBcjjl());
//                ls.setFileid(k.getFileid());
//                ls.setCbkh(k.getCbkh());
//                ls.setCbpq(k.getCbpq());
//                ls.setCbry(k.getCbry());
//                ls.setCbrq(k.getCbrq());
//                ls.setJhrq(k.getJhrq());
//                ls.setCbxh(k.getCbxh());
//                ls.setYhbh(k.getYhbh());
//                ls.setXzbs(k.getXzbs());
//                ls.setJfzt(k.getJfzt());
//                ls.setCwrq(k.getCwrq());
//                qflsList.add(ls);
//            });
//            //        List<Qfcbqfmx> qfcbqfmxList =cbqfService.getListByYhbh(yhbhList);
//            //将上月的抄表数据 批量保存到抄表历史表中
//            qflsService.saveBatch(qflsList);
////        qflsService.insertBatch(qflsList);
//            //当前月 日期
//            String cwRq = Date8Util.getYearMonth();
//            //更新抄表计划数据
//            cbqfService.updateReadPlan(cwRq, subYhbhList);
//            /**
//             * 应该还要根据抄表本得到抄表员，然后再设置给当前月计划的抄表人
//             * 因为可能存在抄表人更换的情况，所以根据抄表本得到抄表人再给当月修改抄表人
//             */
//
//        }
//        return true;
//    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateReadPlanRewrite() {
        //这里每月抄表数据很多
        CbInfo cbInfo = new CbInfo();
        //财务日期，获取当前的年月
        cbInfo.setCWYF(Date8Util.getYearMonth());//Date8Util.getYearMonth()
        //cbInfo.setCWYF("202104");//Date8Util.getYearMonth()
        Map cbMap = null;
        Integer i = 1;

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, -4);
        List<YhbhAndSl> yhbhAndSls = qflsService.selectYhbhAdYsl(new Date());
        //List<YhbhAndSl> yhbhAndSls = qflsService.selectYhbhAdYsl(calendar.getTime());
        Map<String, Long> oneMap = yhbhAndSls.stream().collect(Collectors.toMap(YhbhAndSl::getYhbh, YhbhAndSl::getUsesl));
        boolean isLoad = true;
        while (isLoad) {
            cbInfo.setACTION("query");
            cbInfo.setPageSize(1000);
            cbInfo.setPageIndex(i);
            try {
                Date date = new Date();
                cbMap = CallAPIUtil.callAPIUtil(cbInfo, "api/Business/GetRead");
                if (StringUtil.isNull(cbMap)) {
                    break;
                }
                String jsonString = JSONObject.toJSONString(cbMap.get("data"));
                List<Qfcbqfmx> qfcbqfmxes = JSONObject.parseArray(jsonString, Qfcbqfmx.class);
                String cwyf = DateTimeUtil.addMonth(Date8Util.getYearMonth(), DateTimeUtil.MONTHS_YEARS_FORMAT, 1);
                String cbrqmonth2 = DateTimeUtil.addMonth(Date8Util.getYearMonth(), DateTimeUtil.MONTHS_YEARS_FORMAT, -1);
                String cbrqmonth3 = DateTimeUtil.addMonth(Date8Util.getYearMonth(), DateTimeUtil.MONTHS_YEARS_FORMAT, -2);
//                String cwyf = DateTimeUtil.addMonth("202104", DateTimeUtil.MONTHS_YEARS_FORMAT, 1);
//                String cbrqmonth2 = DateTimeUtil.addMonth("202104", DateTimeUtil.MONTHS_YEARS_FORMAT, -1);
//                String cbrqmonth3 = DateTimeUtil.addMonth("202104", DateTimeUtil.MONTHS_YEARS_FORMAT, -2);

                Map<String, Qfcbqfmx> mapdate = new HashMap<>();
                if (qfcbqfmxes != null && !qfcbqfmxes.isEmpty()) {
                    qfcbqfmxes.forEach(info -> {
                        //借用抄表日期字段，不会作为数据插入，传入当前日期作为查询数据条件
                        info.setCbrq(date);
                        info.setCwrq(cwyf);
                        info.setMonth2(oneMap.get(info.getYhbh() + cbrqmonth2));
                        info.setMonth3(oneMap.get(info.getYhbh() + cbrqmonth3));
                        info.setJfzt(StringUtils.isNotEmpty(info.getJfzt()) ? info.getJfzt().substring(0, 1) : "0");
                        mapdate.put(info.getYhbh(), info);
                    });
                    int row = cbqfService.insertOrUpdate(new ArrayList<>(mapdate.values()));
                } else {
                    isLoad = false;
                }
                i++;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateReadPlan() {
        //这里每月抄表数据很多
        CbInfo cbInfo = new CbInfo();
        String cwyf = Date8Util.getYearMonth();
        //财务日期，获取当前的年月
        cbInfo.setCWYF(cwyf);
        List<Qfcbqfmx> qfcbqfmxList = new ArrayList<>();
        Map cbMap = null;
        Integer i = 1;

        while (true) {
            cbInfo.setACTION("query");
            cbInfo.setPageSize(10000);
            cbInfo.setPageIndex(i);
            try {
                cbMap = CallAPIUtil.callAPIUtil(cbInfo, "api/Business/GetRead");
                if (StringUtil.isNull(cbMap)) {
                    break;
                }
                String jsonString = JSONObject.toJSONString(cbMap.get("data"));
                List<Qfcbqfmx> qfcbqfmxes = JSONObject.parseArray(jsonString, Qfcbqfmx.class);
                //判断数据取完没有，如果没有取完则继续取
                if (StringUtil.isNotNull(qfcbqfmxes) && qfcbqfmxes.size() > 0) {
                    qfcbqfmxList.addAll(qfcbqfmxes);
                    i++;
                } else {
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //执行数据库操作
        action(qfcbqfmxList);
        return true;
    }


    @Override
    public boolean generateHistory() {
        String startTime = Date8Util.getYearMonth();
        String endTime = Date8Util.getYearMonth();

        HistoryReadData historyReadData = new HistoryReadData();
        historyReadData.setACTION("query");
        historyReadData.setCBYF_START(startTime);
        historyReadData.setCBYF_END(endTime);
        Map cbMap = null;
        try {
            cbMap = CallAPIUtil.callAPIUtil(historyReadData, "api/Business/GetReadAndFees");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtil.isNull(cbMap.get("data"))) {
            throw new ToflyDeniedException(cbMap.get("message").toString());
        }
        String jsonString = JSONObject.toJSONString(cbMap.get("data"));
        List<Qfcbqfmxls> qfcbqfmxlsList = JSONObject.parseArray(jsonString, Qfcbqfmxls.class);
        qflsService.saveBatch(qfcbqfmxlsList);
        return true;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean genClientInfo() {
        CbParamInfo cbParamInfo = new CbParamInfo();
        cbParamInfo.setACTION("query");
        //获取所有的抄表片区
        List<ReadAreas> readAreas = webSBservice.getReadAreas(cbParamInfo);
        if (StringUtil.isNotNull(readAreas) && readAreas.size() > 0) {
            List<Qfkhjbxx> qfkhjbxxList = new ArrayList<>();
            //获取客户信息参数实体类
            KhInfo khInfo = new KhInfo();
            for (ReadAreas v : readAreas) {
                //根据片区查询
                khInfo.setACTION("query");
                khInfo.setCBPQ(v.getCbpqBm());
                List<Qfkhjbxx> qfkhjbxx = webSBservice.getKH(khInfo);
                if (StringUtil.isNotNull(qfkhjbxx) && qfkhjbxx.size() > 0) {
                    qfkhjbxxList.addAll(qfkhjbxx);
                }
            }
            if (qfkhjbxxList.size() > 0) {
                //删除所有客户信息
                boolean deleteStatus = khjbxxService.deleteAll();
               /* for (Qfkhjbxx qfkhjbxx : qfkhjbxxList) {
                    if (StringUtil.isNotEmpty(qfkhjbxx.getSbbh())) {
                        qfkhjbxx.setSbbh(qfkhjbxx.getSbbh().trim());
                    }
                }*/
                //再往数据表中添加最新的客户信息
                if (deleteStatus) {
                    khjbxxService.saveBatch(qfkhjbxxList.stream().distinct().collect(Collectors.toList()));
                }


            }
        }
        readmeterhisService.handleAbnormalUser();
        return true;
    }


    @Async
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void action(List<Qfcbqfmx> qfcbqfmxList) {

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        //查询我们数据库中抄表数据；然后过滤分段成需要更新的数据和需要插入的数据
        Map<String, String> myQfcbmx = cbqfService.list(Wrappers.<Qfcbqfmx>lambdaQuery().select(Qfcbqfmx::getYhbh)).stream()
                .collect(Collectors.toMap(Qfcbqfmx::getYhbh, Qfcbqfmx::getYhbh, (key1, key2) -> key2));//如果存在相同的键（key），则拿第二个

        List<Qfcbqfmx> insertList = new ArrayList<>();
        List<Qfcbqfmx> updateList = new ArrayList<>();
        //查询历史表中1月前的水量
        List<YhbhAndSl> oneMonthList = qflsService.getBeforeReadData(0);
        //转MAP
        Map<String, Long> oneMap = oneMonthList.stream().collect(Collectors.toMap(YhbhAndSl::getYhbh, YhbhAndSl::getUsesl, (key1, key2) -> key2));
        //查询历史表中2月前的水量
        List<YhbhAndSl> twoMonthList = qflsService.getBeforeReadData(-1);
        Map<String, Long> twoMap = twoMonthList.stream().collect(Collectors.toMap(YhbhAndSl::getYhbh, YhbhAndSl::getUsesl, (key1, key2) -> key2));
        //查询历史表中3月前的水量
        List<YhbhAndSl> threeMonthList = qflsService.getBeforeReadData(-2);
        Map<String, Long> threeMap = threeMonthList.stream().collect(Collectors.toMap(YhbhAndSl::getYhbh, YhbhAndSl::getUsesl, (key1, key2) -> key2));
        //查询历史表前三年同月的水量
//        List<YhbhAndSl> oneYearList = qflsService.getBeforeReadData(-12);
//        List<YhbhAndSl> twoYearList = qflsService.getBeforeReadData(-24);
//        List<YhbhAndSl> threeYearList = qflsService.getBeforeReadData(-36);

        //财务月份是下一个月的
        String lastCwrq = DateUtil.parseDateToStr("yyyyMM", Date7Utils.addNextPeriod(1, Date8Util.getCurrentDate()));
        qfcbqfmxList.forEach(k -> {
            //由于森鑫炬给我的是上个月抄表数据，所以本次读数实际是上次本月的上次读书
//            k.setScds(k.getBcds());
//            k.setBcds(null);
//            k.setCbrq(null);
            if (StringUtil.isNull(k.getBcds())) {
                k.setBcds(0L);
            }
            if (StringUtil.isNull(k.getScds())) {
                k.setScds(0L);
            }
            if (StringUtil.isNull(k.getBcjjl())) {
                k.setBcjjl(0L);
            }
            //设置前几月水量
            k.setMonth1(oneMap.get(k.getYhbh()));
            k.setMonth2(twoMap.get(k.getYhbh()));
            k.setMonth3(threeMap.get(k.getYhbh()));
            //如果存在，则更新
            if (myQfcbmx.containsKey(k.getYhbh())) {
                updateList.add(k);
            }
            //不存在，则插入
            else {
                insertList.add(k);
            }
        });
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                int count = (int) Math.ceil(Double.valueOf(insertList.size()) / 5000d);
                //插入
                for (int i = 0; i < count; i++) {
                    //stream流表达式，skip表示跳过前*5000条记录，limit表示读取当前流的前5000条记录
                    cbqfService.saveBatch(insertList.stream().skip(i * 5000).limit(5000).collect(Collectors.toList()));
                }
            }
        });
        executorService.execute(() -> {
            //更新
            int count = (int) Math.ceil((double) updateList.size() / 5000d);
            //插入
            for (int i = 0; i < count; i++) {
                //stream流表达式，skip表示跳过前*5000条记录，limit表示读取当前流的前5000条记录
                boolean b = cbqfService.updateCb(updateList.stream().skip(i * 5000L).limit(5000).collect(Collectors.toList()));
            }

        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateWaterNature() {
        CbParamInfo cbParamInfo = new CbParamInfo();
        cbParamInfo.setACTION("query");
        Map xzMap = new HashMap();
        try {
            xzMap = CallAPIUtil.callAPIUtil(cbParamInfo, "api/Business/UseNatures");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtil.isNull(xzMap.get("data"))) {
            throw new ToflyDeniedException(xzMap.get("message").toString());
        }
        //删除数据库所有的原有用水性质
        qfmidysxzbmEService.remove(Wrappers.<QfmidysxzbmE>lambdaQuery().isNotNull(QfmidysxzbmE::getYsxzBm));
        String jsonString = JSONObject.toJSONString(xzMap.get("data"));
        List<QfmidysxzbmE> qfmidysxzbmEList = JSONObject.parseArray(jsonString, QfmidysxzbmE.class);
        qfmidysxzbmEList.forEach(k -> {
            k.setYxbz(k.getYxbz().substring(0, 1));
        });
        //保存获取到森鑫炬接口的用水性质数据
        qfmidysxzbmEService.saveBatch(qfmidysxzbmEList);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateWaterXFNature() {
        CbParamInfo cbParamInfo = new CbParamInfo();
        cbParamInfo.setACTION("query");
        Map xzXFMap = new HashMap();
        try {
            xzXFMap = CallAPIUtil.callAPIUtil(cbParamInfo, "api/Business/UseNaturesSubdivide");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtil.isNull(xzXFMap.get("data"))) {
            throw new ToflyDeniedException(xzXFMap.get("message").toString());
        }
        qfmidysxzxfbmEService.remove(Wrappers.<QfmidysxzxfbmE>lambdaQuery().isNotNull(QfmidysxzxfbmE::getXzxfBm));
        String jsonString = JSONObject.toJSONString(xzXFMap.get("data"));
        List<QfmidysxzxfbmE> qfmidysxzxfbmES = JSONObject.parseArray(jsonString, QfmidysxzxfbmE.class);
        qfmidysxzxfbmES.forEach(k -> {
            k.setYxbz(k.getYxbz().substring(0, 1));
        });
        //保存获取到森鑫炬接口的用水性质数据
        qfmidysxzxfbmEService.saveBatch(qfmidysxzxfbmES);
        return true;
    }


    @Override
    public IPage<AuditMap> getAuditCbData(Page page, ReadSearch search) {

        String sspq = search.getSspq();
        String cbb = search.getQydmc();
        String cbry = search.getCbryName();
        String cwyf = search.getCwyf();
        String isDis = search.getIsDis();
        String isGeneral = search.getIsGeneral();
        if (StringUtil.isEmpty(cwyf)) {
            throw new ToflyDeniedException("选择时间月份");
        } else if (StringUtil.isNull(cbry)) {
            throw new ToflyDeniedException("传递抄表人员");
        } else if (StringUtil.isEmpty(cbb)) {
            throw new ToflyDeniedException("传递抄表区域段名称");
        } else if (StringUtil.isEmpty(sspq)) {
            throw new ToflyDeniedException("传递抄表区域名称");
        } else if (StringUtil.isEmpty(isDis)) {
            throw new ToflyDeniedException("请选择查看类型");
        } else if (StringUtil.isEmpty(isGeneral)) {
            throw new ToflyDeniedException("请选择计划类型");
        }
        IPage<AuditMap> auditCb = cbqfService.getAuditCbData(page, cwyf, sspq, cbb, cbry, isDis, isGeneral);
        return auditCb;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultRespone auditCbData(AuditQuality auditQuality, List<MultipartFile> fileList) {
        Date cbrq = auditQuality.getCbrq();
        String auditRsult = auditQuality.getAuditResult();
        String yhbh = auditQuality.getYhbh();
        String soleSign = auditQuality.getSoleSign();
        String auditReason = auditQuality.getAuditPassReson();
        StringBuilder fileIds = new StringBuilder();
        if (fileList != null && !fileList.isEmpty()) {
            //保存照片
            fileList.forEach(file -> {
                //文件名
                String fileName = file.getOriginalFilename();
                if (!"".equals(fileName)) {
                    //文件路径
                    assert fileName != null;
                    String filePath = "/xrty/slfxsb/" + IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf("."));
                    FtpUtil.uploadFile2Ftp(file, filePath);
                    File localFile = new File();
                    localFile.setFilePath(filePath);
                    localFile.setFileName(fileName);
                    localFile.setOtherName(IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf(".")));
                    //关联表名称
                    localFile.setTableName(TABLE_NAME);
                    //获取后缀
                    String suffix = fileName.substring(fileName.lastIndexOf("."));
                    localFile.setFileFormat(suffix);
                    localFile.setFileSize(file.getSize() + "KB");
                    fileService.save(localFile);
                    //获得文件ID
                    fileIds.append(localFile.getId()).append(",");
                }
            });
        }
        //质检实体参数
//        CertificationOrderDto certificationOrderDto = auditQuality.getCertificationOrderDto();
        //业务工单实体参数
        GdglinfoExtendDto gdglinfoExtendDto = auditQuality.getGdglinfoExtendDto();
        Long auditUser = SecurityUtils.getUserId();
        if (StringUtil.isEmpty(soleSign)) {
            throw new ToflyDeniedException("请传递用户唯一标识");
        }
        //人工确认通过
        if ("0".equals(auditRsult)) {
            Readmeterhis readmeterhisServiceOne = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .select(Readmeterhis::getYhbh, Readmeterhis::getQualityCount, Readmeterhis::getShbz));
            String shbz = readmeterhisServiceOne.getShbz();
            if ("2".equals(shbz) || "3".equals(shbz)) {
                throw new ToflyDeniedException("已转工单");
            }
            //修改抄表历史数据表中的抄表数据；根据用户编号和抄表日期找到唯一抄表历史数据
            readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate()
                    .eq(Readmeterhis::getYhbh, yhbh)
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .set(StringUtil.isNotEmpty(auditReason), Readmeterhis::getAuditPassReson, auditReason)
                    .set(Readmeterhis::getAuditUser, auditUser)
                    .set(Readmeterhis::getShbz, "1")
                    .set(Readmeterhis::getAuditTime, Date8Util.getCurrentDate()));
            readmeterService.update(Wrappers.<Readmeter>lambdaUpdate().eq(Readmeter::getYhbh, yhbh)
                    .set(Readmeter::getAuditUser, auditUser).set(Readmeter::getShbz, "1"));
        }

        //转质检工单     2022年1月26日16:30:53备注：又改成转业务工单
        else if ("1".equals(auditRsult)) {
            Readmeterhis readmeterhisServiceOne = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign));
            String shbz = readmeterhisServiceOne.getShbz();
            if ("1".equals(shbz)) {
                throw new ToflyDeniedException("已人工审核通过");
            }
            int qualityCount = 1;
            //查询上一次质检次数，因为质检次数统计的是所有，用户的所有质检次数
            Readmeterhis readmeterhis = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .isNotNull(Readmeterhis::getQualityCount)
                    .apply("ROWNUM = 1").orderByDesc(Readmeterhis::getQualityCount).select(Readmeterhis::getYhbh, Readmeterhis::getQualityCount));
            if (StringUtil.isNotNull(readmeterhis) && StringUtil.isNotNull(readmeterhis.getQualityCount())) {
                //转质检的次数
                qualityCount = qualityCount + readmeterhis.getQualityCount();
            }
            //业务工单
            if (StringUtil.isNotNull(gdglinfoExtendDto)) {
                gdglinfoExtendDto.setIsCb("1");
                gdglinfoExtendDto.setSoleSign(readmeterhisServiceOne.getSoleSign());
                gdglinfoExtendDto.setGddjFileid(fileIds.length() != 0 ? fileIds.toString() : null);
                String str = JSONObject.toJSONString(gdglinfoExtendDto);
                ResultRespone resultRespone = gdglinfoClient.saveGdglInfoMeter(str);
                if (resultRespone.getCode() == 1) {
                    String gdid = resultRespone.getResult().toString();
                    boolean updateFlag = readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate()
                            .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                            .set(StringUtil.isNotEmpty(auditReason), Readmeterhis::getAuditPassReson, auditReason)
                            .set(Readmeterhis::getShbz, "2").set(Readmeterhis::getGdId, gdid)
                            .set(Readmeterhis::getQualityCount, qualityCount));
                    if (updateFlag) {
                        return ResultRespone.success(true, "成功");
                    } else {
                        return ResultRespone.failed(false, "修改转工单失败");
                    }
                } else {
                    log.error("转工单异常{}", resultRespone.toString());
                    throw new ToflyDeniedException("调用转工单失败");
                }
            }

//            if (StringUtil.isNotNull(certificationOrderDto)) {
//            List<ZlrzClientDto> zjClentList = new ArrayList<>();
//            ZlrzClientDto zlrzClientDto = new ZlrzClientDto();
//            zlrzClientDto.setClientName(readmeterhisServiceOne.getYhxm());
//            zlrzClientDto.setClientNumber(readmeterhisServiceOne.getYhbh());
//            zlrzClientDto.setClientAddress(readmeterhisServiceOne.getYhdz());
//            zlrzClientDto.setMeterType(readmeterhisServiceOne.getSbkjName());
//            zlrzClientDto.setWaterCategory(readmeterhisServiceOne.getYsxzName());
//            zlrzClientDto.setClientPhone(readmeterhisServiceOne.getLxdh());
//            zlrzClientDto.setTableNo(readmeterhisServiceOne.getSbbh());
//            if (StringUtil.isNotNull(readmeterhisServiceOne.getMonth1())) {
//                zlrzClientDto.setLastMonthVolume(new BigDecimal(readmeterhisServiceOne.getMonth1()));
//            }
//            if (StringUtil.isNotNull(readmeterhisServiceOne.getCbsl())) {
//                zlrzClientDto.setThisMonthVolume(new BigDecimal(readmeterhisServiceOne.getCbsl()));
//            }
//            if (StringUtil.isNotNull(readmeterhisServiceOne.getSjsl())) {
//                zlrzClientDto.setDiffVolume(readmeterhisServiceOne.getSjsl().toString());
//            }
//            BigDecimal yearOnYear = yearOnYear(yhbh, cbrq, readmeterhisServiceOne.getCbsl(), readmeterhisServiceOne);
//            if (StringUtil.isNotNull(yearOnYear)) {
//                zlrzClientDto.setMonthOnMonthRatio(yearOnYear.toString());
//            }
//            BigDecimal monthRatio = chainRatio(readmeterhisServiceOne, readmeterhisServiceOne.getCbsl());
//            if (StringUtil.isNotNull(monthRatio)) {
//                zlrzClientDto.setYearOnYearRatio(monthRatio.toString());
//            }
//            zjClentList.add(zlrzClientDto);
//            certificationOrderDto.setIsCb("1");
//            certificationOrderDto.setYearMonth(cbyf);
//            certificationOrderDto.setClients(zjClentList);
//            certificationOrderDto.setDispatchPersonId(SecurityUtils.getUserId());
//            ResultRespone resultRespone = certificationOrderClient.saveCertificationExternalOrder(certificationOrderDto);
//            boolean flag = (boolean) resultRespone.getResult();
//            if (flag) {
//                boolean updateFlag = readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate()
//                        .eq(Readmeterhis::getYhbh, yhbh).eq(Readmeterhis::getCbyf, cbyf)
//                        .eq(StringUtil.isNotEmpty(soleSign) , Readmeterhis::getSoleSign , soleSign)
//                        .set(StringUtil.isNotEmpty(auditReason) , Readmeterhis::getAuditPassReson , auditReason)
//                        .set(Readmeterhis::getShbz, "2")
//                        .set(Readmeterhis::getQualityCount, qualityCount));
//                if (updateFlag) {
//                    return ResultRespone.success(true, "成功");
//                } else {
//                    return ResultRespone.failed(false, "上报质检失败");
//                }
//            } else {
//                return ResultRespone.failed(false, "上报质检失败");
//            }
//            }

        }
        //取消确认通过
        else if ("2".equals(auditRsult)) {
            Readmeterhis readmeterhisServiceOne = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .select(Readmeterhis::getYhbh, Readmeterhis::getQualityCount, Readmeterhis::getShbz));
            String shbz = readmeterhisServiceOne.getShbz();
            if ("2".equals(shbz) || "3".equals(shbz)) {
                throw new ToflyDeniedException("已转工单");
            }
            //修改抄表历史数据表中的抄表数据；根据用户编号和抄表日期找到唯一抄表历史数据
            readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate()
                    .eq(Readmeterhis::getYhbh, yhbh)
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .set(Readmeterhis::getAuditPassReson, "")
                    .set(Readmeterhis::getAuditUser, auditUser)
                    .set(Readmeterhis::getShbz, "0")
                    .set(Readmeterhis::getAuditTime, ""));
            readmeterService.update(Wrappers.<Readmeter>lambdaUpdate().eq(Readmeter::getYhbh, yhbh)
                    .set(Readmeter::getAuditUser, auditUser).set(Readmeter::getShbz, "0"));
        }
        //一键上报工单
        else if ("3".equals(auditRsult)) {
            List<String> soleSignList = Arrays.asList(soleSign.split(","));
            //查询所有待审核的用户，并且上报质检只能是当月的
            List<Readmeterhis> readmeterhisList = readmeterhisService.list(Wrappers.<Readmeterhis>lambdaQuery()
                    .in(Readmeterhis::getSoleSign, soleSignList)
                    .select(Readmeterhis::getYhbh, Readmeterhis::getYhxm, Readmeterhis::getYhdz, Readmeterhis::getLxdh,
                            Readmeterhis::getSbkj, Readmeterhis::getYsxz, Readmeterhis::getSbbh, Readmeterhis::getMonth1,
                            Readmeterhis::getMonth2, Readmeterhis::getMonth3, Readmeterhis::getYearonyear1, Readmeterhis::getYearonyear2,
                            Readmeterhis::getYearonyear3, Readmeterhis::getCbsl, Readmeterhis::getSjsl, Readmeterhis::getSoleSign));
            if (StringUtil.isNotNull(gdglinfoExtendDto)) {
                gdglinfoExtendDto.setIsCb("1");
                List<Readmeterhis> readListUpdate = new ArrayList<>();
                for (Readmeterhis readOne : readmeterhisList) {
                    gdglinfoExtendDto.setSoleSign(readOne.getSoleSign());
                    gdglinfoExtendDto.setKhbh(readOne.getYhbh());
                    gdglinfoExtendDto.setKhxm(readOne.getYhxm());
                    gdglinfoExtendDto.setKhdz(readOne.getYhdz());
                    gdglinfoExtendDto.setLxdh(readOne.getLxdh());
                    gdglinfoExtendDto.setSbbh(readOne.getSbbh());
                    gdglinfoExtendDto.setYsxz(readOne.getYsxz());
                    gdglinfoExtendDto.setSbkj(readOne.getSbkj());
                    gdglinfoExtendDto.setGddjFileid(fileIds.length() != 0 ? fileIds.toString() : null);
                    String str = JSONObject.toJSONString(gdglinfoExtendDto);
                    try {
                        ResultRespone resultRespone = gdglinfoClient.saveGdglInfoMeter(str);
                        if (resultRespone.getCode() == 1) {
                            readOne.setGdId(resultRespone.getResult().toString());
                            //最后已经登记好的工单信息，修改抄表信息
                            readListUpdate.add(readOne);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (readListUpdate.size() > 0) {
                    readmeterhisService.updateAuditCbData(readListUpdate);
                } else {
                    return ResultRespone.failed(false, "上报工单失败");
                }
            }
//            List<ZlrzClientDto> zjClentList = new ArrayList<>();
//            for (Readmeterhis readmeterhisServiceOne : readmeterhisList) {
//                ZlrzClientDto zlrzClientDto = new ZlrzClientDto();
//                zlrzClientDto.setClientName(readmeterhisServiceOne.getYhxm());
//                zlrzClientDto.setClientNumber(readmeterhisServiceOne.getYhbh());
//                zlrzClientDto.setClientAddress(readmeterhisServiceOne.getYhdz());
//                zlrzClientDto.setMeterType(readmeterhisServiceOne.getSbkjName());
//                zlrzClientDto.setWaterCategory(readmeterhisServiceOne.getYsxzName());
//                zlrzClientDto.setClientPhone(readmeterhisServiceOne.getLxdh());
//                zlrzClientDto.setTableNo(readmeterhisServiceOne.getSbbh());
//                if (StringUtil.isNotNull(readmeterhisServiceOne.getMonth1())) {
//                    zlrzClientDto.setLastMonthVolume(new BigDecimal(readmeterhisServiceOne.getMonth1()));
//                }
//                if (StringUtil.isNotNull(readmeterhisServiceOne.getCbsl())) {
//                    zlrzClientDto.setThisMonthVolume(new BigDecimal(readmeterhisServiceOne.getCbsl()));
//                }
//                if (StringUtil.isNotNull(readmeterhisServiceOne.getSjsl())) {
//                    zlrzClientDto.setDiffVolume(readmeterhisServiceOne.getSjsl().toString());
//                }
//                BigDecimal yearOnYear = yearOnYear(yhbh, cbrq, readmeterhisServiceOne.getCbsl(), readmeterhisServiceOne);
//                if (StringUtil.isNotNull(yearOnYear)) {
//                    zlrzClientDto.setMonthOnMonthRatio(yearOnYear.toString());
//                }
//                BigDecimal monthRatio = chainRatio(readmeterhisServiceOne, readmeterhisServiceOne.getCbsl());
//                if (StringUtil.isNotNull(monthRatio)) {
//                    zlrzClientDto.setYearOnYearRatio(monthRatio.toString());
//                }
//                zjClentList.add(zlrzClientDto);
//            }
//            certificationOrderDto.setIsCb("1");
//            //只能是本月的才可以一键上报
//            certificationOrderDto.setYearMonth(currentMonth);
//            certificationOrderDto.setClients(zjClentList);
//            certificationOrderDto.setDispatchPersonId(SecurityUtils.getUserId());
//            ResultRespone resultRespone = certificationOrderClient.saveCertificationExternalOrder(certificationOrderDto);
//            boolean flag = (boolean) resultRespone.getResult();
//            if (flag) {
//                readmeterhisService.updateAuditCbData(readmeterhisList, currentMonth);
//            } else {
//                return ResultRespone.failed(false, "上报质检失败");
//            }
        } else {
            throw new ToflyDeniedException("不满足操作条件");
        }
        return ResultRespone.success(true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultRespone auditYcbData(AuditQuality auditQuality, List<MultipartFile> fileList) {
        Date cbrq = auditQuality.getCbrq();
        String auditRsult = auditQuality.getAuditResult();
        String yhbh = auditQuality.getYhbh();

        String soleSign = auditQuality.getSoleSign();
        String auditReason = auditQuality.getAuditPassReson();
        StringBuilder fileIds = new StringBuilder();
        if (fileList != null && !fileList.isEmpty()) {
            //保存照片
            fileList.forEach(file -> {
                //文件名
                String fileName = file.getOriginalFilename();
                if (!"".equals(fileName)) {
                    //文件路径
                    assert fileName != null;
                    String filePath = "/xrty/slfxsb/" + IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf("."));
                    FtpUtil.uploadFile2Ftp(file, filePath);
                    File localFile = new File();
                    localFile.setFilePath(filePath);
                    localFile.setFileName(fileName);
                    localFile.setOtherName(IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf(".")));
                    //关联表名称
                    localFile.setTableName(TABLE_NAME);
                    //获取后缀
                    String suffix = fileName.substring(fileName.lastIndexOf("."));
                    localFile.setFileFormat(suffix);
                    localFile.setFileSize(file.getSize() + "KB");
                    fileService.save(localFile);
                    //获得文件ID
                    fileIds.append(localFile.getId()).append(",");
                }
            });
        }
        //质检实体参数
//        CertificationOrderDto certificationOrderDto = auditQuality.getCertificationOrderDto();
        //业务工单实体参数
        GdglinfoExtendDto gdglinfoExtendDto = auditQuality.getGdglinfoExtendDto();
        Long auditUser = SecurityUtils.getUserId();
        if (StringUtil.isEmpty(soleSign)) {
            throw new ToflyDeniedException("请传递用户唯一标识");
        }
        //人工确认通过
        if ("0".equals(auditRsult)) {
            Readmetereashis readmeterhisServiceOne = readmetereashisService.getOne(Wrappers.<Readmetereashis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign)
                    .select(Readmetereashis::getYhbh, Readmetereashis::getQualityCount, Readmetereashis::getShbz));
            String shbz = readmeterhisServiceOne.getShbz();
            if ("2".equals(shbz) || "3".equals(shbz)) {
                throw new ToflyDeniedException("已转工单");
            }
            //修改抄表历史数据表中的抄表数据；根据用户编号和抄表日期找到唯一抄表历史数据
            readmetereashisService.update(Wrappers.<Readmetereashis>lambdaUpdate()
                    .eq(Readmetereashis::getYhbh, yhbh)
                    .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign)
                    .set(StringUtil.isNotEmpty(auditReason), Readmetereashis::getAuditPassReson, auditReason)
                    .set(Readmetereashis::getAuditUser, auditUser)
                    .set(Readmetereashis::getShbz, "1")
                    .set(Readmetereashis::getAuditTime, Date8Util.getCurrentDate()));
        }

        //转质检工单     2022年1月26日16:30:53备注：又改成转业务工单
        else if ("1".equals(auditRsult)) {
            Readmetereashis readmeterhisServiceOne = readmetereashisService.getOne(Wrappers.<Readmetereashis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign));
            String shbz = readmeterhisServiceOne.getShbz();
            if ("1".equals(shbz)) {
                throw new ToflyDeniedException("已人工审核通过");
            }
            int qualityCount = 1;
            //查询上一次质检次数，因为质检次数统计的是所有，用户的所有质检次数
            Readmetereashis readmeterhis = readmetereashisService.getOne(Wrappers.<Readmetereashis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign)
                    .isNotNull(Readmetereashis::getQualityCount)
                    .apply("ROWNUM = 1").orderByDesc(Readmetereashis::getQualityCount)
                    .select(Readmetereashis::getYhbh, Readmetereashis::getQualityCount));
            if (StringUtil.isNotNull(readmeterhis) && StringUtil.isNotNull(readmeterhis.getQualityCount())) {
                //转质检的次数
                qualityCount = qualityCount + readmeterhis.getQualityCount();
            }
            //业务工单
            if (StringUtil.isNotNull(gdglinfoExtendDto)) {
                gdglinfoExtendDto.setIsCb("1");
                gdglinfoExtendDto.setIsGeneral("2");
                gdglinfoExtendDto.setSoleSign(readmeterhisServiceOne.getSoleSign());
                gdglinfoExtendDto.setGddjFileid(fileIds.length() != 0 ? fileIds.toString() : null);
                String str = JSONObject.toJSONString(gdglinfoExtendDto);
                ResultRespone resultRespone = gdglinfoClient.saveGdglInfoMeter(str);
                if (resultRespone.getCode() == 1) {
                    String gdid = resultRespone.getResult().toString();
                    boolean updateFlag = readmetereashisService.update(Wrappers.<Readmetereashis>lambdaUpdate()
                            .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign)
                            .set(StringUtil.isNotEmpty(auditReason), Readmetereashis::getAuditPassReson, auditReason)
                            .set(Readmetereashis::getShbz, "2").set(Readmetereashis::getGdId, gdid)
                            .set(Readmetereashis::getQualityCount, qualityCount));
                    if (updateFlag) {
                        return ResultRespone.success(true, "成功");
                    } else {
                        return ResultRespone.failed(false, "转工单失败");
                    }
                } else {
                    throw new ToflyDeniedException("转工单失败");
                }
            }
        }
        //取消确认通过
        else if ("2".equals(auditRsult)) {
            Readmetereashis readmeterhisServiceOne = readmetereashisService.getOne(Wrappers.<Readmetereashis>lambdaQuery()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign)
                    .select(Readmetereashis::getYhbh, Readmetereashis::getQualityCount, Readmetereashis::getShbz));
            String shbz = readmeterhisServiceOne.getShbz();
            if ("2".equals(shbz) || "3".equals(shbz)) {
                throw new ToflyDeniedException("已转工单");
            }
            //修改抄表历史数据表中的抄表数据；根据用户编号和抄表日期找到唯一抄表历史数据
            readmetereashisService.update(Wrappers.<Readmetereashis>lambdaUpdate()
                    .eq(Readmetereashis::getYhbh, yhbh)
                    .eq(StringUtil.isNotEmpty(soleSign), Readmetereashis::getSoleSign, soleSign)
                    .set(Readmetereashis::getAuditPassReson, "")
                    .set(Readmetereashis::getAuditUser, auditUser)
                    .set(Readmetereashis::getShbz, "0")
                    .set(Readmetereashis::getAuditTime, ""));
        }
        //一键上报工单
        else if ("3".equals(auditRsult)) {
            List<String> soleSignList = Arrays.asList(soleSign.split(","));
            //查询所有待审核的用户，并且上报质检只能是当月的
            List<Readmetereashis> readmeterhisList = readmetereashisService.list(Wrappers.<Readmetereashis>lambdaQuery()
                    .in(Readmetereashis::getSoleSign, soleSignList)
                    .select(Readmetereashis::getYhbh, Readmetereashis::getYhxm, Readmetereashis::getYhdz, Readmetereashis::getLxdh,
                            Readmetereashis::getSbkj, Readmetereashis::getYsxz, Readmetereashis::getSbbh, Readmetereashis::getMonth1,
                            Readmetereashis::getMonth2, Readmetereashis::getMonth3, Readmetereashis::getYearonyear1, Readmetereashis::getYearonyear2,
                            Readmetereashis::getYearonyear3, Readmetereashis::getCbsl, Readmetereashis::getSjsl, Readmetereashis::getSoleSign));
            if (StringUtil.isNotNull(gdglinfoExtendDto)) {
                gdglinfoExtendDto.setIsCb("1");
                List<Readmetereashis> readListUpdate = new ArrayList<>();
                for (Readmetereashis readOne : readmeterhisList) {
                    gdglinfoExtendDto.setSoleSign(readOne.getSoleSign());
                    gdglinfoExtendDto.setIsGeneral("2");
                    gdglinfoExtendDto.setKhbh(readOne.getYhbh());
                    gdglinfoExtendDto.setKhxm(readOne.getYhxm());
                    gdglinfoExtendDto.setKhdz(readOne.getYhdz());
                    gdglinfoExtendDto.setLxdh(readOne.getLxdh());
                    gdglinfoExtendDto.setSbbh(readOne.getSbbh());
                    gdglinfoExtendDto.setYsxz(readOne.getYsxz());
                    gdglinfoExtendDto.setSbkj(readOne.getSbkj());
                    gdglinfoExtendDto.setGddjFileid(fileIds.length() != 0 ? fileIds.toString() : null);
                    String str = JSONObject.toJSONString(gdglinfoExtendDto);
                    try {
                        ResultRespone resultRespone = gdglinfoClient.saveGdglInfoMeter(str);
                        if (resultRespone.getCode() == 1) {
                            readOne.setGdId(resultRespone.getResult().toString());
                            //最后已经登记好的工单信息，修改抄表信息
                            readListUpdate.add(readOne);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (readListUpdate.size() > 0) {
                    readmeterhisService.updateAuditYcbData(readListUpdate);
                } else {
                    return ResultRespone.failed(false, "上报工单失败");
                }
            }
        } else {
            throw new ToflyDeniedException("不满足操作条件");
        }
        return ResultRespone.success(true);
    }

    @Override
    public Bwrksbdatail getSbByRFID(String rfid) {
//        String sbbh = watermeterService.getOne(Wrappers.<Watermeter>lambdaQuery().eq(Watermeter::getRfid, rfid).select(Watermeter::getSid)).getSid();
        Bwrksbdatail info = bwrksbdatailService.getBySbbh(rfid);
        return info;
    }


    @Override
    public IPage getReadHistory(Page page, String yhbh, String startTime, String endTime, String isGeneral, String isCollect) {
        if (StringUtil.isEmpty(isCollect)) {
            isGeneral = "1".equals(isGeneral) ? "1" : "0";
            if ("0".equals(isGeneral)) {
                if (StringUtil.isNotEmpty(startTime)) {
                    String startPlanTime = startTime + " 00:00:00";
                    Date startDate = DateUtil.formatDate(startPlanTime, "yyyy-MM-dd HH:mm:ss");
                    Date endDate = null;
                    String yearMonth = null;
                    //没传递结束时间，默认今天
                    if (StringUtil.isEmpty(endTime)) {
                        endDate = cn.hutool.core.date.DateUtil.endOfDay(new Date());
                    } else {
                        String endPlanTime = endTime + " 23:59:59";
                        endDate = DateUtil.formatDate(endPlanTime, "yyyy-MM-dd HH:mm:ss");
                    }
                    if (DateUtil.parseDateToStr("yyyyMM", endDate).equals(Date8Util.getYearMonth())) {
                        yearMonth = Date8Util.getYearMonth();
                    }
                    Readmeterhis readmeterhis = null;
                    //web端水量分析，查询历史抄表水量信息
                    if (StringUtil.isNotEmpty(yearMonth)) {
                        //本月水量
                        readmeterhis = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getYhbh, yhbh)
                                .eq(Readmeterhis::getMonthPlan, yearMonth).eq(Readmeterhis::getCbbz, "1")
                                .select(Readmeterhis::getYhbh, Readmeterhis::getYhxm, Readmeterhis::getYhdz, Readmeterhis::getCbsl,
                                        Readmeterhis::getScds, Readmeterhis::getBcds, Readmeterhis::getCbyf, Readmeterhis::getBcjjl));
                    }
                    if (StringUtil.isNotNull(readmeterhis)) {
                        page.setSize(page.getSize() - 1);
                    }
                    IPage<Qfcbqfmxls> qfcbqfmxlsIPage = qflsService.page(page, Wrappers.<Qfcbqfmxls>lambdaQuery().eq(Qfcbqfmxls::getYhbh, yhbh)
                            .between(Qfcbqfmxls::getCbrq, startDate, endDate).orderByDesc(Qfcbqfmxls::getCbyf)
                            .select(Qfcbqfmxls::getYhbh, Qfcbqfmxls::getYhxm, Qfcbqfmxls::getYhdz, Qfcbqfmxls::getCbsl,
                                    Qfcbqfmxls::getScds, Qfcbqfmxls::getBcds, Qfcbqfmxls::getCbyf, Qfcbqfmxls::getBcjjl));
                    List<Qfcbqfmxls> qfcbqfmxlsList = new ArrayList<Qfcbqfmxls>();
                    if (StringUtil.isNotNull(readmeterhis)) {
                        Qfcbqfmxls qfcbqfmxls = JSONObject.parseObject(JSONObject.toJSONString(readmeterhis), Qfcbqfmxls.class);
                        if (StringUtil.isNotNull(qfcbqfmxlsIPage)) {
                            List<Qfcbqfmxls> pageRecords = qfcbqfmxlsIPage.getRecords();
                            qfcbqfmxlsList.addAll(pageRecords);
                            qfcbqfmxlsList.add(qfcbqfmxls);
                            //倒序
                            qfcbqfmxlsList.sort(Comparator.comparing(Qfcbqfmxls::getCbyf, Comparator.reverseOrder()));
                        } else {
                            qfcbqfmxlsList.add(qfcbqfmxls);
                        }
                        qfcbqfmxlsIPage.setRecords(qfcbqfmxlsList);
                        qfcbqfmxlsIPage.setTotal(qfcbqfmxlsList.size());
                    }
                    return qfcbqfmxlsIPage;
                }
                //APP端查看
                //获取本月一月一号，排除调本月数据
                Date dateTime = cn.hutool.core.date.DateUtil.beginOfMonth(new Date());
                IPage<Qfcbqfmxls> qfcbqfmxlsIPage = qflsService.getReadHistory(page, yhbh, dateTime);
                return qfcbqfmxlsIPage;
            } else if ("1".equals(isGeneral)) {
                Date endDate = null;
                Date startDate = null;
                if (StringUtil.isNotEmpty(startTime)) {
                    String startPlanTime = startTime + " 00:00:00";
                    startDate = DateUtil.formatDate(startPlanTime, "yyyy-MM-dd HH:mm:ss");
                    //没传递结束时间，默认今天
                    if (StringUtil.isEmpty(endTime)) {
                        endDate = cn.hutool.core.date.DateUtil.endOfDay(new Date());
                    } else {
                        String endPlanTime = endTime + " 23:59:59";
                        endDate = DateUtil.formatDate(endPlanTime, "yyyy-MM-dd HH:mm:ss");
                    }
                }
                //APP端查看  没有本月的
                String yearMonth = Date8Util.getYearMonth();
                return readmeterhisService.page(page, Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getIsGeneral, isGeneral)
                        .ne(StringUtil.isNull(startDate), Readmeterhis::getMonthPlan, yearMonth).eq(Readmeterhis::getCbbz, "1")
                        .eq(Readmeterhis::getYhbh, yhbh).between(StringUtil.isNotNull(startDate), Readmeterhis::getCbrq, startDate, endDate).orderByDesc(Readmeterhis::getCbyf)
                        .select(Readmeterhis::getYhbh, Readmeterhis::getYhxm, Readmeterhis::getYhdz, Readmeterhis::getCbsl, Readmeterhis::getLxdh, Readmeterhis::getBz,
                                Readmeterhis::getScds, Readmeterhis::getBcds, Readmeterhis::getCbyf, Readmeterhis::getBcjjl));
            } else {
                throw new ToflyDeniedException("请正确传递抄表类型");
            }
        } else {
            String startPlanTime = startTime + " 00:00:00";
            Date startDate = DateUtil.formatDate(startPlanTime, "yyyy-MM-dd HH:mm:ss");
            Date endDate = null;
            String yearMonth = null;
            //没传递结束时间，默认今天
            if (StringUtil.isEmpty(endTime)) {
                endDate = cn.hutool.core.date.DateUtil.endOfDay(new Date());
            } else {
                String endPlanTime = endTime + " 23:59:59";
                endDate = DateUtil.formatDate(endPlanTime, "yyyy-MM-dd HH:mm:ss");
            }
            IPage<Readmeterhis> readmeterhisIPage = readmeterhisService.page(page, Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getYhbh, yhbh)
                    .between(Readmeterhis::getCbrq, startDate, endDate).eq(Readmeterhis::getCbbz, "1")
                    .select(Readmeterhis::getYhbh, Readmeterhis::getYhxm, Readmeterhis::getYhdz, Readmeterhis::getCbsl,
                            Readmeterhis::getScds, Readmeterhis::getBcds, Readmeterhis::getCbyf, Readmeterhis::getBcjjl));
            return readmeterhisIPage;
        }

    }

    /**
     * 同比
     * 同比数据平均量与本月抄表水量的比较，超过或者低于的具体百分比
     *
     * @param yhbh     用户编号
     * @param readTime 抄表时间
     * @param bcsl     本次水量
     * @return //如果返回的是 0 ，则代表前三年中存在着没有抄表数据
     */
    private BigDecimal yearOnYear(String yhbh, Date readTime, Long bcsl, Readmeterhis readmeterhis) {
        Long yearonyear1 = readmeterhis.getYearonyear1();
        Long yearonyear2 = readmeterhis.getYearonyear2();
        Long yearonyear3 = readmeterhis.getYearonyear3();
        if (StringUtil.isNull(yearonyear1) || StringUtil.isNull(yearonyear2) || StringUtil.isNull(yearonyear3) || StringUtil.isNull(bcsl)) {
            return null;
        }
        BigDecimal sl1 = new BigDecimal(yearonyear1);
        BigDecimal sl2 = new BigDecimal(yearonyear2);
        BigDecimal sl3 = new BigDecimal(yearonyear3);
        BigDecimal bcslBig = new BigDecimal(bcsl);
        return readDataDispose(sl1, sl2, sl3, bcslBig);
    }

    /**
     * 环比
     * 环比数据平均量与本月抄表水量的比较，超过或者低于的具体百分比
     *
     * @param bcsl 本次水量
     * @return 如果返回的是 0 ，则代表前三次抄表数据中存在着没有抄表数据
     */
    private BigDecimal chainRatio(Readmeterhis readmeterhis, Long bcsl) {
        Long month1 = readmeterhis.getMonth1();
        Long month2 = readmeterhis.getMonth2();
        Long month3 = readmeterhis.getMonth3();
        if (StringUtil.isNull(month1) || StringUtil.isNull(month2) || StringUtil.isNull(month3) || StringUtil.isNull(bcsl)) {
            return null;
        }
        BigDecimal monthBig1 = new BigDecimal(month1);
        BigDecimal monthBig2 = new BigDecimal(month2);
        BigDecimal monthBig3 = new BigDecimal(month3);
        BigDecimal bcslBig = new BigDecimal(bcsl);
        return readDataDispose(monthBig1, monthBig2, monthBig3, bcslBig);
    }

    /**
     * 本次与另外三次抄表数据的平均值比较
     *
     * @param sl1
     * @param sl2
     * @param sl3
     * @param bcslBig
     * @return
     */
    private BigDecimal readDataDispose(BigDecimal sl1, BigDecimal sl2, BigDecimal sl3, BigDecimal bcslBig) {
        BigDecimal zero = ReadData.CALCULATE_ZERO.getYield();
        //前三次水量数据之和
        BigDecimal sum = sl1.add(sl2).add(sl3);
        //除以 3 求平均值用的
        BigDecimal three = ReadData.CALCULATE_THREE.getYield();
        //平均值
        BigDecimal average = sum.divide(three, 2, BigDecimal.ROUND_HALF_UP);
        if (average.compareTo(zero) == 0) {
            return zero;
        }
        //如果平均量小于5，并且本次水量小于5，则系统不做同比
        BigDecimal five = ReadData.CALCULATE_FIVE.getYield();
        if (average.compareTo(five) == -1 && bcslBig.compareTo(five) == -1) {
            return zero;
        }
        //本次水量与平均值的差(绝对值.abs()) 可以得到突升或突降
        BigDecimal diff = average.subtract(bcslBig).abs();
        if (diff.compareTo(zero) == 0) {
            return zero;
        }
        //百分比
        BigDecimal percent = diff.divide(average, 2, BigDecimal.ROUND_HALF_UP);
        return percent;
    }

}
