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

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
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.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.auth.ToflyUser;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.watermeter.config.ComConstans;
import com.tofly.watermeter.config.FilePathBean;
import com.tofly.watermeter.config.ForeignConfig;
import com.tofly.watermeter.custom.dto.WaterAuditDto;
import com.tofly.watermeter.custom.entity.dto.FileRequest;
import com.tofly.watermeter.custom.entity.enums.CbfsEnum;
import com.tofly.watermeter.custom.entity.enums.ReadData;
import com.tofly.watermeter.custom.entity.meterRead.ReadRecord;
import com.tofly.watermeter.custom.entity.webserverbean.ReadUpload;
import com.tofly.watermeter.custom.entity.webserverbean.ReadWrite;
import com.tofly.watermeter.custom.mapper.SynchronousAboutMapper;
import com.tofly.watermeter.custom.service.ReadDataCheckThreeService;
import com.tofly.watermeter.custom.util.SnowflakeUtils;
import com.tofly.watermeter.em.AbnormalEnum;
import com.tofly.watermeter.em.ApiCallEnum;
import com.tofly.watermeter.em.CommonConstant;
import com.tofly.watermeter.em.Constant;
import com.tofly.watermeter.entity.*;
import com.tofly.watermeter.mapper.QfkhjbxxMapper;
import com.tofly.watermeter.service.*;
import com.tofly.watermeter.util.CallAPIUtil;
import com.tofly.watermeter.util.ThreadPoolUtil;
import com.tofly.watermeter.util.service.CallAPIService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author FlashWJL
 * @date 2021/8/30 11:09
 */
@Service
@AllArgsConstructor
public class ReadDataCheckThreeServiceImpl implements ReadDataCheckThreeService {


    private final FileService fileService;
    private final FilePathBean pathBean;
    private final QfcbarithmeticService qfcbarithmeticService;
    private final ReadmeterhisService readmeterhisService;
    private final ReadabnormalService readabnormalService;
    private final ReadupdateService readupdateService;
    private final ForeignConfig foreignConfig;
    private final RedisTemplate redisTemplate;
    private final QfkhjbxxMapper qfkhjbxxMapper;
    private final CallAPIService callAPIService;
    private final SynchronousAboutMapper synchronizationAboutMapper;

    private static final Logger log = LoggerFactory.getLogger(ReadDataCheckThreeServiceImpl.class);

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean readRecord(ReadRecord record, List<MultipartFile> fileList) {
        //防止APP同一时刻重复提交，先把参数做HASH后，用redis锁，并将hash做键水量做值存入redis，
        // 同步森鑫炬接口的时候再次用redis锁，但是与上面的hash区别一下，最后比较两个水量是否一样？一样就不同步了
        String yhbh = record.getYhbh();
        Long bcds = record.getBcds();
        Date time = record.getCbrq();
        String imgUrl = record.getImgUrl();
        Long cbfsCode = record.getCbfsCode();
        Long bcsl = record.getBczl();
        Long scds = record.getScds();
        Long zgl = record.getZgl();
        String bz = record.getBz();
        Double x = record.getX();
        Double y = record.getY();
        String addressState = record.getAddressState();
        String isGeneral = record.getIsGeneral();
        String yearMonth = DateUtil.parseDateToStr("yyyyMM", time);
        String yearMonthDay = DateUtil.parseDateToStr("yyyyMMdd", time);
        String ysxz = record.getYsxzBm();
        String sbkj = record.getSbkj();
        String soleSign = record.getSoleSign();
        //判断抄表是否超过月份
        if (!Date8Util.getYearMonth().equals(yearMonth)) {
            throw new ToflyDeniedException("抄表已过月份，暂不能抄表");
        }
        Integer diffTime = record.getDiffTime();
        //是否离线抄表
        String isOffline = "1".equals(record.getIsOffline()) ? "1" : "0";
        //操作者、操作时间
        ToflyUser toflyUser = SecurityUtils.getUser();
        Date currentDate = Date8Util.getCurrentDate();
        //操作用于确定最终抄表数据录入的人员，离线抄表处有作用，用于追踪谁录入的抄表数据
        Long handlersId = toflyUser.getUserid();
        String handlersName = toflyUser.getRealName();
        if (StringUtil.isEmpty(soleSign)) {
            throw new ToflyDeniedException("请传入抄表唯一标识");
        }
        if (StringUtil.isEmpty(yhbh)) {
            throw new ToflyDeniedException("请传入用户编号");
        }
        if (StringUtil.isEmpty(ysxz)) {
            throw new ToflyDeniedException("请传入用水性质编码");
        }
        if (StringUtil.isEmpty(sbkj)) {
            throw new ToflyDeniedException("请传入水表口径");
        }
        if (StringUtil.isEmpty(isGeneral)) {
            throw new ToflyDeniedException("请传递抄表计划类型");
        }
        if (StringUtil.isNull(time)) {
            throw new ToflyDeniedException("请传入抄表时间");
        }
        if (StringUtil.isNull(cbfsCode)) {
            throw new ToflyDeniedException("请传入抄表方式");
        }
        if (StringUtil.isNull(bcsl)) {
            throw new ToflyDeniedException("请传入本次水量");
        }
        if (StringUtil.isNull(scds)) {
            throw new ToflyDeniedException("请传入上次水量读数");
        }
        if (StringUtil.isNull(bcds)) {
            throw new ToflyDeniedException("请传入本次水量读数");
        }
        //后期新增的用唯一标识查询，同时可以在数据库添加一个唯一索引（暂未添加）；查询抄表用户信息
        Readmeterhis readmeterhis = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery()
                .eq(Readmeterhis::getMonthPlan,yearMonth).eq(Readmeterhis::getSoleSign, soleSign));
        if (StringUtil.isNull(readmeterhis)) {
            throw new ToflyDeniedException("暂无该用户抄表信息或上传数据与当前月份不一致");
        }
        String sblx = readmeterhis.getSblx();
        if (StringUtil.isNull(zgl) && "1".equals(isGeneral) && "3".equals(sblx)) {
            throw new ToflyDeniedException("卡表抄表必须传递总购量");
        }
//        scds = StringUtil.isNotNull(readmeterhis.getScds()) ? readmeterhis.getScds() : 0;
//        bcsl = bcds - scds;
//
//        if (bcsl < 0){
//            bcsl = Long.valueOf(0);
//        }
        //差值
        Long diffValue = null;
        //卡表抄表情况才能计算差值
        if ("1".equals(isGeneral) && "3".equals(sblx)) {
            diffValue = zgl - bcds;
        }
        //是否首次抄表；0：否；1：是
        String isFirst = "1";
        Integer zeroCount = 0;
        Integer upCount = 0;
        Integer downCount = 0;
        Integer equalCount = 0;
        //上次抄表水量
        Long lastCbsl = readmeterhis.getMonth1();
        //升降水量
        Long sjsl = bcsl;
        //只要没有上次读数，则表示第一次抄表
        if (StringUtil.isNotNull(lastCbsl)) {
            sjsl = bcsl - lastCbsl;
            isFirst = "0";
            //比较本次抄表水量与上一次抄表水量
            int compareTo = bcsl.compareTo(lastCbsl);
            //如果有上一次记录（0水量次数、水量连续上升/下降/相同次数）的情况
            //本次上升
            if (compareTo == 1) {
                upCount = readmeterhis.getContinuityUp() + 1;
            }
            //本次下降
            else if (compareTo == -1) {
                downCount = readmeterhis.getContinuityDown() + 1;
            }
            //本次相同
            else if (compareTo == 0) {
                equalCount = readmeterhis.getContinuityEqual() + 1;
            }
        }
        //0水量
        if (bcsl.equals(0L)) {
            zeroCount = readmeterhis.getZeroCount() + 1;
        }
        record.setMonth1(readmeterhis.getMonth1());
        record.setMonth2(readmeterhis.getMonth2());
        record.setMonth3(readmeterhis.getMonth3());
        Long yearonyear1 = readmeterhis.getYearonyear1();
        Long yearonyear2 = readmeterhis.getYearonyear2();
        Long yearonyear3 = readmeterhis.getYearonyear3();
        List<FileRequest> fr = new ArrayList<>();
        //是否同步
        String isSyn = "0";
        // 判断当前是否有文件,则存入返回文件id
        if (null != fileList && fileList.size() > 0) {
            try {
                synchronized (this) {
                    StringBuilder fileIdList = saveFileList(fileList, pathBean.getReadMeter(), "TF_YWPN_READMETERHIS_W");
                    if (fileIdList.length() > 0) {
                        // 根据文件id反射填充对象
                        record.setFileIds(fileIdList.toString());
                    }

                    //文件上传森鑫炬
                    /*Map<String, Object> params = new HashMap<>(2);
                    params.put("appId", 1);
                    params.put("type",1);
                    for (MultipartFile file : fileList) {
                        Map<String, Object> uploadMap = callAPIService.uploadFile(params, file, "/api/v1/rabbit/file/apicloud/upload");
                        if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(uploadMap.get("statusCode")))){
                            fr.add(JSONObject.parseObject(String.valueOf(uploadMap.get("data")), FileRequest.class));
                        }
                    }*/
                }

            } catch (ToflyDeniedException e) {
                throw new ToflyDeniedException("图片上传异常，请重新上传");
            } catch (Exception e) {
                throw new ToflyDeniedException("图片上传失败");
            }
        }else {
            throw new ToflyDeniedException("图片为空，请重新上传");
        }
        String images = null;
        if (CollectionUtil.isNotEmpty(fr)) {
            images = fr.stream().map(FileRequest::getFileId).collect(Collectors.joining(","));
        }
        //修改抄表数据
        readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate()
                .eq(Readmeterhis::getSoleSign, soleSign)
                .set(!StringUtils.isEmpty(images),Readmeterhis::getImages,images)
                .set(Readmeterhis::getScds, scds)
                .set(Readmeterhis::getBcds, bcds).set(Readmeterhis::getCbrq, time)
                .set(Readmeterhis::getCbfsCode, cbfsCode)
                .set(Readmeterhis::getCbsl, bcsl)
                .set(Readmeterhis::getBcjjl, bcsl)
                .set(Readmeterhis::getUpdateScds, scds)
                .set(Readmeterhis::getUpdateBcds, bcds)
                .set(Readmeterhis::getUpdateWater, bcsl)
                .set(StringUtil.isNotNull(zgl), Readmeterhis::getZgl, zgl)
                .set(Readmeterhis::getCbbz, "1")
                .set(StringUtil.isNotNull(diffValue), Readmeterhis::getDiffValue, diffValue)
                .set(Readmeterhis::getIsOffline, isOffline)
                .set(Readmeterhis::getCbyf, yearMonth)
                .set(Readmeterhis::getUploadDay, DateUtil.parseDateToStr("yyyyMMdd", currentDate))
                .set(StringUtil.isNotEmpty(record.getFileIds()), Readmeterhis::getFileid, record.getFileIds())
                .set(Readmeterhis::getIssyn, isSyn)
                .set(StringUtil.isNotEmpty(bz), Readmeterhis::getBz, bz)
                .set(Readmeterhis::getHandlersId, handlersId)
                .set(Readmeterhis::getHandlersTime, currentDate)
                .set(Readmeterhis::getHandlersName, handlersName)
                .set(StringUtil.isNotEmpty(imgUrl), Readmeterhis::getImgUrl, imgUrl)
                .set(StringUtil.isNotNull(x), Readmeterhis::getX, x)
                .set(StringUtil.isNotNull(y), Readmeterhis::getY, y)
                .set(StringUtil.isNotEmpty(addressState), Readmeterhis::getAddressState, addressState)
                .set(Readmeterhis::getZeroCount, zeroCount)
                .set(Readmeterhis::getIsfirst, isFirst)
                .set(Readmeterhis::getContinuityUp, upCount)
                .set(StringUtil.isNotNull(diffTime), Readmeterhis::getDiffTime, diffTime)
                .set(Readmeterhis::getContinuityDown, downCount)
                .set(Readmeterhis::getContinuityEqual, equalCount)
                .set(Readmeterhis::getUpdateUser, SecurityUtils.getUserId())
                .set(Readmeterhis::getUpdateDate, new Date())
                .set(Readmeterhis::getSjsl, sjsl));

        if (!"1".equals(isGeneral) && !"3".equals(sblx)) {
            //保存在森鑫炬
            ReadUpload upload = new ReadUpload();
            upload.setReadTime(time.getTime());
            upload.setUserId(readmeterhis.getUserId());
            upload.setBeginScale(scds);
            //判断起度是否大于止读；如果起度大于止读，则止读作为为起度数同步
            if (scds.compareTo(bcds) > 0) {
                upload.setEndScale(scds);
                upload.setAmount("0");
            } else {
                upload.setEndScale(bcds);
                upload.setAmount(String.valueOf(bcsl));
            }
            upload.setKtId(readmeterhis.getSoleSign());
            upload.setReadStatus(1);
            upload.setChannel(2);
            upload.setType(1);
            if (!StringUtils.isEmpty(images)) {
                upload.setImages(images);
            }
            record.setSblx(readmeterhis.getSblx());
            //异步执行同步森鑫炬抄表数据
            sysSXJCbData(upload, yhbh, yearMonth, record, zeroCount, upCount, downCount, equalCount, isFirst,
                    yearonyear1, yearonyear2, yearonyear3);
        }
        return true;
    }

    /**
     * 异步执行同步更新森鑫炬抄表数据
     *
     * @param upload       同步森鑫炬实体
     * @param yhbh        用户编号
     * @param yearMonth   月份
     * @param record      抄表信息
     * @param zeroCount   0水量个数
     * @param upCount     连续上升个数
     * @param downCount   连续下降个数
     * @param equalCount  相同个数
     * @param isFirst     是否首次抄表；0：否；1：是
     * @param yearonyear1 同比1
     * @param yearonyear2 同比2
     * @param yearonyear3 同比3
     */
    @Async
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean sysSXJCbData(ReadUpload upload, String yhbh, String yearMonth, ReadRecord record, Integer zeroCount, Integer upCount,
                                Integer downCount, Integer equalCount, String isFirst,
                                Long yearonyear1, Long yearonyear2, Long yearonyear3) {
        String isGeneral = record.getIsGeneral();
        String sblx = record.getSblx();
        log.info("===================》抄表数据同步开始：" + upload);
        //卡表计划或者类型是卡表的水表不同步
        if (!"1".equals(isGeneral) && !sblx.contains("4")) {
            ThreadPoolUtil.executorService.execute(() -> {
                Map map = null;
                //新增森鑫炬返回消息
                String sxjMessage;
                //是否同步
                String isSyn = "0";
                try {
                    map = callAPIService.getApiResult(upload, "/api/v1/bat/user/read/detail/upload");
                    log.info("============》抄表同步结果为" + map);
                } catch (Exception e) {
                    log.info("用户编号：" + yhbh + "，进行同步森鑫炬接口时异常");
                    e.printStackTrace();
                }
                //如果返回成功则是 600 编码
                if (map != null) {
                    if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(map.get("statusCode")))){
                        log.info("===================》抄表数据已同步");
                        isSyn = "1";
                        //同步成功后才可以走算法
                        //抄表异常算法
                        try {
                            abnormalReadDataCheck(record, zeroCount, upCount, downCount, equalCount, isFirst,
                                    yearonyear1, yearonyear2, yearonyear3, yearMonth);
                        } catch (Exception e) {
                            log.info("用户编号：" + yhbh + "，进行抄表算法模型异常");
                            e.printStackTrace();
                        }
                    }
                    if (StringUtil.isNotNull(map.get("message"))){
                        Long sysSbqd = null;
                        sxjMessage = map.get("message").toString();
                        log.info("===================》抄表数据同步结束：" + sxjMessage);
                        try {
                            if (sxjMessage.contains("起度大于止度")) {
                                //存在分隔符后面没有读数的情况
                                int lastIndexOf = sxjMessage.lastIndexOf("|");
                                if (lastIndexOf != -1) {
                                    String qdInfo = sxjMessage.substring(lastIndexOf);
                                    if (StringUtil.isNotEmpty(qdInfo)) {
                                        //森鑫炬返回的系统起度
                                        String sbqd = qdInfo.substring(1);
                                        if (StringUtil.isNotEmpty(sbqd)) {
                                            sysSbqd = Long.parseLong(sbqd);
                                        }
                                    }
                                }
                                //还存在没有返回读数的情况
                                if ("起度大于止度".equals(sxjMessage)) {
                                    sysSbqd = upload.getBeginScale();
                                }
                            }
                        } catch (Exception e) {
                            log.info("用户编号：" + yhbh + "，获取同步原因、水量信息异常");
                            e.printStackTrace();
                        }
                        //修改抄表历史数据
                        readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(upload.getKtId()), Readmeterhis::getSoleSign, upload.getKtId())
                                .eq(Readmeterhis::getYhbh, yhbh).eq(Readmeterhis::getMonthPlan, yearMonth)
                                .set(Readmeterhis::getIssyn, isSyn)
                                .set(StringUtil.isNotNull(sysSbqd), Readmeterhis::getSxjSbqd, sysSbqd)
                                .set(Readmeterhis::getUploadTime, Date8Util.getCurrentDate())
                                .set(StringUtil.isNotEmpty(sxjMessage), Readmeterhis::getSxjmessage, sxjMessage));
                    }
                }

            });
        }
        return true;
    }


    /**
     * 抄水量异常验证
     *
     * @param record 异常信息说明
     * @return
     */
    @Override
    public String readDataCheck(ReadRecord record, String isGeneral) {
        String ysxz = record.getYsxzBm();
        //本次增量让APP端传递，要不然又要去走一次数据库查询上次读数再相减
        Long bczl = record.getBczl();
        String sbkj = record.getSbkj();
        Long month1 = record.getMonth1();
        Long month2 = record.getMonth2();
        Long month3 = record.getMonth3();
        if (StringUtil.isEmpty(ysxz)) {
            throw new ToflyDeniedException("请传递用水性质");
        }
        if (StringUtil.isNull(bczl)) {
            throw new ToflyDeniedException("请填写本次使用水量");
        }
        if (StringUtil.isEmpty(sbkj)) {
            throw new ToflyDeniedException("请传递水表口径");
        }
//        if (StringUtil.isNull(month1) || StringUtil.isNull(month2) || StringUtil.isNull(month3)) {
//            throw new ToflyDeniedException("请传递前三次用水量");
//        }

        //查询算法配置表
        List<Qfcbarithmetic> qfcbarithmeticList = qfcbarithmeticService.list(Wrappers.<Qfcbarithmetic>lambdaQuery()
                .eq(Qfcbarithmetic::getIsForbidden, "1")
                .select(Qfcbarithmetic::getArithType, Qfcbarithmetic::getStartKjcode,
                        Qfcbarithmetic::getEndKjcode, Qfcbarithmetic::getArithCount,
                        Qfcbarithmetic::getIsForbidden, Qfcbarithmetic::getIscomment));
        //根据算法类型将配置表分组
        Map<String, List<Qfcbarithmetic>> arithMap = qfcbarithmeticList.stream().collect(Collectors.groupingBy(Qfcbarithmetic::getArithType));

        //算法提醒基础
        List<Qfcbarithmetic> avergeArith = arithMap.get("水量平均值");
        if (StringUtil.isNull(avergeArith)) {
            return null;
        }
        Qfcbarithmetic qfcbarithmetic = avergeArith.get(0);
        //配置的水量吨位，超过才走算法提醒
        BigDecimal arithCount = new BigDecimal(qfcbarithmetic.getArithCount());

        //第一类型算法：进行 0水量模型 判断
        List<Qfcbarithmetic> zeroType = arithMap.get("0水量模型");
        //存储前几次抄表，顺序是存储抄表月份倒序
        List<Qfcbqfmxls> qfcbqfmxlsList = null;
        //有可能都禁用的状态，就没有 为null
        if (StringUtil.isNotNull(zeroType)) {
            //0水量模型配置次数；由于是连续未抄表的次数，那么本次抄表也算一次，所以需要减 1 次
            Integer count = zeroType.get(0).getArithCount() - 1;
            //当配置的是1次，那么本次如果抄表水量为 0，就算异常
            if (count == 0) {
                //本次如果抄表水量为 0 ，也表示异常
                if (bczl == 0L) {
                    return zeroType.get(0).getIscomment();
                }
            } else {
                //本次抄表水量为 0 ，并且查询出来的条数要与配置数相同
                if (bczl == 0L && month1 == 0L && month2 == 0L) {
                    //"0水量模型：连续" + (count + 1) + "次水量为0";
                    return zeroType.get(0).getIscomment();
                }
            }
        }

        //前三次水量数据
        BigDecimal bigMonth1 = null;
        if (StringUtil.isNotNull(record.getMonth1())) {
            bigMonth1 = new BigDecimal(record.getMonth1());
        }
        BigDecimal bigMonth2 = null;
        if (StringUtil.isNotNull(record.getMonth2())) {
            bigMonth2 = new BigDecimal(record.getMonth2());
        }
        BigDecimal bigMonth3 = null;
        if (StringUtil.isNotNull(record.getMonth3())) {
            bigMonth3 = new BigDecimal(record.getMonth3());
        }
        BigDecimal avergeSl = null;
        //前三次平均水量
        if (StringUtil.isNotNull(bigMonth1) && StringUtil.isNotNull(bigMonth2) && StringUtil.isNotNull(bigMonth3)) {
            avergeSl = bigMonth1.add(bigMonth2).add(bigMonth3).divide(ReadData.CALCULATE_THREE.getYield(), 2, BigDecimal.ROUND_HALF_UP);
        } else if (StringUtil.isNotNull(bigMonth1) && StringUtil.isNotNull(bigMonth2)) {
            avergeSl = bigMonth1.add(bigMonth2).divide(ReadData.CALCULATE_TWO.getYield(), 2, BigDecimal.ROUND_HALF_UP);
        } else if (StringUtil.isNotNull(bigMonth1)) {
            avergeSl = bigMonth1;
        }
        if (StringUtil.isNotNull(avergeSl)) {
            //求前三次水量平均值 平均水量大于配置水量才能走下面的异常提醒
            boolean flag = avergeSl.compareTo(arithCount) == 1;
            if (flag) {
                //第二类型算法：根据用水性质、口径、升降幅度比例判断
                //上次抄表水量
                Long lastCbsl = month1;
                //如果上次抄表水量为 0 就不进行判断
                if (lastCbsl != 0) {
                    BigDecimal sl1 = new BigDecimal(lastCbsl);
                    //计算：本次水量与上周期水量跌幅
                    BigDecimal bcslBig = new BigDecimal(bczl);
                    //本次水量与上周期水量的差(绝对值.abs()) 可以得到水量升降幅度
                    BigDecimal diff = sl1.subtract(bcslBig).abs();
                    //本次水量与上次水量的升降幅度指数
                    BigDecimal percent = diff.divide(sl1, 2, BigDecimal.ROUND_HALF_UP).multiply(ReadData.CALCULATE_HUNDRED.getYield());
                    //水表口径编码
                    Integer sbkjCode = Integer.parseInt(sbkj.substring(2));
                    //根据用水性质判断是否 居民用水 非居民用水 特种用水
                    //居民用水
                    if ("10000".equals(ysxz) || "10004".equals(ysxz) || "10060".equals(ysxz) ||
                            "10020".equals(ysxz) || "10024".equals(ysxz) || "10027".equals(ysxz) ||
                            "10033".equals(ysxz) || "10034".equals(ysxz)) {
                        //获取居民用水类型配置
                        List<Qfcbarithmetic> residentType = arithMap.get("居民用水");
                        //如果禁用的状态，就没有 为null
                        if (StringUtil.isNotNull(residentType)) {
                            //根据配置动态判断
                            String abnormalInfo = dynamic(percent, sbkjCode, residentType);
                            if (StringUtil.isNotNull(abnormalInfo)) {
                                return abnormalInfo;
                            }
                        }
                    }
                    //特种用水
                    else if ("10005".equals(ysxz) || "10006".equals(ysxz) || "10025".equals(ysxz) ||
                            "10026".equals(ysxz) || "10031".equals(ysxz) || "10032".equals(ysxz)) {
                        //获取特种用水类型配置
                        List<Qfcbarithmetic> specialType = arithMap.get("特种用水");
                        //如果禁用的状态，就没有 为null
                        if (StringUtil.isNotNull(specialType)) {
                            //根据配置动态判断
                            String abnormalInfo = dynamic(percent, sbkjCode, specialType);
                            if (StringUtil.isNotNull(abnormalInfo)) {
                                return abnormalInfo;
                            }
                        }
                    }
                    //非居民用水
                    else {
                        //获取特种用水类型配置
                        List<Qfcbarithmetic> specialType = arithMap.get("非居民用水");
                        //如果禁用的状态，就没有 为null
                        if (StringUtil.isNotNull(specialType)) {
                            //根据配置动态判断
                            String abnormalInfo = dynamic(percent, sbkjCode, specialType);
                            if (StringUtil.isNotNull(abnormalInfo)) {
                                return abnormalInfo;
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultRespone updateCbsl(ReadRecord record) {

//        String month = record.getMonth();
        Long scds = record.getScds();
        Long bcds = record.getBcds();
        Long bcsl = record.getBczl();
        String soleSign = record.getSoleSign();
        if (StringUtil.isNull(scds)) {
            throw new ToflyDeniedException("请传递最新上次读数");
        } else if (StringUtil.isNull(bcds)) {
            throw new ToflyDeniedException("请传递最新本次读数");
        } else if (StringUtil.isNull(bcsl)) {
            throw new ToflyDeniedException("请传递最新本次水量");
        } else if (StringUtil.isEmpty(soleSign)) {
            throw new ToflyDeniedException("请传递抄表唯一标识");
        }
        String month = Date8Util.getYearMonth();
        Readmeterhis readmeterhis = readmeterhisService.getOne(Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getSoleSign, soleSign));
        String monthPlan = readmeterhis.getMonthPlan();
        if (!month.equals(monthPlan)) {
            throw new ToflyDeniedException("只能修改当月水量信息");
        }
        //判断数据
        String cbbz = readmeterhis.getCbbz();
        String isGeneral = readmeterhis.getIsGeneral();
        if ("0".equals(cbbz)) {
            throw new ToflyDeniedException("该用户没有进行抄表，不能随意更改水量数据信息");
        }
        //保存历史数据
        Readupdate readupdate = new Readupdate();
        readupdate.setYhbh(readmeterhis.getYhbh());
        readupdate.setYhxm(readmeterhis.getYhxm());
        readupdate.setYhdz(readmeterhis.getYhdz());
        readupdate.setLxdh(readmeterhis.getLxdh());
        readupdate.setNewBcds(bcds);
        readupdate.setNewScds(scds);
        readupdate.setNewCbsl(bcsl);
        readupdate.setOldScds(readmeterhis.getScds());
        readupdate.setOldBcds(readmeterhis.getBcds());
        readupdate.setOldCbsl(readmeterhis.getCbsl());
        readupdate.setSoleSign(soleSign);
        readupdate.setUpdateBz(record.getBz());
        Long newZgl = null;
        Long newDiffValue = null;
        //卡表修改的情况
        if ("1".equals(isGeneral)) {
            readupdate.setOldZgl(readmeterhis.getZgl());
            readupdate.setOldDiffValue(readmeterhis.getDiffValue());
            newZgl = readmeterhis.getZgl();
            readupdate.setNewZgl(newZgl);
            newDiffValue = newZgl - bcds;
            //差值等于：总购量减本次最新读数
            readupdate.setNewDiffValue(newDiffValue);
        }
        readupdate.setMonth(month);
        readupdate.setSourceType("0");
        readupdateService.save(readupdate);
        Long id = readupdate.getId();
        readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(Readmeterhis::getSoleSign, soleSign)
                .set(Readmeterhis::getScds, scds).set(Readmeterhis::getBcds, bcds).set(Readmeterhis::getCbsl, bcsl)
                .set(StringUtil.isNotNull(newZgl), Readmeterhis::getZgl, newZgl).set(StringUtil.isNotNull(newDiffValue), Readmeterhis::getDiffValue, newDiffValue)
                .set(Readmeterhis::getUpdateScds, readmeterhis.getScds()).set(Readmeterhis::getUpdateBcds, readmeterhis.getBcds())
                .set(Readmeterhis::getUpdateWater, readmeterhis.getCbsl()).set(Readmeterhis::getIsUpdateid, id)
                .set(Readmeterhis::getIsUpdatecbsl, "1"));
        return ResultRespone.success(true, "修改成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultRespone synCbsl(String yhbhS, String monthPlan, String isGeneral) {
        if (StringUtil.isEmpty(yhbhS)) {
            throw new ToflyDeniedException("请选择用户同步");
        }
        List<String> yhbhList = Arrays.asList(yhbhS.split(","));
      /*  if (yhbhList.size() >= 1001) {
            throw new ToflyDeniedException("同步数据太多，不能超过1000条，请仔细检查后再同步");
        }*/
        int size = yhbhList.size();
        //向上取整
        int count = (int) Math.ceil((double) size / 20d);

        for (int i = 0; i < count; i++) {
//        while (i < count) {
            int startIndex = i * 20;
            int endIndex = 20 + i * 20;
            List<String> subList;
            //判断是否截取的最后一次数据，如果是最后一次数据，则不能使用endIndex这个参数去截取了，有可能会存在endIndex参数值超过索引最大值的情况
            if (i < count - 1) {
                subList = yhbhList.subList(startIndex, endIndex);
            } else {
                //分段采取最后的数据
                subList = yhbhList.subList(startIndex, yhbhList.size());
            }
            List<Readmeterhis> readmeterhisList = readmeterhisService.list(Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getMonthPlan, monthPlan)
                    .in(Readmeterhis::getYhbh, subList).eq(Readmeterhis::getIssyn, "0")
                    .select(Readmeterhis::getYhbh, Readmeterhis::getYhxm, Readmeterhis::getYsxz, Readmeterhis::getCbsl, Readmeterhis::getSbkj, Readmeterhis::getScds,
                            Readmeterhis::getBcds, Readmeterhis::getCbrq, Readmeterhis::getIsGeneral, Readmeterhis::getCbfsCode, Readmeterhis::getMonth1, Readmeterhis::getSbbh,
                            Readmeterhis::getMonth2, Readmeterhis::getIsfirst, Readmeterhis::getMonthPlan, Readmeterhis::getSblx, Readmeterhis::getSxjmessage,
                            Readmeterhis::getMonth3, Readmeterhis::getYearonyear1, Readmeterhis::getYearonyear2, Readmeterhis::getYearonyear3, Readmeterhis::getSxjSbqd,
                            Readmeterhis::getZeroCount, Readmeterhis::getContinuityUp, Readmeterhis::getContinuityDown, Readmeterhis::getContinuityEqual,
                            Readmeterhis::getSoleSign,Readmeterhis::getUserId,Readmeterhis::getImages));
            for (Readmeterhis readmeterhis : readmeterhisList) {
                //异常算法参数
                ReadRecord record = new ReadRecord();
                record.setSoleSign(readmeterhis.getSoleSign());
                record.setSblx(readmeterhis.getSblx());
                record.setYsxzBm(readmeterhis.getYsxz());
                record.setBczl(readmeterhis.getCbsl());
                record.setYhbh(readmeterhis.getYhbh());
                record.setSbkj(readmeterhis.getSbkjName());
                record.setCbrq(readmeterhis.getCbrq());
                record.setIsGeneral(readmeterhis.getIsGeneral());
                record.setCbfsCode(readmeterhis.getCbfsCode());
                record.setMonth1(readmeterhis.getMonth1());
                record.setMonth2(readmeterhis.getMonth2());
                record.setMonth3(readmeterhis.getMonth3());
                Integer zeroCount = readmeterhis.getZeroCount();
                Integer upCount = readmeterhis.getContinuityUp();
                Integer downCount = readmeterhis.getContinuityDown();
                Integer equalCount = readmeterhis.getContinuityEqual();
                String isFirst = readmeterhis.getIsfirst();
                Long yearonyear1 = readmeterhis.getYearonyear1();
                Long yearonyear2 = readmeterhis.getYearonyear2();
                Long yearonyear3 = readmeterhis.getYearonyear3();

                //保存在森鑫炬
                ReadUpload upload = new ReadUpload();
                upload.setReadTime(readmeterhis.getCbrq().getTime());
                upload.setUserId(readmeterhis.getUserId());
                upload.setKtId(readmeterhis.getSoleSign());
                upload.setReadStatus(1);
                upload.setChannel(2);
                upload.setType(1);
                upload.setImages(readmeterhis.getImages());

                if (!StringUtils.isEmpty(readmeterhis.getSxjmessage()) && readmeterhis.getSxjmessage().contains("起度大于止度") && readmeterhis.getSxjmessage().lastIndexOf("|") != -1) {
                    upload.setBeginScale(readmeterhis.getSxjSbqd());
                    upload.setEndScale(readmeterhis.getSxjSbqd() > readmeterhis.getBcds() ? readmeterhis.getSxjSbqd() : readmeterhis.getBcds());
                    upload.setAmount("0");
                    //增加操作记录
                    ReadRecord record2 = new ReadRecord();
                    record2.setSoleSign(readmeterhis.getSoleSign());
                    record2.setBczl(0L);
                    record2.setBcds(readmeterhis.getBcds());
                    record2.setScds(readmeterhis.getSxjSbqd());
                    this.updateCbsl(record2);
                } else {
                    upload.setBeginScale(readmeterhis.getScds());
                    //判断起度是否大于止读；如果起度大于止读，则止读作为为起度数同步
                    if (readmeterhis.getScds().compareTo(readmeterhis.getBcds()) > 0) {
                        upload.setEndScale(readmeterhis.getScds());
                        upload.setAmount("0");
                    } else {
                        upload.setEndScale(readmeterhis.getBcds());
                        upload.setAmount(String.valueOf(readmeterhis.getCbsl()));
                    }
                }
                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(upload.getKtId()), Readmeterhis::getSoleSign, upload.getKtId())
                        .eq(Readmeterhis::getSoleSign, readmeterhis.getSoleSign())
                        .set(Readmeterhis::getUpdateUser, SecurityUtils.getUserId())
                        .set(Readmeterhis::getUpdateDate, new Date()));

                sysSXJCbData(upload, readmeterhis.getYhbh(), readmeterhis.getMonthPlan(), record,
                        zeroCount, upCount, downCount, equalCount, isFirst, yearonyear1, yearonyear2, yearonyear3);
            }
        }

        return ResultRespone.success(true, "成功");
    }

    @Override
    public ResultRespone cbsf(String yearMonth) {
//        List<String> lis = Arrays.asList("975", "992");
        List<Readmeterhis> readmeterhisList = readmeterhisService.list(Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getCbbz, "1").eq(Readmeterhis::getMonthPlan, yearMonth));
        for (Readmeterhis readmeterhis : readmeterhisList) {
            //异常算法参数
            ReadRecord record = new ReadRecord();
            record.setYsxzBm(readmeterhis.getYsxz());
            record.setBczl(readmeterhis.getCbsl());
            record.setYhbh(readmeterhis.getYhbh());
            record.setSbkj(readmeterhis.getSbkjName());
            record.setCbrq(readmeterhis.getCbrq());
            record.setIsGeneral(readmeterhis.getIsGeneral());
            record.setCbfsCode(readmeterhis.getCbfsCode());
            record.setMonth1(readmeterhis.getMonth1());
            record.setMonth2(readmeterhis.getMonth2());
            record.setMonth3(readmeterhis.getMonth3());
            record.setSoleSign(readmeterhis.getSoleSign());
            Integer zeroCount = readmeterhis.getZeroCount();
            Integer upCount = readmeterhis.getContinuityUp();
            Integer downCount = readmeterhis.getContinuityDown();
            Integer equalCount = readmeterhis.getContinuityEqual();
            String isFirst = readmeterhis.getIsfirst();
            Long yearonyear1 = readmeterhis.getYearonyear1();
            Long yearonyear2 = readmeterhis.getYearonyear2();
            Long yearonyear3 = readmeterhis.getYearonyear3();
            try {
                //可能会有算法异常
                String checkReuslt = abnormalReadDataCheck(record, zeroCount, upCount, downCount, equalCount, isFirst,
                        yearonyear1, yearonyear2, yearonyear3, yearMonth);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }


    @Override
    public ResultRespone soleSign(String yearMonth) {
        int count = readmeterhisService.count(Wrappers.<Readmeterhis>lambdaQuery().eq(Readmeterhis::getMonthPlan, yearMonth)
                .select(Readmeterhis::getYhbh));
        if (count > 0) {
            int size = (int) Math.ceil(Double.valueOf(count) / 200d);
            for (int i = 0; i < size; i++) {
                Page page = new Page();
                page.setCurrent(i + 1);
                page.setSize(200);
                IPage<Readmeterhis> readmeterhisIPage = readmeterhisService.page(page, Wrappers.<Readmeterhis>lambdaQuery()
                        .eq(Readmeterhis::getMonthPlan, yearMonth).select(Readmeterhis::getYhbh));
                List<String> yhbhList = readmeterhisIPage.getRecords().stream().map(Readmeterhis::getYhbh).collect(Collectors.toList());
                if (StringUtil.isNotNull(yhbhList) && yhbhList.size() > 0) {
                    List<Readmeterhis> readmeterhisArrayList = new ArrayList<>();
                    for (String s : yhbhList) {
                        Readmeterhis readmeterhis1 = new Readmeterhis();
                        readmeterhis1.setYhbh(s);
                        readmeterhis1.setSoleSign(SnowflakeUtils.getId(foreignConfig.getDate(), foreignConfig.getWorkerId(), ComConstans.SNOWFLAKE_READ_TYPE).toString());
                        readmeterhisArrayList.add(readmeterhis1);
                    }
                    readmeterhisService.updateSoleSign(readmeterhisArrayList, yearMonth);
                }
            }
        }
        return ResultRespone.success(true);
    }


    /**
     * 根据配置中信息；统一判断对应口径的用水量升降幅度是否在范围内
     *
     * @param percent  本次用水量与上次用水量的升降幅度指数
     * @param sbkjCode 水表口径code
     * @param type     具体算法配置类型（居民用水、非居民用水、特种用水）
     * @return 返回异常信息
     */
    private String dynamic(BigDecimal percent, Integer sbkjCode, List<Qfcbarithmetic> type) {
        //根据配置动态判断
        for (Qfcbarithmetic resident : type) {
            Integer startKjcode = resident.getStartKjcode();
            Integer endKjcode = resident.getEndKjcode();
            //算法的配置升降幅度指数
            BigDecimal ratioCount = new BigDecimal(resident.getArithCount());
            //异常提示
            String comment = resident.getIscomment();
            //在配置范围内的水表口径
            if (startKjcode <= sbkjCode && endKjcode >= sbkjCode) {
                //比较配置比例
                if (percent.compareTo(ratioCount) == 1) {
                    //异常内容
                    return comment + ",本次升降幅度为：" + percent + "%";
                }
            }
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class )
    public StringBuilder saveFileList(List<MultipartFile> fileList, String filePathBean, String tableName) {
        List<String> filePathList = new ArrayList<>();
        Long userId = SecurityUtils.getUserId();
        List<File> saveFileList = new ArrayList<>();
        Long fileMaxId = synchronizationAboutMapper.getMaxId("TF_YWPN_FILE_W");
        for (MultipartFile file : fileList) {
            //文件名
            String fileName = file.getOriginalFilename();
            if (!"".equals(fileName)) {
                //文件路径
                String filePath = filePathBean + IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf("."));
                filePathList.add(filePath);
                boolean b = FtpUtil.uploadFile2Ftp(file, filePath);
                log.info("FTP保存图片是否成功：" + b);
                if (b) {
                    File localFile = new File();
                    localFile.setFilePath(filePath);
                    localFile.setFileName(fileName);
                    localFile.setOtherName(IdWorker.getIdStr() + fileName.substring(fileName.lastIndexOf(".")));
                    localFile.setTableName(tableName);//关联表名称
                    //获取后缀
                    String suffix = fileName.substring(fileName.lastIndexOf("."));
                    localFile.setFileFormat(suffix);
                    localFile.setFileSize(file.getSize() + "kb");
                    localFile.setId(fileMaxId);
                    localFile.setCreateTime(Date8Util.getCurrentDate());
                    localFile.setCreateUser(userId);
                    saveFileList.add(localFile);
                    fileMaxId ++;
                } else {
                    if (filePathList.size() > 1) {
                        for (int i = 0; i < filePathList.size() - 1; i++) {
                            //需要移除之前上传的文件
                            filePathList.forEach(FtpUtil::deleteFile);
                        }
                    }
                    throw new ToflyDeniedException("图片上传异常，请重新上传");
                }
            }
        }
        if ( CollectionUtils.isNotEmpty(saveFileList)){
            log.info("保存文件信息：" + saveFileList);
            synchronizationAboutMapper.insertFile(saveFileList);
            StringBuilder fileIds = new StringBuilder();
            saveFileList.forEach(f -> fileIds.append(f.getId()).append(Constant.CSV));
            if (fileIds.length() > 0) {
                return fileIds.deleteCharAt(fileIds.length() - 1);
            }
            return fileIds;
        }else {
            return null;
        }
    }

    /**
     * 利用redis获取文件最大ID测试
     */
    @Override
    public void testRead() {
        String lockPrefix = CommonConstant.READ_REDIS_LOCK_PREFIX.getLockPrefix();
        String lockValue = CommonConstant.READ_REDIS_LOCK_VALUE.getLockPrefix();
        String readMaxId = CommonConstant.READ_REDIS_MAX_ID.getLockPrefix();
        Long maxId = null;
        //这个是redis封装的带锁的情况
        RedisAtomicLong counter = new RedisAtomicLong(readMaxId, redisTemplate.getConnectionFactory());
        maxId = counter.incrementAndGet();
        if (maxId == 1) {
            Integer fileMaxId = fileService.getMaxId();
            counter.set(fileMaxId);
            counter.expire(30, TimeUnit.SECONDS);
            maxId = counter.incrementAndGet();
        }
        log.info("MAXid:::=================" + maxId);

        //首先给redis加锁，然后设置过期时间，然后去值是否等于1，如果是1则代表第一次进来，那么就查询数据库最大ID，同时将最大ID加1后压到redis里面，以便于下次直接获取值的时候不重新走数据库，而走redis获取
        //两个key是不一样的，一个加锁的key，一个redis获取自增的key
        //第一步获取  获取不到则设置
        //这里加个循环，其实也就是锁了，一直等待
//        if (redisTemplate.opsForValue().setIfAbsent(lockPrefix, lockValue, 1, TimeUnit.MINUTES)) {
//            //获取是否有最大ID了，如果没有则返回1，那么我们就去数据库查询最大ID是多少，定一个失效时间，这样只要在这段时间内都会从redis里面获取最大ID，避免对数据库频繁查询最大ID , 1 , TimeUnit.MINUTES
//            maxId = redisTemplate.opsForValue().increment(readMaxId, 1);
//            if (maxId == 1) {
//                //去数据库查询最大ID
//                Integer fileMaxId = fileService.getMaxId();
//                redisTemplate.delete(readMaxId);
//                redisTemplate.opsForValue().set(readMaxId, fileMaxId, 1, TimeUnit.MINUTES);
//                maxId = redisTemplate.opsForValue().increment(readMaxId, 1);
//                log.info("MAXid:::"+maxId);
//            }
//            //执行业务代码
//            //删除key
//            redisTemplate.opsForValue().getOperations().delete(lockPrefix);
//        }else {
//            log.info("未进入");
//        }
    }

    /**
     * 抄水量异常验证
     *
     * @param record     抄表信息
     * @param zeroCount  0水量个数
     * @param upCount    连续上升个数
     * @param downCount  连续下降个数
     * @param equalCount 相同个数
     * @param isFirst    是否首次抄表；0：否；1：是
     * @return 异常信息
     */
    public String abnormalReadDataCheck(ReadRecord record, Integer zeroCount, Integer upCount,
                                        Integer downCount, Integer equalCount, String isFirst,
                                        Long yearonyear1, Long yearonyear2, Long yearonyear3,
                                        String yearMonth) {
        String ysxz = record.getYsxzBm();
        //本次增量让APP端传递，要不然又要去走一次数据库查询上次读数再相减
        Long bczl = record.getBczl();
        String sbkj = record.getSbkj();
        String yhbh = record.getYhbh();
        Date readTime = record.getCbrq();
        String isGeneral = record.getIsGeneral();
        String soleSign = record.getSoleSign();
        Long cbfsCode = record.getCbfsCode();
        //估水、换表、首次查抄均默认配置
        //估水模型
        if (cbfsCode.equals(CbfsEnum.GC.getCbfsId())) {
            //说明
            String describe = "估水信息模型：因各种原因进行估水方式抄表";
            //修改抄表类型原因
            Long typeId = AbnormalEnum.GSMX.getTypeId();
            //.eq(Readmeterhis::getYhbh, yhbh).eq(Readmeterhis::getIsGeneral, isGeneral).eq(Readmeterhis::getMonthPlan, yearMonth)
            readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate()
                    .eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .set(Readmeterhis::getAbnomalId, typeId)
                    .set(Readmeterhis::getShbz, "0")
                    .set(Readmeterhis::getAuditReason, describe));
            return describe;
        }
        //换表模型
        if (cbfsCode.equals(CbfsEnum.BMDZJHB.getCbfsId()) || cbfsCode.equals(CbfsEnum.ZCZJHB.getCbfsId()) || cbfsCode.equals(CbfsEnum.YHBRQGZHB.getCbfsId()) || cbfsCode.equals(CbfsEnum.WHBRQGZHB.getCbfsId())) {
            //说明
            String describe = "换表信息模型：在上次抄表后，本次抄表前，水表进行了更换操作";
            //修改抄表类型原因
            Long typeId = AbnormalEnum.HBMX.getTypeId();
            readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                    .set(Readmeterhis::getAbnomalId, typeId)
                    .set(Readmeterhis::getShbz, "0")
                    .set(Readmeterhis::getAuditReason, describe));
            return describe;
        }
        //首次查抄水量
        if ("1".equals(isFirst)) {
            Long typeId = AbnormalEnum.SCSLMX.getTypeId();
            //首次抄表水量为0
            if (bczl.equals(0L)) {
               /* String describe = "首次水量模型：首次抄表水量为0";
                //修改抄表类型原因
                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                        .set(Readmeterhis::getAbnomalId, typeId)
                        .set(Readmeterhis::getShbz, "0")
                        .set(Readmeterhis::getAuditReason, describe));
                return describe;*/
            }
            //首次非正常抄表方式
            else {
                if (!cbfsCode.equals(66L)) {
                    String describe = "首次水量模型：首次非正常抄表方式";
                    //修改抄表类型原因
                    readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                            .set(Readmeterhis::getAbnomalId, typeId)
                            .set(Readmeterhis::getShbz, "0")
                            .set(Readmeterhis::getAuditReason, describe));
                    return describe;
                }
            }
        }
        //前三次水量数据
        BigDecimal month1 = null;
        if (StringUtil.isNotNull(record.getMonth1())) {
            month1 = new BigDecimal(record.getMonth1());
        }
        BigDecimal month2 = null;
        if (StringUtil.isNotNull(record.getMonth2())) {
            month2 = new BigDecimal(record.getMonth2());
        }
        BigDecimal month3 = null;
        if (StringUtil.isNotNull(record.getMonth3())) {
            month3 = new BigDecimal(record.getMonth3());
        }

        //0水量模型
        Readabnormal readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.LSLMX.getTypeCode()).eq(Readabnormal::getYsxzBm, ysxz)
                .eq(Readabnormal::getSbkjBm, sbkj));
        if (StringUtil.isNotNull(readabnormal)) {
            String describe = readabnormal.getDescribe();
            Integer count = readabnormal.getCount();
            if (zeroCount > count) {
                //修改抄表类型原因
                Long typeId = readabnormal.getType();
                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                        .set(Readmeterhis::getAbnomalId, typeId)
                        .set(Readmeterhis::getShbz, "0")
                        .set(Readmeterhis::getAuditReason, describe + "，现有：" + zeroCount + "次0水量抄表"));
                return describe + "，现有：" + zeroCount + "次0水量抄表";
            }
        }
        //水量上升
        readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.SLLXSSMX.getTypeCode()));
        if (StringUtil.isNotNull(readabnormal)) {
            String describe = readabnormal.getDescribe();
            Integer count = readabnormal.getCount();
            if (upCount >= count) {
                //修改抄表类型原因
                Long typeId = readabnormal.getType();
                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                        .set(Readmeterhis::getAbnomalId, typeId)
                        .set(Readmeterhis::getShbz, "0")
                        .set(Readmeterhis::getAuditReason, describe + "，现有：" + upCount + "次连续上升水量"));
                return describe + "，现有：" + upCount + "次连续上升水量";
            }
        }
        //水量下降
        readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.SLLXXJMX.getTypeCode()));
        if (StringUtil.isNotNull(readabnormal)) {
            String describe = readabnormal.getDescribe();
            Integer count = readabnormal.getCount();
            if (downCount >= count) {
                //修改抄表类型原因
                Long typeId = readabnormal.getType();
                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                        .set(Readmeterhis::getAbnomalId, typeId)
                        .set(Readmeterhis::getShbz, "0")
                        .set(Readmeterhis::getAuditReason, describe + "，现有：" + downCount + "次连续下降水量"));
                return describe + "，现有：" + downCount + "次连续下降水量";
            }
        }
        //水量相同，水量相同排除0水量情况
        if (!bczl.equals(0L)) {
            readabnormal = readabnormalService.getOne(Wrappers.<Readabnormal>lambdaQuery().isNotNull(Readabnormal::getCount)
                    .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj)
                    .eq(Readabnormal::getTypeCode, AbnormalEnum.LXSLXTMX.getTypeCode()));
            if (StringUtil.isNotNull(readabnormal)) {
                String describe = readabnormal.getDescribe();
                Integer count = readabnormal.getCount();
                if (equalCount >= count) {
                    //修改抄表类型原因
                    Long typeId = readabnormal.getType();
                    readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                            .set(Readmeterhis::getAbnomalId, typeId)
                            .set(Readmeterhis::getShbz, "0")
                            .set(Readmeterhis::getAuditReason, describe + "，现有：" + equalCount + "次水量相同"));
                    return describe + "，现有：" + equalCount + "次水量相同";
                }
            }
        }
        BigDecimal bigBcsl = new BigDecimal(bczl);
        List<Readabnormal> readabnormalList = new ArrayList<>();
        //水量突降模型
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .and(v -> v.eq(Readabnormal::getTypeCode, AbnormalEnum.SLTJMX.getTypeCode())
                        .or().eq(Readabnormal::getTypeCode, AbnormalEnum.SLTSMX.getTypeCode()))
                .isNotNull(Readabnormal::getMinAverageValue).isNotNull(Readabnormal::getRatio)
                .eq(Readabnormal::getYsxzBm, ysxz)
                .eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            for (Readabnormal readab : readabnormalList) {
                String describe = readab.getDescribe();
                BigDecimal ratio = new BigDecimal(readab.getRatio());
                BigDecimal minAverageValue = new BigDecimal(readab.getMinAverageValue());
                String typeCode = readab.getTypeCode();
                BigDecimal average = null;
                //前三次平均水量
                if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2) && StringUtil.isNotNull(month3)) {
                    average = month1.add(month2).add(month3).divide(ReadData.CALCULATE_THREE.getYield(), 2, BigDecimal.ROUND_UP);
                } else if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2)) {
                    average = month1.add(month2).divide(ReadData.CALCULATE_TWO.getYield(), 2, BigDecimal.ROUND_UP);
                } else if (StringUtil.isNotNull(month1)) {
                    average = month1;
                }
                if (StringUtil.isNotNull(average)) {
                    //前三次平均水量是否大于基准值 如果是则进入筛选，如果本次水量小于等于突降值则异常，
                    // 这里定义的突降值居然是本次水量小于突降值就异常，我觉得正常的理解应该是和上次水量的比较只差，这个差值突降的比较
                    if (average.compareTo(minAverageValue) != -1) {
                        if (AbnormalEnum.SLTJMX.getTypeCode().equals(typeCode)) {
                            BigDecimal tjDiff = month1.subtract(bigBcsl).divide(month1, 3, BigDecimal.ROUND_UP)
                                    .multiply(ReadData.CALCULATE_HUNDRED.getYield());
                            //百分比
                            if (ratio.compareTo(tjDiff) == -1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                        .set(Readmeterhis::getAbnomalId, typeId)
                                        .set(Readmeterhis::getShbz, "0")
                                        .set(Readmeterhis::getAuditReason, describe + "，本次突降比例为：" + tjDiff + "%"));
                                return describe + "，本次突降比例为：" + tjDiff + "%";
                            }
                        }
                        if (AbnormalEnum.SLTSMX.getTypeCode().equals(typeCode)) {
                            BigDecimal tsDiff = bigBcsl.subtract(month1).divide(month1, 3, BigDecimal.ROUND_UP)
                                    .multiply(ReadData.CALCULATE_HUNDRED.getYield());
                            //百分比
                            if (ratio.compareTo(tsDiff) == -1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                        .set(Readmeterhis::getAbnomalId, typeId)
                                        .set(Readmeterhis::getShbz, "0")
                                        .set(Readmeterhis::getAuditReason, describe + "，本次突升比例为：" + tsDiff + "%"));
                                return describe + "，本次突升比例为：" + tsDiff + "%";
                            }
                        }
                    }
                }
            }
        }
        //环比升 、环比降
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .and(v -> v.eq(Readabnormal::getTypeCode, AbnormalEnum.HBSMX.getTypeCode())
                        .or().eq(Readabnormal::getTypeCode, AbnormalEnum.HBJMX.getTypeCode()))
                .isNotNull(Readabnormal::getRatio).isNotNull(Readabnormal::getMinAverageValue)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            //只要其中有一个为null，那么就不满足算法条件
            if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2) && StringUtil.isNotNull(month3)) {
                //前三次水量平均值
                BigDecimal average = getAverage(month1, month2, month3);
                for (Readabnormal readab : readabnormalList) {
                    String describe = readab.getDescribe();
                    String typeCode = readab.getTypeCode();
                    BigDecimal ratio = new BigDecimal(readab.getRatio());
                    BigDecimal minAverageValue = new BigDecimal(readab.getMinAverageValue());
                    if (AbnormalEnum.HBSMX.getTypeCode().equals(typeCode)) {
                        //水量平均值必须大于等于最小基准值 才进入算法筛选
                        if (average.compareTo(minAverageValue) != -1) {
                            //升百分比
                            BigDecimal upRatio = getUpRatio(average, bigBcsl);
                            if (upRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                        .set(Readmeterhis::getAbnomalId, typeId)
                                        .set(Readmeterhis::getShbz, "0")
                                        .set(Readmeterhis::getAuditReason, describe + "，本次环比升比例为：" + upRatio + "%"));
                                return describe + "，本次环比升比例为：" + upRatio + "%";
                            }
                        }
                    } else if (AbnormalEnum.HBJMX.getTypeCode().equals(typeCode)) {
                        if (average.compareTo(minAverageValue) != -1) {
                            //降百分比
                            BigDecimal downRatio = getDownRatio(average, bigBcsl);
                            if (downRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                        .set(Readmeterhis::getAbnomalId, typeId)
                                        .set(Readmeterhis::getShbz, "0")
                                        .set(Readmeterhis::getAuditReason, describe + "，本次环比降比例为：" + downRatio + "%"));
                                return describe + "，本次环比降比例为：" + downRatio + "%";
                            }
                        }
                    }
                }
            }
        }
        //同比升 、同比降
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .and(v -> v.eq(Readabnormal::getTypeCode, AbnormalEnum.TBSMX.getTypeCode())
                        .or().eq(Readabnormal::getTypeCode, AbnormalEnum.TBJMX.getTypeCode()))
                .isNotNull(Readabnormal::getRatio).isNotNull(Readabnormal::getMinAverageValue)
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            //只要其中有一个为null，那么就不满足算法条件
            if (StringUtil.isNotNull(yearonyear1) && StringUtil.isNotNull(yearonyear2) && StringUtil.isNotNull(yearonyear3)) {
                BigDecimal yearSl1 = new BigDecimal(yearonyear1);
                BigDecimal yearSl2 = new BigDecimal(yearonyear2);
                BigDecimal yearSl3 = new BigDecimal(yearonyear3);
                //前三年同月水量平均值
                BigDecimal average = getAverage(yearSl1, yearSl2, yearSl3);
                for (Readabnormal readab : readabnormalList) {
                    String describe = readab.getDescribe();
                    String typeCode = readab.getTypeCode();
                    BigDecimal ratio = new BigDecimal(readab.getRatio());
                    BigDecimal minAverageValue = new BigDecimal(readab.getMinAverageValue());
//                    Integer minAverageValue = readab.getMinAverageValue();
//                    Float ratio = readab.getRatio();
                    if (AbnormalEnum.TBSMX.getTypeCode().equals(typeCode)) {
                        //水量平均值必须大于等于最小基准值 才进入算法筛选
                        if (average.compareTo(minAverageValue) != -1) {
                            //升比例
                            BigDecimal upRatio = getUpRatio(average, bigBcsl);
                            if (upRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                        .set(Readmeterhis::getAbnomalId, typeId)
                                        .set(Readmeterhis::getShbz, "0")
                                        .set(Readmeterhis::getAuditReason, describe + "，本次同比升比例为：" + upRatio + "%"));
                                return describe + "，本次同比升比例为：" + upRatio + "%";
                            }
                        }
                    } else if (AbnormalEnum.TBJMX.getTypeCode().equals(typeCode)) {
                        if (average.compareTo(minAverageValue) != -1) {
                            //降比例
                            BigDecimal downRatio = getDownRatio(average, bigBcsl);
                            if (downRatio.compareTo(ratio) == 1) {
                                //修改抄表类型原因
                                Long typeId = readab.getType();
                                readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                        .set(Readmeterhis::getAbnomalId, typeId)
                                        .set(Readmeterhis::getShbz, "0")
                                        .set(Readmeterhis::getAuditReason, describe + "，本次同比降比例为：" + downRatio + "%"));
                                return describe + "，本次同比降比例为：" + downRatio + "%";
                            }
                        }
                    }
                }
            }
        }
        //水量微幅波动
        readabnormalList = readabnormalService.list(Wrappers.<Readabnormal>lambdaQuery()
                .isNotNull(Readabnormal::getRatio).isNotNull(Readabnormal::getFiducialValue)
                .eq(Readabnormal::getTypeCode, AbnormalEnum.SLWFBDMX.getTypeCode())
                .eq(Readabnormal::getYsxzBm, ysxz).eq(Readabnormal::getSbkjBm, sbkj));
        if (readabnormalList.size() > 0) {
            for (Readabnormal readab : readabnormalList) {
                String describe = readab.getDescribe();
                BigDecimal ratio = new BigDecimal(readab.getRatio());
                //同比环比
                String isYearorchain = readab.getIsYearorchain();
                //升降比例
                String isUpordown = readab.getIsUpordown();
                //基准值
                BigDecimal fiducialValue = new BigDecimal(readab.getFiducialValue());
                //当月水量大于基准值纳入筛选
                if (bigBcsl.compareTo(fiducialValue) == 1) {
                    //同比
                    if ("0".equals(isYearorchain)) {
                        //只要其中有一个为null，那么就不满足算法条件
                        if (StringUtil.isNotNull(yearonyear1) && StringUtil.isNotNull(yearonyear2) && StringUtil.isNotNull(yearonyear3)) {
                            BigDecimal yearSl1 = new BigDecimal(yearonyear1);
                            BigDecimal yearSl2 = new BigDecimal(yearonyear2);
                            BigDecimal yearSl3 = new BigDecimal(yearonyear3);
                            //前三年同月水量平均值
                            BigDecimal average = getAverage(yearSl1, yearSl2, yearSl3);
                            //升
                            if ("0".equals(isUpordown)) {
                                BigDecimal upRatio = getUpRatio(average, bigBcsl);
                                if (upRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                            .set(Readmeterhis::getAbnomalId, typeId)
                                            .set(Readmeterhis::getShbz, "0")
                                            .set(Readmeterhis::getAuditReason, describe + "，本次同比升比例为：" + upRatio + "%"));
                                    return describe + "，本次同比升比例为：" + upRatio + "%";
                                }
                            }
                            //降
                            else if ("1".equals(isUpordown)) {
                                BigDecimal downRatio = getDownRatio(average, bigBcsl);
                                if (downRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                            .set(Readmeterhis::getAbnomalId, typeId)
                                            .set(Readmeterhis::getShbz, "0")
                                            .set(Readmeterhis::getAuditReason, describe + "，本次同比降比例为：" + downRatio + "%"));
                                    return describe + "，本次同比降比例为：" + downRatio + "%";
                                }
                            }
                        }
                    }
                    //环比
                    else if ("1".equals(isYearorchain)) {
                        if (StringUtil.isNotNull(month1) && StringUtil.isNotNull(month2) && StringUtil.isNotNull(month3)) {
                            //前三次水量平均值
                            BigDecimal average = getAverage(month1, month2, month3);
                            //升
                            if ("0".equals(isUpordown)) {
                                BigDecimal upRatio = getUpRatio(average, bigBcsl);
                                if (upRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                            .set(Readmeterhis::getAbnomalId, typeId)
                                            .set(Readmeterhis::getShbz, "0")
                                            .set(Readmeterhis::getAuditReason, describe + "，本次环比升比例为：" + upRatio + "%"));
                                    return describe + "，本次环比升比例为：" + upRatio + "%";
                                }
                            }
                            //降
                            else if ("1".equals(isUpordown)) {
                                BigDecimal downRatio = getDownRatio(average, bigBcsl);
                                if (downRatio.compareTo(ratio) != 1) {
                                    //修改抄表类型原因
                                    Long typeId = readab.getType();
                                    readmeterhisService.update(Wrappers.<Readmeterhis>lambdaUpdate().eq(StringUtil.isNotEmpty(soleSign), Readmeterhis::getSoleSign, soleSign)
                                            .set(Readmeterhis::getAbnomalId, typeId)
                                            .set(Readmeterhis::getShbz, "0")
                                            .set(Readmeterhis::getAuditReason, describe + "，本次环比降比例为：" + downRatio + "%"));
                                    return describe + "，本次环比降比例为：" + downRatio + "%";
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 计算平均值
     *
     * @param sl1 水量1
     * @param sl2 水量2
     * @param sl3 水量3
     * @return average 平均值
     */
    private BigDecimal getAverage(BigDecimal sl1, BigDecimal sl2, BigDecimal sl3) {
        //三次水量数据之和
        BigDecimal sum = sl1.add(sl2).add(sl3);
        //除以 3 求平均值用的
        BigDecimal three = ReadData.CALCULATE_THREE.getYield();
        //平均值
        BigDecimal average = sum.divide(three, 2, BigDecimal.ROUND_HALF_UP);
        return average;
    }

    /**
     * 获取升比例
     *
     * @param average 平均值
     * @param bcsl    本次水量
     * @return 升比例
     */
    private BigDecimal getUpRatio(BigDecimal average, BigDecimal bcsl) {
        BigDecimal zero = ReadData.CALCULATE_ZERO.getYield();
        //本次水量与平均值的差 可以得到升值
        BigDecimal diff = bcsl.subtract(average);
        if (diff.compareTo(zero) == 0) {
            return zero;
        }
        //百分比
        BigDecimal percent = diff.divide(average, 2, BigDecimal.ROUND_HALF_UP);
        return percent;
    }

    /**
     * 获取降比例
     *
     * @param average 平均值
     * @param bcsl    本次水量
     * @return 降比例
     */
    private BigDecimal getDownRatio(BigDecimal average, BigDecimal bcsl) {
        BigDecimal zero = ReadData.CALCULATE_ZERO.getYield();
        //平均值与本次水量的差 可以得到降值
        BigDecimal diff = average.subtract(bcsl);
        if (diff.compareTo(zero) == 0) {
            return zero;
        }
        //百分比
        BigDecimal percent = diff.divide(average, 2, BigDecimal.ROUND_HALF_UP);
        return percent;
    }


    /**
     * 通过客户编号获取用户名与上次抄表水量
     */
    @Override
    public List<Map<String, String>> queryInfoByCode() {
        return qfkhjbxxMapper.getCodeAndWater();
    }

    /**
     * 根据区域统计水量审核信息
     *
     * @return list
     */
    @Override
    public List<Map> waterAuditCountByZone() {
        Map<String,Object> param = new HashMap<>();
        List<Map> result = new ArrayList<>();
        param.put("readBookCodes",null);
        param.put("type",2);
        param.put("userId",null);
        Map apiResult = callAPIService.getApiResult(param, "/api/v1/koi/read/audit/find/count");
        if (CollectionUtil.isNotEmpty(apiResult) && ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(apiResult.get("statusCode")))) {
            List<Map> data = JSONObject.parseArray(JSONObject.toJSONString(apiResult.get("data")), Map.class);
            if (CollectionUtils.isNotEmpty(data)){
                String userName = SecurityUtils.getUser().getRealName();
                result = data.stream().filter(map -> map.get("name").equals(userName)).collect(Collectors.toList());
            }
        }
        return result;
    }

    /**
     * 统计各个状态审核信息
     *
     * @param readBookCode readBookCode
     * @return list
     */
    @Override
    public Map waterAuditStatusCount(String readBookCode) {
        Map<String,Object> param = new HashMap<>();
        param.put("hasException",0);
        param.put("readBookCode",readBookCode);
        Map apiResult = callAPIService.getApiResult(param, "/api/v1/koi/read/audit/status/count");
        if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(apiResult.get("statusCode")))) {
            return JSONObject.parseObject(JSONObject.toJSONString(apiResult.get("data")), Map.class);
        }else {
            return new HashMap<>();
        }
    }

    /**
     * 获取水量审核信息
     *
     * @param hasException 是否异常 0 正常 1 异常 2 复核 6 已停水
     * @param readBookCode 抄表册
     * @return list
     */
    @Override
    public List<Map> waterAuditInfo(Integer hasException, String readBookCode) {
        Map<String, Object> param = new HashMap<>(2);
        List<Map> result = new ArrayList<>();
        param.put("hasException",hasException);
        param.put("readBookCode",readBookCode);
        Map apiResult = callAPIService.getApiResult(param, "/api/v1/koi/read/audit/find/page");
        if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(apiResult.get("statusCode")))) {
            result = JSONObject.parseArray(JSONObject.toJSONString(apiResult.get("data")), Map.class);
        }
        return result;
    }

    /**
     * 获取水量审核人员
     *
     * @return list
     */
    @Override
    public List<Map> waterAuditUser() {
        Map<String,Object> params = new HashMap<>(1);
        params.put("jobCode", "010001");
        List<Map> result = new ArrayList<>();
        Map apiResult = callAPIService.getApiResult(params, "/api/v1/rabbit/system/member/dept/job/tree/find");
        if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(apiResult.get("statusCode")))) {
            result = JSONObject.parseArray(JSONObject.toJSONString(apiResult.get("data")), Map.class);
        }
        return result;
    }

    /**
     * 水量审核
     *
     * @return boolean
     */
    @Override
    public boolean waterAudit(WaterAuditDto dto) {
        Map apiResult = callAPIService.getApiResult(dto, "/api/v1/koi/read/audit/reserve/batch");
        if (ApiCallEnum.STATUS_CODE_OK.getCode().equals(String.valueOf(apiResult.get("statusCode")))){
            return true;
        }else {
            throw new ToflyDeniedException(String.valueOf(apiResult.get("statusCode")));
        }
    }


}
