package com.tofly.feesapi.sfgl.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ibm.icu.impl.data.ResourceReader;
import com.sun.istack.NotNull;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.core.util.StringUtil;
import com.tofly.feesapi.bjgl.entity.YhCbkxx;
import com.tofly.feesapi.bjgl.service.YhCbkxxService;
import com.tofly.feesapi.bmgl.entity.BmCbb;
import com.tofly.feesapi.bmgl.entity.BmFffs;
import com.tofly.feesapi.bmgl.entity.BmGs;
import com.tofly.feesapi.bmgl.entity.BmSj;
import com.tofly.feesapi.bmgl.service.*;
import com.tofly.feesapi.cbgl.entity.ZnbZlLog;
import com.tofly.feesapi.cbgl.service.IZnbZlLogService;
import com.tofly.feesapi.common.NumberHelper;
import com.tofly.feesapi.common.constant.PjztEnum;
import com.tofly.feesapi.common.constant.SflxEnum;
import com.tofly.feesapi.common.core.dto.Order;
import com.tofly.feesapi.common.core.dto.PageDto;
import com.tofly.feesapi.common.core.vo.PageResult;
import com.tofly.feesapi.common.dbhelper.DbHelper;
import com.tofly.feesapi.common.dzfp.InvoiceService;
import com.tofly.feesapi.common.enums.BcFylxEnum;
import com.tofly.feesapi.common.enums.ReportFylxEnum;
import com.tofly.feesapi.common.exception.FeesErrorCode;
import com.tofly.feesapi.common.exception.FeesException;
import com.tofly.feesapi.common.util.DateUtils;
import com.tofly.feesapi.common.util.GuidGenerator;
import com.tofly.feesapi.common.util.SysConstant;
import com.tofly.feesapi.common.util.ToolsUtils;
import com.tofly.feesapi.common.znj.ZnjCal;
import com.tofly.feesapi.dzfp.entity.EiFpkjRequest;
import com.tofly.feesapi.dzfp.entity.EiYkfpLog;
import com.tofly.feesapi.dzfp.service.EiFpkjRequestService;
import com.tofly.feesapi.dzfp.service.EiYkfpLogService;
import com.tofly.feesapi.mxcx.entity.dto.YsartjFilter;
import com.tofly.feesapi.mxcx.entity.vo.YffkjmxcxSelect;
import com.tofly.feesapi.mxcx.entity.vo.YffycmxcxSelect;
import com.tofly.feesapi.mxcx.entity.vo.YsartjSelect;
import com.tofly.feesapi.security.util.SecurityUtils;
import com.tofly.feesapi.sfgl.entity.Plsfkhxx;
import com.tofly.feesapi.sfgl.entity.YyQfmx;
import com.tofly.feesapi.sfgl.entity.YySspjxx;
import com.tofly.feesapi.sfgl.entity.dto.*;
import com.tofly.feesapi.sfgl.entity.vo.*;
import com.tofly.feesapi.sfgl.mapper.YySspjxxMapper;
import com.tofly.feesapi.sfgl.service.PlsfkhxxService;
import com.tofly.feesapi.sfgl.service.YyPjbhService;
import com.tofly.feesapi.sfgl.service.YyQfmxService;
import com.tofly.feesapi.sfgl.service.YySspjxxService;
import com.tofly.feesapi.udb.entity.User;
import com.tofly.feesapi.udb.service.IUserService;
import com.tofly.feesapi.xtgl.entity.Syscommlog;
import com.tofly.feesapi.xtgl.service.ISysGdcsbService;
import com.tofly.feesapi.xtgl.service.ISyscommlogService;
import com.tofly.feesapi.yhgl.entity.YhGroup;
import com.tofly.feesapi.yhgl.entity.YhGroupAccounts;
import com.tofly.feesapi.yhgl.entity.YhKhjbxx;
import com.tofly.feesapi.yhgl.entity.YyZjzh;
import com.tofly.feesapi.yhgl.entity.dto.YyZjzhUpdate;
import com.tofly.feesapi.yhgl.entity.vo.YhkhjbxxSelect2;
import com.tofly.feesapi.yhgl.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.TransactionTemplate;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.hutool.core.date.DateUtil.beginOfMonth;
import static com.tofly.feesapi.common.constant.SflxEnum.*;
import static com.tofly.feesapi.common.exception.FeesErrorCode.*;

/**
 * 收费明细
 */
@Slf4j
@Service("yySspjxxService")
public class YySspjxxServiceImpl extends ServiceImpl<YySspjxxMapper, YySspjxx> implements YySspjxxService {

    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private BmSjService sjService;
    @Autowired
    private IBmFffsService bmFffsService;
    @Autowired
    private YyQfmxService qfmxService;
    @Autowired
    private IYyZjzhService zjzhService;
    @Autowired
    private ISysGdcsbService gdcsbService;
    @Autowired
    private YhKhjbxxService khjbxxService;
    @Autowired
    private YhCbkxxService yhCbkxxService;
    @Autowired
    private IZnbZlLogService iZnbZlLogService;
    @Autowired
    private IUserService userService;
    @Autowired
    private InvoiceService invoiceService;
    @Autowired
    private YhGroupService yhGroupService;
    @Autowired
    private YhGroupAccountsService yhGroupAccountsService;
    @Autowired
    private YyPjbhService yyPjbhService;
    @Autowired
    private EiFpkjRequestService eiFpkjRequestService;
    @Autowired
    private ISyscommlogService syscommlogService;
    @Autowired
    private EiYkfpLogService eiYkfpLogService;
    @Autowired
    private ZnjCal znjCal;
    @Autowired
    private IBmGsService bmGsService;
    @Autowired
    private BmCbbService bmCbbService;
    @Autowired
    private PlsfkhxxService plsfkhxxService;

    @Autowired
    private YhsjqxService yhsjqxService;

    @Autowired
    private BmYmjzConfigService bmYmjzConfigService;

    public List<RyYySspjxxSelect> getRymxReport(YySspjxxDailyStatFilter filter) {

        List<RySlSelect> ryLst = baseMapper.getRyMxReport(filter);
        List<RySlSelect> ryChLst = baseMapper.getRyMxChReport(filter);
        List<RySlSelect> ryTfLst = baseMapper.getRyMxTfReport(filter);

        List<BmFffs> fffs = bmFffsService.list(new QueryWrapper<BmFffs>().eq("isdisabled", "1"));
        List<User> lstUser = userService.getAllUser();

        List<RyYySspjxxSelect> lst = new ArrayList<>();
        List<RyYySspjxxSelect> newLst = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(ryLst)) {
            ryLst.forEach(e -> {
                RyYySspjxxSelect ryselect = getRyselect(e, fffs, lstUser, ReportFylxEnum.收费);
                lst.add(ryselect);
            });
        }

        if (CollectionUtil.isNotEmpty(ryChLst)) {
            ryChLst.forEach(e -> {
                lst.add(getRyselect(e, fffs, lstUser, ReportFylxEnum.冲红));
            });
        }

        if (CollectionUtil.isNotEmpty(ryTfLst)) {
            ryTfLst.forEach(e -> {
                lst.add(getRyselect(e, fffs, lstUser, ReportFylxEnum.退费));
            });
        }

        if (CollectionUtil.isNotEmpty(lst)) {
            Map<Long, List<RyYySspjxxSelect>> userMap = lst.stream()
                    .filter(l -> !StringUtil.isEmpty(String.valueOf(l.getRybm())))
                    .collect(Collectors.groupingBy(RyYySspjxxSelect::getRybm))
                    .entrySet()
                    .stream().collect(Collectors.toMap(o -> o.getKey(), o -> {

                        List<RyYySspjxxSelect> model = o.getValue().stream().collect(Collectors.toMap(RyYySspjxxSelect::getFffs, a -> a, (o1, o2) -> {
                            o1.setSfje(o1.getSfje().add(o2.getSfje()));
                            o1.setSfbs(o1.getSfbs().add(o2.getSfbs()));
                            o1.setChje(o1.getChje().add(o2.getChje()));
                            o1.setChbs(o1.getChbs().add(o2.getChbs()));
                            o1.setTfje(o1.getTfje().add(o2.getTfje()));
                            o1.setTfbs(o1.getTfbs().add(o2.getTfbs()));
                            o1.setHjje(o1.getHjje().add(o2.getHjje()));
                            return o1;
                        })).values().stream().collect(Collectors.toList());

                        return model;
                    }));

            lst.clear();
            userMap.forEach((k, v) -> {
                v.forEach(m -> {
                    lst.add(m);
                });
            });
        }


        Map<Long, RyYySspjxxSelect> ryMap = lst.stream()
                .filter(l -> !StringUtil.isEmpty(String.valueOf(l.getRybm())))
                .collect(Collectors.groupingBy(RyYySspjxxSelect::getRybm)).entrySet()
                .stream().collect(Collectors.toMap(o -> o.getKey(), o -> {
                    List<RyYySspjxxSelect> l = o.getValue();
                    BigDecimal totalSfje = l.stream()
                            .map(RyYySspjxxSelect::getSfje)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);

                    BigDecimal totalChje = l.stream()
                            .map(RyYySspjxxSelect::getChje)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);

                    BigDecimal totalTfje = l.stream()
                            .map(RyYySspjxxSelect::getTfje)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);

                    BigDecimal totalSfbs = l.stream()
                            .map(RyYySspjxxSelect::getSfbs)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);
                    BigDecimal totalHjje = l.stream()
                            .map(RyYySspjxxSelect::getHjje)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);
                    BigDecimal totalChbs = l.stream()
                            .map(RyYySspjxxSelect::getChbs)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);
                    BigDecimal totalTfbs = l.stream()
                            .map(RyYySspjxxSelect::getTfbs)
                            .reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_UP);
                    RyYySspjxxSelect newRyYySspjxxSelect = new RyYySspjxxSelect();
                    newRyYySspjxxSelect.setRybm(o.getKey());
                    newRyYySspjxxSelect.setMc("小计");
                    newRyYySspjxxSelect.setLx("小计");
                    newRyYySspjxxSelect.setSfje(totalSfje);
                    newRyYySspjxxSelect.setSfbs(totalSfbs);
                    newRyYySspjxxSelect.setTfje(totalTfje);
                    newRyYySspjxxSelect.setTfbs(totalTfbs);

                    newRyYySspjxxSelect.setChje(totalChje);
                    newRyYySspjxxSelect.setChbs(totalChbs);
                    newRyYySspjxxSelect.setHjje(totalHjje);
                    return newRyYySspjxxSelect;
                }));

        Iterator<Long> keyIterator = ryMap.keySet().iterator();
        while (keyIterator.hasNext()) {
            Long key = keyIterator.next();
            lst.add(ryMap.get(key));
        }
        if (!lst.isEmpty()) {
            RyYySspjxxSelect total = new RyYySspjxxSelect();
            total.setRybm(999999L);
            total.setLx("合计");
            total.setMc("合计");
            total.setSfje(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getSfje).reduce(BigDecimal.ZERO, BigDecimal::add));
            total.setSfbs(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getSfbs).reduce(BigDecimal.ZERO, BigDecimal::add));
            total.setTfje(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getTfje).reduce(BigDecimal.ZERO, BigDecimal::add));
            total.setTfbs(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getTfbs).reduce(BigDecimal.ZERO, BigDecimal::add));
            total.setChje(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getChje).reduce(BigDecimal.ZERO, BigDecimal::add));
            total.setChbs(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getChbs).reduce(BigDecimal.ZERO, BigDecimal::add));
            total.setHjje(lst.stream().filter(e -> e.getLx().equals("小计")).map(RyYySspjxxSelect::getHjje).reduce(BigDecimal.ZERO, BigDecimal::add));
            lst.add(total);
        }
        return lst;
    }

    private RyYySspjxxSelect getRyselect(RySlSelect ry, List<BmFffs> fffs, List<User> lstUser, ReportFylxEnum reportFylxEnum) {

        String userName = "";
        Long userId = Long.valueOf("0");
        String sfrybm = ry.getSfrybm();
        if (StringUtil.isNotEmpty(sfrybm)) {
            Optional<User> user = lstUser.stream().filter(m -> m.getId().equals(Long.valueOf(sfrybm))).
                    findFirst();
            if (user.isPresent()) {
                userName = user.get().getRealName();
                userId = user.get().getId();
            }
        }

        BmFffs bmFffs = fffs.stream().filter(m -> m.getCode().equals(ry.getFffs())).findFirst().get();
        RyYySspjxxSelect rySelect = new RyYySspjxxSelect();
        rySelect.setLx("明细");
        rySelect.setMc(userName);
        rySelect.setRybm(userId);
        rySelect.setFffs(bmFffs.getName());
        rySelect.setChje(BigDecimal.valueOf(0.00));
        rySelect.setChbs(BigDecimal.valueOf(0.00));
        rySelect.setTfje(BigDecimal.valueOf(0.00));
        rySelect.setTfbs(BigDecimal.valueOf(0.00));
        rySelect.setSfje(BigDecimal.valueOf(0.00));
        rySelect.setSfbs(BigDecimal.valueOf(0.00));
        if (ReportFylxEnum.冲红 == reportFylxEnum) {
            rySelect.setChje(ry.getJe());
            rySelect.setChbs(ry.getCnt());
        }
        if (ReportFylxEnum.退费 == reportFylxEnum) {
            rySelect.setTfje(ry.getJe());
            rySelect.setTfbs(ry.getCnt());
        }
        if (ReportFylxEnum.收费 == reportFylxEnum) {
            rySelect.setSfje(ry.getJe());
            rySelect.setSfbs(ry.getCnt());
        }
        rySelect.setHjje(add(add(rySelect.getSfje(), rySelect.getChje()), rySelect.getTfje()));
        return rySelect;
    }

    private RyYySspjxxSelect getTfRyselect(RySlSelect ry, List<BmFffs> fffs, List<User> lstUser) {
        User user = lstUser.stream().filter(m -> m.getId().equals(Long.valueOf(ry.getSfrybm()))).findFirst().get();
        BmFffs bmFffs = fffs.stream().filter(m -> m.getCode().equals(ry.getFffs())).findFirst().get();
        RyYySspjxxSelect rySelect = new RyYySspjxxSelect();
        rySelect.setLx("明细");
        rySelect.setMc(user.getRealName());
        rySelect.setRybm(user.getId());
        rySelect.setFffs(bmFffs.getName());
        rySelect.setTfje(ry.getJe());
        rySelect.setTfbs(ry.getCnt());
        rySelect.setChje(BigDecimal.valueOf(0.00));
        rySelect.setChbs(BigDecimal.valueOf(0.00));
        rySelect.setSfje(BigDecimal.valueOf(0.00));
        rySelect.setSfbs(BigDecimal.valueOf(0.00));
        return rySelect;
    }

    @Override
    public YySspjxxDailyStat dailyStat(YySspjxxDailyStatFilter filter) {
        Map<String, String> fffsMap = getFffsMapByDailyStat();
        if (!CollectionUtil.isEmpty(fffsMap)) {
            fffsMap.put("9", "其他");
        }


        List<YySspjxxDailyStat.SrxmStat> jbsf = getSfsr(filter, fffsMap);
        List<YySspjxxDailyStat.SrxmStat> qtfjf = getFjjdsf(filter, fffsMap);

        // 总计
        List<YySspjxxDailyStat.SrxmStat> xjStats = new ArrayList<>();
        int sfsfSize = jbsf.size();
        int fjjdsfSize = qtfjf.size();

        if (sfsfSize > 0) {
            xjStats.add(jbsf.get(sfsfSize - 1));
        }

        if (fjjdsfSize > 0) {
            xjStats.add(qtfjf.get(fjjdsfSize - 1));
        }

        YySspjxxDailyStat.SrxmStat zj = getZj(fffsMap, xjStats);

        return new YySspjxxDailyStat(jbsf, qtfjf, zj);
    }

    private void yjcyjzj(YySspjxxDailyStat.SrxmStat zj, List<YySspjxxDailyStat.SrxmStat> yjcyjmx) {
        List<YySspjxxDailyStat.FffsStat> sffjfzjlist = zj.getFffsStats();
        if (CollectionUtil.isEmpty(yjcyjmx)) {
            return;
        }

        List<YySspjxxDailyStat.FffsStat> yjcyjStats = new ArrayList<>();
        yjcyjmx.forEach(o -> yjcyjStats.addAll(o.getFffsStats()));
        Map<String, List<YySspjxxDailyStat.FffsStat>> fffsYjCyjMap = yjcyjStats.stream()
                .collect(Collectors.groupingBy(YySspjxxDailyStat.FffsStat::getFffsmc));

        for (YySspjxxDailyStat.FffsStat fffsStat : sffjfzjlist) {
            String fffsmc = fffsStat.getFffsmc();
            List<YySspjxxDailyStat.FffsStat> yjcyjstats = fffsYjCyjMap.get(fffsmc);

            if (CollectionUtil.isEmpty(yjcyjstats)) {
                continue;
            }

            BigDecimal yjcyjje = yjcyjstats.stream().filter(o -> ObjUtil.isNotNull(o.getJe())).map(YySspjxxDailyStat.FffsStat::getJe)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal je = fffsStat.getJe();
            BigDecimal totalJe = je.add(yjcyjje);
            fffsStat.setJe(totalJe);
        }
    }

    @Override
    public PageResult<YySspjxxSelect> getPage(PageDto pageDto, YySspjxxFilter filter, String sffl, String chbz) {
        List<Order> orders = pageDto.getOrders();
        if (orders.isEmpty()) {
            orders.add(new Order("sfrq", false));
        }


        String khbm = filter.getKhbm();
        if (StrUtil.isNotEmpty(khbm) && khbm.length() > 7) {
            khbm = khbm.substring(0, 7);
        }
        PageDto<YySspjxxSelect> page = baseMapper.getPageList(pageDto, filter, sffl, chbz);

        List<YySspjxxSelect> records = page.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return new PageResult(0, new ArrayList());
        }

        Map<String, String> sjMap = getSjMap();
        records.forEach(e -> {
            setYslx(e, sjMap);
            e.setYsecjyf(checkNumber(e.getYsecjyf()));
            e.setYsfjf(checkNumber(e.getYsfjf()));
            e.setYsqt(checkNumber(e.getYsqt()));
            if (!"1".equals(e.getFylx()) && !"2".equals(e.getFylx())) {
                e.setYssl(BigDecimal.ZERO);
            }
        });

        return page.toVo();
    }

    public Map getZhcxPage(PageDto pageDto, YySspjxxFilter filter, String sffl, String chbz) {
        List<Order> orders = pageDto.getOrders();
        if (orders.isEmpty()) {
            orders.add(new Order("sfrq", false));
        }
        PageDto<YySspjxxSelect> page = this.baseMapper.getPageList(pageDto, filter, sffl, chbz);
        Map<String, String> sjMap = getSjMap();
        page.getRecords().forEach(e -> {
            setYslx(e, sjMap);
            if (!"1".equals(e.getFylx()) && !"2".equals(e.getFylx())) {
                e.setYssl(BigDecimal.ZERO);
            }
        });
        Map map = new HashMap();
        map.put("page", page.toVo());
        List<Map> mapList = Collections.singletonList(page.toVo().getRecords().stream()
                .collect(Collectors.groupingBy(e -> e.getSflsbh(), Collectors.counting())));
        map.put("list", mapList);
        return map;
    }

    /**
     * 先存后扣
     */
    @SneakyThrows
    @Override
    @DSTransactional
    public Boolean wxgzhsf(@NotNull YySspjxxInsert insert) {
        String yhbh = insert.getYhbh();
        String fffs = insert.getFffs();

        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("付费方式为空", BUSINESS_ERROR);
        }

        if (StringUtil.isEmpty(yhbh)) {
            throw new FeesException("用户编号不能为空", BUSINESS_ERROR);
        }

        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
        if (StringUtil.isNull(yhKhjbxx)) {
            throw new FeesException("用户信息不存在", BUSINESS_ERROR);
        }

        if (this.sfsqzhgx(yhbh)) {
            throw new FeesException("用户存在群主户关系，请到营业厅缴费！", BUSINESS_ERROR);
        }

        String sflsbh = insert.getSflsbh();
        if (StringUtil.isEmpty(sflsbh)) {
            sflsbh = GuidGenerator.getSflsbh();
        }

        long count = this.count(Wrappers.<YySspjxx>lambdaQuery().eq(YySspjxx::getSflsbh, sflsbh));
        if (count > 0) {
            throw new FeesException("该流水号已存在", BUSINESS_ERROR);
        }

        Date now = new Date();
        Date dsfsfrq = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(insert.getSfrq());

        BigDecimal sszje = insert.getSszje();
        List<YyQfmx> yyQfmxList = qfmxService.lambdaQuery()
                .eq(YyQfmx::getYhbh, yhbh)
                .eq(YyQfmx::getSfbz, "0")
                .eq(YyQfmx::getChbz, "0")
                .list();

        YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
        zjzhUpdate.setYhbh(yhbh);
        zjzhUpdate.setJe(sszje);
        zjzhUpdate.setSfrq(now);

        if (CollectionUtil.isEmpty(yyQfmxList)) {
            if (!zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh)) {
                throw new FeesException("预存失败", BUSINESS_ERROR);
            }

            this.lambdaUpdate().set(YySspjxx::getSfrq, dsfsfrq)
                    .eq(YySspjxx::getSflsbh, sflsbh)
                    .update();
            return true;
        }

        //根据第三方的缴费日期计算违约金
        //znjCal.YyQfmxZnj(yhbh, yyQfmxList, insert.getSfrq());

        //重新查询违约金调整后的欠费明细
        yyQfmxList = qfmxService.lambdaQuery()
                .eq(YyQfmx::getYhbh, yhbh)
                .eq(YyQfmx::getSfbz, "0")
                .eq(YyQfmx::getChbz, "0")
                .list();

        yyQfmxList = yyQfmxList.stream()
                .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                .collect(Collectors.toList());

        BigDecimal yhye = BigDecimal.ZERO;

        // 用户资金账号
        YyZjzh zjzh = zjzhService.getById(insert.getYhbh());
        if (zjzh != null) {
            BigDecimal syje = zjzh.getSyje();
            yhye = syje == null ? BigDecimal.ZERO : syje;
        }

        YyQfmx firstQfmx = yyQfmxList.get(0);
        BigDecimal ysje = firstQfmx.getYsje();
        BigDecimal znj = firstQfmx.getZnj();

        ysje = ysje == null ? BigDecimal.ZERO : ysje;
        znj = znj == null ? BigDecimal.ZERO : znj;
        if (yhye.compareTo(ysje.add(znj)) > 0) {
            throw new FeesException("剩余预付费大于等于最早一笔欠费", BUSINESS_ERROR);
        }

        BigDecimal yszje = yyQfmxList.stream().map(e -> e.getYsje()).filter(e -> e != null)
                .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));

        BigDecimal yszwyj = yyQfmxList.stream().map(e -> e.getZnj()).filter(e -> e != null)
                .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));

        yszje = yszje.add(yszwyj).subtract(yhye);
        if (sszje.compareTo(yszje) < 0) {
            throw new FeesException("缴费金额不能低于欠费金额", BUSINESS_ERROR);
        }

        //判断余额是否足够后，添加预存
        zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);

        //重新获取预存金额
        zjzh = zjzhService.getById(insert.getYhbh());
        yhye = zjzh.getSyje();

        int sfxh = 2;


        for (YyQfmx qfmx : yyQfmxList) {
            //更新欠费明细
            qfmxService.lambdaUpdate()
                    .set(YyQfmx::getSfrq, dsfsfrq)
                    .set(YyQfmx::getSfbz, "1")
                    .set(YyQfmx::getSflsbh, sflsbh)
                    .eq(YyQfmx::getId, qfmx.getId())
                    .update();

            BigDecimal ysje1 = qfmx.getYsje();
            BigDecimal znj1 = qfmx.getZnj();
            BigDecimal sszje1 = ysje1.add(znj1);
            BigDecimal bckj1 = sszje1;
            BigDecimal bcjz1 = yhye.subtract(sszje1);
            BigDecimal scjz1 = yhye;
            YySspjxx sspjxx = new YySspjxx();
            BeanUtils.copyProperties(qfmx, sspjxx);
            sspjxx.setQfid(qfmx.getId());
            sspjxx.setSfxh(sfxh);//收费序号
            sspjxx.setBckj(bckj1);//本次扣减
            sspjxx.setBcye(bcjz1);//本次余额
            sspjxx.setScye(scjz1);//上次余额
            sspjxx.setSflx(预存抵扣);
            sspjxx.setSszje(BigDecimal.ZERO);
            sspjxx.setFffs(fffs);
            sspjxx.setSfrq(dsfsfrq);
            sspjxx.setSfsjrq(now);
            sspjxx.setSflsbh(sflsbh);
            sspjxx.setChbz(PjztEnum.正常.getValue());
            sspjxx.setSfbz("1");
            sspjxx.setSfyf(new SimpleDateFormat("yyyyMM").format(dsfsfrq));
            sspjxx.setSfrybm(insert.getSfrybm());
            sspjxx.setSfryxm(insert.getSfryxm());
            sspjxx.setFph2(yyPjbhService.getPjh(SecurityUtils.getUserId().toString()));

            this.save(sspjxx);
            //扣减资金帐户的金额
            zjzhService.lambdaUpdate()
                    .setSql(String.format("syje = syje-(%s)", bckj1))
                    .setSql(String.format("kjje = kjje+(%s)", bckj1))
                    .eq(YyZjzh::getYhbh, yhbh)
                    .update();
            //扣减当前收费金额
            yhye = yhye.subtract(sszje1);
            sfxh++;
        }

        List<YySspjxx> list = this.lambdaQuery()
                .eq(YySspjxx::getSflsbh, sflsbh)
                .orderByAsc(YySspjxx::getSfxh)
                .list();

        //-------------------------------------EI数电发票数据添加---------------------
        this.dzfpcl(list, yhKhjbxx, dsfsfrq, sflsbh, insert.getSfkp(), "0");
        return true;
    }

    /**
     * 先扣后存
     */
    @Override
    @DSTransactional
    @SneakyThrows
    public Boolean wxgzhsfxkhc(@NotNull YySspjxxInsert insert) {
        String yhbh = insert.getYhbh();
        String fffs = insert.getFffs();
        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("付费方式为空", BUSINESS_ERROR);
        }
        if (StringUtil.isEmpty(yhbh)) {
            throw new FeesException("用户编号不能为空", BUSINESS_ERROR);
        }
        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
        if (StringUtil.isNull(yhKhjbxx)) {
            throw new FeesException("用户信息不存在", BUSINESS_ERROR);
        }
        if (Integer.valueOf("1").equals(yhKhjbxx.getDxh())) {
            throw new FeesException("用户为大户用户，请到营业厅缴费！", BUSINESS_ERROR);
        }

        String sflsbh = insert.getSflsbh();
        long count = this.count(Wrappers.<YySspjxx>lambdaQuery().eq(YySspjxx::getSflsbh, sflsbh));
        if (count > 0) {
            throw new FeesException("该流水号已存在", BUSINESS_ERROR);
        }

        Date now = new Date();
        Date dsfsfrq = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(insert.getSfrq());

        List<YyQfmx> yyQfmxList = qfmxService.lambdaQuery()
                .eq(YyQfmx::getYhbh, yhbh)
                .eq(YyQfmx::getSfbz, "0")
                .eq(YyQfmx::getChbz, "0")
                .list();

        BigDecimal sszje = insert.getSszje();
        // 没有欠费直接预存金额
        if (CollectionUtil.isEmpty(yyQfmxList)) {
            YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
            zjzhUpdate.setYhbh(yhbh);
            zjzhUpdate.setJe(sszje);
            zjzhUpdate.setSfrq(dsfsfrq);
            return zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);
        }

        yyQfmxList = yyQfmxList.stream()
                .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                .collect(Collectors.toList());

        BigDecimal yhye = BigDecimal.ZERO;
        YyZjzh zjzh = zjzhService.getById(insert.getYhbh());
        if (zjzh != null) {
            BigDecimal syje = zjzh.getSyje();
            yhye = syje == null ? BigDecimal.ZERO : syje;
        }

        // 校验是否自动扣费
//        YyQfmx firstQfmx = yyQfmxes.get(0);
//        BigDecimal ysje = firstQfmx.getYsje();
//        BigDecimal znj = firstQfmx.getZnj();
//        ysje = ysje == null ? BigDecimal.ZERO : ysje;
//        znj = znj == null ? BigDecimal.ZERO : znj;
//        if (yhye.compareTo(ysje.add(znj)) > 0) {
//            throw new FeesException("剩余预付费大于等于最早一笔欠费", BUSINESS_ERROR);
//        }

        BigDecimal yszje = yyQfmxList.stream().map(e -> e.getYsje()).filter(e -> e != null)
                .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));

//        BigDecimal yszwyj = yyQfmxList.stream().map(e -> e.getZnj()).filter(e -> e != null)
//                .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
//        yszje = yszje.add(yszwyj).subtract(yhye);
        yszje = yszje.subtract(yhye);
        if (sszje.compareTo(yszje) < 0) {
            throw new FeesException("缴费金额不能低于欠费金额", BUSINESS_WXSF_ERROR);
        }

        if (StringUtil.isEmpty(sflsbh)) {
            sflsbh = GuidGenerator.getSflsbh();
        }

        BigDecimal bcyfje = sszje.subtract(yszje);

        List<YySspjxx> list = new ArrayList<>();
        int sfxh = 1;

        for (YyQfmx qfmx : yyQfmxList) {
            //更新欠费明细
            qfmxService.lambdaUpdate().set(YyQfmx::getSfrq, dsfsfrq).set(YyQfmx::getSfbz, "1")
                    .set(YyQfmx::getSflsbh, sflsbh).eq(YyQfmx::getId, qfmx.getId())
                    .update();

            BigDecimal bckj1 = BigDecimal.ZERO;
            BigDecimal ysje1 = qfmx.getYsje();
            BigDecimal znj1 = qfmx.getZnj();
            BigDecimal sszje1 = null;
            BigDecimal bcjz1 = BigDecimal.ZERO;

            if (sfxh == 1) {
                bckj1 = yhye;
                sszje1 = ysje1.add(znj1).subtract(yhye);
            } else {
                sszje1 = ysje1.add(znj1);
            }
            YySspjxx sspjxx = new YySspjxx();
            BeanUtils.copyProperties(qfmx, sspjxx);
            sspjxx.setQfid(qfmx.getId());
            sspjxx.setSfxh(sfxh);
            sspjxx.setBckj(bckj1);
            sspjxx.setBcye(bcjz1);
            sspjxx.setScye(bckj1);
            sspjxx.setSflx(欠费收取);
            sspjxx.setSszje(sszje1);
            sspjxx.setFffs(fffs);
            sspjxx.setSflsbh(sflsbh);
            sspjxx.setSfrq(dsfsfrq);
            sspjxx.setSfsjrq(now);
            sspjxx.setChbz(PjztEnum.正常.getValue());
            sspjxx.setSfbz("1");
            sspjxx.setSfrybm(insert.getSfrybm());
            sspjxx.setSfryxm(insert.getSfryxm());
            sspjxx.setFph2(yyPjbhService.getPjh(SecurityUtils.getUserId().toString()));
            this.save(sspjxx);
            list.add(sspjxx);
            // 1、第一笔交费，先扣除账户余额
            if (sfxh == 1) {
                if (bckj1.compareTo(BigDecimal.ZERO) != 0) {
                    zjzhService.lambdaUpdate()
                            .setSql(String.format("syje = syje-(%s)", bckj1))
                            .setSql(String.format("kjje = kjje+(%s)", bckj1))
                            .setSql(String.format("nbsyje = nbsyje-(%s)", bckj1))
                            .eq(YyZjzh::getYhbh, yhbh)
                            .update();
                }
            }
            // 2、如果交费多于当前欠费,存进账户里
            if (yyQfmxList.size() == sfxh) {
                if (bcyfje.compareTo(BigDecimal.ZERO) > 0) {
                    YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
                    zjzhUpdate.setYhbh(yhbh);
                    zjzhUpdate.setJe(bcyfje);
                    zjzhUpdate.setSfrq(dsfsfrq);
                    int ycxh = sfxh + 1;
                    zjzhService.xgyck(zjzhUpdate, true, ycxh, fffs, sflsbh);
                }
            }
            sfxh++;
        }

        //-------------------------------------EI数电发票数据添加---------------------
        yyQfmxList = qfmxService.lambdaQuery()
                .eq(YyQfmx::getSflsbh, sflsbh)
                .eq(YyQfmx::getEiYkfpBz, "0")
                .list();
        if (CollectionUtil.isNotEmpty(yyQfmxList)) {
            invoiceService.addInvoiceData(yyQfmxList, list, yhKhjbxx, "0", insert.getSfkp());
        }
        return true;
    }


    /**
     * 营业厅收费-小户收费-可部分收费-先扣后存
     */
    @Override
    @DSTransactional
    public List<String> payByReduceFirst(@NotNull YySspjxxInsert insert) throws Exception {
        List<Integer> chargeTypes = insert.getChargeTypes();
        if (CollectionUtil.isEmpty(chargeTypes)) {
            throw new FeesException("请选择费用项目", BUSINESS_ERROR);
        }

        String fffs = insert.getFffs();
        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("付费方式为空", BUSINESS_ERROR);
        }

        String yhbh = insert.getYhbh();
        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
        if (yhKhjbxx == null) {
            throw new FeesException("用户不存在", BUSINESS_ERROR);
        }
        if (yhKhjbxx.getDxh().equals(1)) {
            throw new FeesException("用户为大户用户，请到大用户收费模块收费！", BUSINESS_ERROR);
        }
        BigDecimal sszje = insert.getSszje();
        String sflsbh = GuidGenerator.getSflsbh();
        Date now = new Date();
        List<String> printpjList = new ArrayList<>();
        List<String> qfids = insert.getQfids();
        // 无欠费明细，相当于充值
        if (CollectionUtil.isEmpty(qfids)) {
            YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
            zjzhUpdate.setYhbh(yhbh);
            zjzhUpdate.setJe(sszje);
            zjzhUpdate.setSfrq(now);
            zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);
            printpjList.add(yffpj(sflsbh, 预付费收取.getValue().toString(), ""));
            return printpjList;
        }

        return this.dxhqfsf(qfids, yhKhjbxx, insert.getChargeTypes(),
                sflsbh, insert.getDyfs(), fffs, insert.getSfkp(), now, "xh", sszje);
    }


    private void updateZjzh(String yhbh, BigDecimal bcyfje, Date now, int sfxh, String fffs, String sflsbh) {
        YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
        zjzhUpdate.setYhbh(yhbh);
        zjzhUpdate.setJe(bcyfje);
        zjzhUpdate.setSfrq(now);
        zjzhService.xgyck(zjzhUpdate, true, sfxh, fffs, sflsbh);
    }

    /**
     * 大户收费-主账户扣费-可部分收费-先扣后存
     */
    @Override
    @DSTransactional
    public List<String> keyAccountCharge(YySspjxxInsert insert) throws Exception {
        List<Integer> chargeTypes = insert.getChargeTypes();
        if (CollectionUtil.isEmpty(chargeTypes)) {
            throw new FeesException("请选择费用项目", BUSINESS_ERROR);
        }
        String fffs = insert.getFffs();
        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("付费方式为空", BUSINESS_ERROR);
        }

        // 大户客户编码相同，根据客户编码找到主户，收费信息与账户使用主户信息
        String yhbh = insert.getYhbh();
        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
        String khbm = yhKhjbxx.getKhbm();
        if (StrUtil.isEmpty(khbm)) {
            throw new FeesException("请先添加该户的客户编码", BUSINESS_ERROR);
        }

        YhKhjbxx keyAccount;
        Integer zhbz = yhKhjbxx.getZhbz();
        if (ObjectUtil.isNotNull(zhbz) && zhbz == 1) {
            keyAccount = yhKhjbxx;
        } else {
            // 如果没有主户标志或不是主户的，根据客户编码和标志找到主户
            keyAccount = khjbxxService.selectByKhbm(khbm);
        }
        if (keyAccount == null) {
            throw new FeesException("该用户档案未找到主户信息", BUSINESS_ERROR);
        }

        String zhyhbh = keyAccount.getYhbh();

        BigDecimal sszje = insert.getSszje();
        String sflsbh = GuidGenerator.getSflsbh();
        Date now = new Date();
        List<String> printpjList = new ArrayList<>();
        List<String> qfids = insert.getQfids();
        // 无欠费明细，相当于充值
        if (CollectionUtil.isEmpty(qfids)) {
            YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
            zjzhUpdate.setYhbh(zhyhbh);
            zjzhUpdate.setJe(sszje);
            zjzhUpdate.setSfrq(now);
//            zjzhService.dhsfxgyck(zjzhUpdate, khbm, true, 1, fffs, sflsbh);
            zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);
            printpjList.add(yffpj(sflsbh, 预付费收取.getValue().toString(), ""));
            return printpjList;
        }

        return this.dxhqfsf(qfids, keyAccount, insert.getChargeTypes(),
                sflsbh, insert.getDyfs(), fffs, insert.getSfkp(), now, "dh", sszje);
    }

    /**
     * 大小户欠费收取
     */
    private List<String> dxhqfsf(List<String> qfids, YhKhjbxx yhKhjbxx, List<Integer> chargeTypes,
                                 String sflsbh, String dyfs, String fffs, String sfkp, Date now,
                                 String type, BigDecimal sszje) throws Exception {
        List<YyQfmx> yyQfmxes = qfmxService.listByIds(qfids);
        if (CollectionUtil.isEmpty(yyQfmxes)) {
            throw new FeesException("欠费明细不存在", BUSINESS_ERROR);
        }

        // 校验欠费状态
        for (YyQfmx e : yyQfmxes) {
            if ("1".equals(e.getSfbz()))
                throw new FeesException(String.format("已收费:用户%s[%s]，财务日期：%s", e.getYhxm(), e.getYhbh(), e.getCwrq()), BUSINESS_ERROR);
            if ("1".equals(e.getChbz()))
                throw new FeesException(String.format("已冲红:用户%s[%s]，财务日期：%s", e.getYhxm(), e.getYhbh(), e.getCwrq()), BUSINESS_ERROR);
        }

        yyQfmxes = yyQfmxes.stream()
                .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                .collect(Collectors.toList());

        BigDecimal yhye = BigDecimal.ZERO;
        YyZjzh zjzh = zjzhService.getById(yhKhjbxx.getYhbh());

        if (zjzh != null) {
            BigDecimal syje = zjzh.getSyje();
            yhye = syje == null ? BigDecimal.ZERO : syje;
        }

//        YyQfmx firstQfmx = yyQfmxes.get(0);
//        BigDecimal ysje = firstQfmx.getYsje();
//        BigDecimal znj = firstQfmx.getZnj();
//        ysje = ysje == null ? BigDecimal.ZERO : ysje;
//        znj = znj == null ? BigDecimal.ZERO : znj;
//        if (yhye.compareTo(ysje.add(znj)) > 0) {
//            throw new FeesException("剩余预付费大于等于最早一笔欠费", BUSINESS_ERROR);
//        }

        // 应收总金额
        BigDecimal yszje = yyQfmxes.stream().map(YyQfmx::getYsje)
                .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 应收滞纳金(违约金)
//        BigDecimal yszwyj = yyQfmxes.stream().map(e -> e.getZnj())
//                .filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
        // 总费用减去账户余额
//        yszje = yszje.add(yszwyj).subtract(yhye);
        if (CollectionUtil.isNotEmpty(chargeTypes) && chargeTypes.size() != 6) {
            yszje = BigDecimal.ZERO;
            if (chargeTypes.contains(1)) {
                BigDecimal yssf = yyQfmxes.stream().map(YyQfmx::getYssf)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                yszje = yszje.add(yssf);
            }
            if (chargeTypes.contains(2)) {
                BigDecimal yswsf = yyQfmxes.stream().map(YyQfmx::getYswsf)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                yszje = yszje.add(yswsf);
            }
            if (chargeTypes.contains(3)) {
                BigDecimal ysszyf = yyQfmxes.stream().map(YyQfmx::getYsszyf)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                yszje = yszje.add(ysszyf);
            }
            if (chargeTypes.contains(4)) {
                BigDecimal ysecjyf = yyQfmxes.stream().map(YyQfmx::getYsecjyf)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                yszje = yszje.add(ysecjyf);
            }
            if (chargeTypes.contains(5)) {
                BigDecimal ysfjf = yyQfmxes.stream().map(YyQfmx::getYsfjf)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                yszje = yszje.add(ysfjf);
            }
            if (chargeTypes.contains(6)) {
                BigDecimal ysxfsf = yyQfmxes.stream().map(YyQfmx::getYsqt)
                        .filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                yszje = yszje.add(ysxfsf);
            }
        }
        yszje = yszje.subtract(yhye);

        if (sszje.compareTo(yszje) < 0) {
            throw new FeesException("缴费金额低于欠费金额", FeesErrorCode.BUSINESS_ERROR);
        }
        // 实收金额减-要扣减的金额 = 存进账户的
        BigDecimal bcyfje = sszje.subtract(yszje);
        //判断用户余额是否大于欠费总金额
        if (yszje.compareTo(BigDecimal.ZERO) <= 0) {
            bcyfje = sszje;
        }
        List<String> printpjList = new ArrayList<>();
        List<YySspjxx> list = new ArrayList<>();
        int sfxh = 1;
        String currentUserId = SecurityUtils.getUserId().toString();
        for (YyQfmx qfmx : yyQfmxes) {
            if (CollectionUtil.isNotEmpty(chargeTypes) && chargeTypes.size() != 6) {
                // 部分收费时：生成已收费状态的欠费明细，原欠费明细中费用置为0
                YyQfmx chargeDetail = qfmxService.createByPartialCharges(qfmx, chargeTypes, sflsbh);
                qfmx = chargeDetail;
            } else {
                // 如果全交不用拆分，直接更新
                qfmxService.lambdaUpdate().set(YyQfmx::getSfrq, now).set(YyQfmx::getSfbz, "1")
                        .set(YyQfmx::getSflsbh, sflsbh).eq(YyQfmx::getId, qfmx.getId())
                        .update();
            }

            BigDecimal bckj1 = BigDecimal.ZERO;
            BigDecimal scye1 = BigDecimal.ZERO;
            BigDecimal ysje1 = qfmx.getYsje();
            BigDecimal znj1 = qfmx.getZnj();
            BigDecimal sszje1 = null;

            if (yhye.compareTo(ysje1.add(znj1)) >= 0) {
                scye1 = yhye;
                bckj1 = ysje1.add(znj1);
                sszje1 = BigDecimal.ZERO;
            } else {
                scye1 = yhye;
                bckj1 = yhye;
                sszje1 = ysje1.add(znj1).subtract(yhye);
            }
            yhye = yhye.subtract(bckj1);

            YySspjxx sspjxx = new YySspjxx();
            BeanUtils.copyProperties(qfmx, sspjxx);
            sspjxx.setQfid(qfmx.getId());
            sspjxx.setSfxh(sfxh);//收费序号
            sspjxx.setBckj(bckj1);//本次扣减
            sspjxx.setBcye(yhye);//本次余额
            sspjxx.setScye(scye1);//上次余额
            sspjxx.setSflx(欠费收取);
            sspjxx.setSszje(sszje1);
            sspjxx.setFffs(fffs);
            sspjxx.setSflsbh(sflsbh);
            sspjxx.setSfrq(now);
            sspjxx.setSfsjrq(now);
            sspjxx.setChbz(PjztEnum.正常.getValue());
            sspjxx.setSfbz("1");
            sspjxx.setFph2(yyPjbhService.getPjh(currentUserId));
            sspjxx.setSfrybm(currentUserId);
            sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
            sspjxx.setKhbm(qfmx.getKhbm());

            this.save(sspjxx);
            list.add(sspjxx);


            if (bckj1.compareTo(BigDecimal.ZERO) > 0) {
                zjzhService.lambdaUpdate()
                        .setSql(String.format("syje = syje-(%s)", bckj1))
                        .setSql(String.format("kjje = kjje+(%s)", bckj1))
                        .setSql(String.format("nbsyje = nbsyje-(%s)", bckj1))
                        .eq(YyZjzh::getYhbh, yhKhjbxx.getYhbh())
                        .update();
            }
            // 最后一条欠费
            if (yyQfmxes.size() == sfxh) {
                if (bcyfje.compareTo(BigDecimal.ZERO) > 0) {
                    int ycxh = sfxh + 1;
                    // 扣费后有剩余的存进账户
//                    if (type.equals("dh")) {
//                        YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
//                        zjzhUpdate.setYhbh(yhKhjbxx.getYhbh());
//                        zjzhUpdate.setJe(bcyfje);
//                        zjzhUpdate.setSfrq(now);
//                        zjzhService.dhsfxgyck(zjzhUpdate, yhKhjbxx.getKhbm(), true, ycxh, fffs, sflsbh);
//                    } else {
//                        updateZjzh(yhKhjbxx.getYhbh(), bcyfje, now, ycxh, fffs, sflsbh);
//                    }
                    updateZjzh(yhKhjbxx.getYhbh(), bcyfje, now, ycxh, fffs, sflsbh);
                }
            }
            sfxh++;
        }
        // 打印票据
        printPjList(dyfs, currentUserId, sflsbh, yhKhjbxx, printpjList, type);

        // 已收费明细预开发票
        LambdaQueryWrapper<YyQfmx> wrapper = Wrappers.<YyQfmx>lambdaQuery()
                .eq(YyQfmx::getSflsbh, sflsbh)
                .eq(YyQfmx::getSfbz, "1")
                .eq(YyQfmx::getEiYkfpBz, "0");
        List<YyQfmx> qfmxList = qfmxService.list(wrapper);

        if (CollUtil.isNotEmpty(qfmxList)) {
            invoiceService.addInvoiceData(qfmxList, list, yhKhjbxx, "0", sfkp);
        }
        return printpjList;
    }

    /**
     * 楼栋户批量收费
     */
    @Override
    @DSTransactional
    public List<String> batchCharge(PlsfReq plsfReq) {
        List<String> qfmxs = plsfReq.getQfmxs();
        if (CollectionUtil.isEmpty(qfmxs)) {
            throw new FeesException("请选择批量收费的明细", BUSINESS_ERROR);
        }

        String fffs = plsfReq.getFffs();
        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("请选择付费方式", BUSINESS_ERROR);
        }

        List<YyQfmx> dataList = new ArrayList<>();
        List<List<String>> listqfids = Lists.partition(qfmxs, 1000);
        for (List<String> qfids : listqfids) {
            dataList.addAll(qfmxService.listByIds(qfids));
        }
        if (CollectionUtil.isEmpty(dataList)) {
            throw new FeesException("未查询到欠费明细", BUSINESS_ERROR);
        }

        String sscbb = dataList.get(0).getSscbb();
        Plsfkhxx info = plsfkhxxService.getUserInfoByCode(sscbb);
        if (ObjectUtil.isNull(info)) {
            throw new FeesException("未找到抄表本客户信息,请先配置抄表本对应客户的开票信息", BUSINESS_ERROR);
        }

        // 欠费更新
        String sflsbh = GuidGenerator.getSflsbh();
        dataList.forEach(o -> {
            o.setSflsbh(sflsbh);
            o.setSfbz("1");
        });
        if (dataList.size() > 1000) {
            List<List<YyQfmx>> listqfmxs = Lists.partition(dataList, 1000);
            listqfmxs.forEach(
                    o -> qfmxService.updateBatchById(o)
            );
        } else {
            qfmxService.updateBatchById(dataList);
        }

        String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
        plsfpjxx(dataList, fffs, sflsbh, pjh);

        // 票据和电子发票合并
        YySspjxx hbpjxx = mergeDetailList(dataList, fffs, sflsbh, info);
        String printStr = printReceipt(hbpjxx, pjh, info);

        dataList = dataList.stream().filter(o -> "0".equalsIgnoreCase(o.getEiYkfpBz())).collect(Collectors.toList());
        /*
        if (CollectionUtil.isNotEmpty(dataList)) {
            List<YySspjxx> list = new ArrayList<>();
            list.add(hbpjxx);
            YhKhjbxx yhKhjbxx = JSONObject.parseObject(JSON.toJSONString(info), YhKhjbxx.class);
            yhKhjbxx.setYhxm(info.getGfxm());
            yhKhjbxx.setFpDz(info.getGfdz());
            yhKhjbxx.setFpLxdh(info.getGfdh());
            invoiceService.addInvoiceData(dataList, list, yhKhjbxx, "0", "1", "1");
        }
        */

        List<String> printpjList = new ArrayList<>();
        printpjList.add(printStr);
        return printpjList;
    }

    /**
     * 批量收费创建实收明细
     */
    private void plsfpjxx(List<YyQfmx> dataList, String fffs, String sflsbh, String pjh) {
        int sfxh = 1;
        Date now = new Date();

        for (YyQfmx qfmx : dataList) {
            BigDecimal yhye = BigDecimal.ZERO;

            String yhbh = qfmx.getYhbh();
            YyZjzh zjzh = zjzhService.getById(yhbh);
            if (ObjUtil.isNotNull(zjzh)) {
                BigDecimal syje = zjzh.getSyje();
                yhye = syje == null ? BigDecimal.ZERO : syje;
            }

            BigDecimal bckj1 = BigDecimal.ZERO;
            BigDecimal ysje1 = qfmx.getYsje();

            BigDecimal znj1 = qfmx.getZnj();
            BigDecimal sszje1 = BigDecimal.ZERO;
            BigDecimal bcjz1 = BigDecimal.ZERO;

            // 计算实收金额
            if (sfxh == 1) {
                bckj1 = yhye;
                sszje1 = ysje1.add(znj1).subtract(yhye);
            } else {
                sszje1 = ysje1.add(znj1);
            }

            YySspjxx sspjxx = new YySspjxx();
            BeanUtils.copyProperties(qfmx, sspjxx, NumberHelper.getNullPropertyNames(qfmx));

            sspjxx.setQfid(qfmx.getId());
            sspjxx.setSfxh(sfxh);
            sspjxx.setBckj(bckj1);
            sspjxx.setBcye(bcjz1);
            sspjxx.setScye(bckj1);
            sspjxx.setSflx(欠费收取);
            sspjxx.setSszje(sszje1);
            sspjxx.setFffs(fffs);
            sspjxx.setSflsbh(sflsbh);
            sspjxx.setSfrq(now);
            sspjxx.setSfsjrq(now);
            sspjxx.setChbz(PjztEnum.正常.getValue());
            sspjxx.setSfbz("1");
            sspjxx.setFph2(pjh);
            sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
            sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
            this.save(sspjxx);
            sfxh++;
        }
    }

    public List<String> qtfysf(YySspjxxInsertQtfy insert) throws Exception {
        List<YySspjxxInsertQtfymx> qtfymxs = insert.getQtfymx();
        if (CollectionUtil.isEmpty(qtfymxs)) {
            throw new FeesException("请填写费用明细", BUSINESS_ERROR);
        }
        String fffs = insert.getFffs();
        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("请选择付费方式", BUSINESS_ERROR);
        }
        YhKhjbxx yhKhjbxx = khjbxxService.getById(insert.getYhbh());
        if (StringUtil.isNull(yhKhjbxx)) {
            throw new FeesException("未找到用户信息", BUSINESS_ERROR);
        }
        BigDecimal mxzje = qtfymxs.stream().map(YySspjxxInsertQtfymx::getJe).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (mxzje.compareTo(BigDecimal.ZERO) <= 0) {
            throw new FeesException("请填写正确的费用明细金额", BUSINESS_ERROR);
        }
        BigDecimal yhye = BigDecimal.ZERO;
        if (fffs.equals("9") || insert.getYesfcyjs().equals("1")) {
            YyZjzh zjzh = zjzhService.getById(insert.getYhbh());
            if (zjzh != null) {
                BigDecimal syje = zjzh.getSyje();
                yhye = syje == null ? BigDecimal.ZERO : syje;
            }
            if (mxzje.compareTo(yhye.add(insert.getSszje())) > 0) {
                throw new FeesException("费用明细汇总金额大于实收加用户余额，无法收费", BUSINESS_ERROR);
            }
        } else {
            if (mxzje.compareTo(insert.getSszje()) != 0) {
                throw new FeesException("实收金额与费用明细汇总金额不一致，无法收费", BUSINESS_ERROR);
            }
        }
        List<YySspjxx> list = new ArrayList<>();
        int sfxh = 1;
        String sflsbh = GuidGenerator.getSflsbh();
        Date now = new Date();
        String currentUserId = SecurityUtils.getUserId().toString();
        String pjh = yyPjbhService.getPjh(currentUserId);
        String cwrq = gdcsbService.selectCwrq();
        for (YySspjxxInsertQtfymx qtfymx : qtfymxs) {
            BigDecimal bckj1;
            BigDecimal scye1;
            BigDecimal ysje1 = qtfymx.getJe();
            BigDecimal sszje1;

            if (yhye.compareTo(ysje1) >= 0) {
                scye1 = yhye;
                bckj1 = ysje1;
                sszje1 = BigDecimal.ZERO;
            } else {
                scye1 = yhye;
                bckj1 = yhye;
                sszje1 = ysje1.subtract(yhye);
            }
            yhye = yhye.subtract(bckj1);

            YySspjxx sspjxx = new YySspjxx();
            BeanUtils.copyProperties(yhKhjbxx, sspjxx);
            sspjxx.setCwrq(cwrq);
            sspjxx.setSfxh(sfxh);//收费序号
            sspjxx.setBckj(bckj1);//本次扣减
            sspjxx.setBcye(yhye);//本次余额
            sspjxx.setScye(scye1);//上次余额
            sspjxx.setYsje(ysje1);
            sspjxx.setYsqt(ysje1);
            sspjxx.setSszje(sszje1);
            sspjxx.setFffs(fffs);
            sspjxx.setSflsbh(sflsbh);
            sspjxx.setSfrq(now);
            sspjxx.setSfsjrq(now);
            sspjxx.setChbz(PjztEnum.正常.getValue());
            sspjxx.setSfbz("1");
            sspjxx.setFph2(pjh);
            sspjxx.setSfrybm(currentUserId);
            sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
            sspjxx.setCbjsbz("6");
            sspjxx.setCbjsfs("其他费用计费");
            sspjxx.setFplx(yhKhjbxx.getFplx());
            sspjxx.setBz(insert.getBz());
            sspjxx.setFylx(qtfymx.getFylx());
            sspjxx.setFylxmc(qtfymx.getFylxmc());
            if (!fffs.equals("9")) {
                sspjxx.setSflx(欠费收取);
            } else {
                sspjxx.setSflx(预存抵扣);
            }
            this.save(sspjxx);
            list.add(sspjxx);

            if (bckj1.compareTo(BigDecimal.ZERO) > 0) {
                zjzhService.lambdaUpdate()
                        .setSql(String.format("syje = syje-(%s)", bckj1))
                        .setSql(String.format("kjje = kjje+(%s)", bckj1))
                        .setSql(String.format("nbsyje = nbsyje-(%s)", bckj1))
                        .eq(YyZjzh::getYhbh, yhKhjbxx.getYhbh())
                        .update();
            }
            sfxh++;
        }
        //是否合并开票暂未启用，默认0不合并
        eiFpkjRequestService.qtfykp(yhKhjbxx, list, insert.getSfkp(), "0");
        List<String> printpjList = new ArrayList<>();
        printpjList.add(this.qfsfpj(list, pjh, yhKhjbxx));
        return printpjList;
    }

    @Override
    public List<YySspjxxDailyStat2> getDailySummary(YySspjxxFilter filter) {
        List<YySspjxxDailyStat2> dailySummary = baseMapper.getDailySummary(filter);

//        String sfrybm = filter.getSfrybm();
//
//        if (CollectionUtil.isNotEmpty(dailySummary) && StrUtil.isNotEmpty(sfrybm)) {
//            User user = userService.get(Long.valueOf(sfrybm));
//            if (ObjUtil.isNotNull(user)) {
//                dailySummary.forEach(o -> o.setSfryxm(user.getRealName()));
//            }
//        }
        return dailySummary;
    }

    @Override
    public List<YySspjxxDailyStat1> getDailySummary1(YySspjxxFilter filter) {
        List<YySspjxxDailyStat1> dailySummary = new ArrayList<>();
        //获取非水费费用
        List<Map> mapListfsf = baseMapper.getDailySummary_fsf(filter);
        //获取水费费用
        List<Map> mapListsf = baseMapper.getDailySummary_sf(filter);
        String cwrq = bmYmjzConfigService.getCwrq(filter.getSfrqStart());
        BigDecimal bckj = BigDecimal.ZERO;
        if (!mapListsf.isEmpty()) {
            //水费当月
            List<Map> sf_dy = mapListsf.stream().filter(o -> cwrq.compareTo(o.get("cwrq").toString()) <= 0).collect(Collectors.toList());
            if (!sf_dy.isEmpty()) {
                List<String> xmmc = sf_dy.stream().map(o -> o.get("name").toString()).distinct().collect(Collectors.toList());
                xmmc.forEach(o -> {
                    List<BigDecimal> sjlist = sf_dy.stream()
                            .filter(item -> item.get("name").equals(o))
                            .map(item -> (BigDecimal) item.get("sj")).distinct().collect(Collectors.toList());
                    sjlist.forEach(sj -> {
                        List<Map> sf_dy_mc = sf_dy.stream().filter(item -> item.get("name").equals(o)).collect(Collectors.toList());
                        YySspjxxDailyStat1 dailyStat = new YySspjxxDailyStat1();
                        dailyStat.setXmmc(o + "(本月)");
                        BigDecimal sl = sf_dy_mc.stream().filter(item -> item.get("sj").equals(sj))
                                .map(item -> (BigDecimal) item.get("sl"))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal je = sf_dy_mc.stream().filter(item -> item.get("sj").equals(sj))
                                .map(item -> (BigDecimal) item.get("sf"))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        dailyStat.setJg(sj);
                        dailyStat.setSl(sl);
                        dailyStat.setJe(je);
                        dailySummary.add(dailyStat);
                    });
                });
            }
            //水费非当月
            List<Map> sf_yqy = mapListsf.stream().filter(o -> cwrq.compareTo(o.get("cwrq").toString()) > 0).collect(Collectors.toList());
            if (!sf_yqy.isEmpty()) {
                List<String> xmmc = sf_yqy.stream().map(o -> o.get("name").toString()).distinct().collect(Collectors.toList());
                xmmc.forEach(o -> {
                    List<BigDecimal> sjlist = sf_yqy.stream()
                            .filter(item -> item.get("name").equals(o))
                            .map(item -> (BigDecimal) item.get("sj")).distinct().collect(Collectors.toList());
                    sjlist.forEach(sj -> {
                        List<Map> sf_yqy_mc = sf_yqy.stream().filter(item -> item.get("name").equals(o)).collect(Collectors.toList());
                        YySspjxxDailyStat1 dailyStat = new YySspjxxDailyStat1();
                        dailyStat.setXmmc(o + "(以前月)");
                        BigDecimal sl = sf_yqy_mc.stream().filter(item -> item.get("sj").equals(sj))
                                .map(item -> (BigDecimal) item.get("sl"))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal je = sf_yqy_mc.stream().filter(item -> item.get("sj").equals(sj))
                                .map(item -> (BigDecimal) item.get("sf"))
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                        dailyStat.setJg(sj);
                        dailyStat.setSl(sl);
                        dailyStat.setJe(je);
                        dailySummary.add(dailyStat);
                    });
                });
            }
        }
        if (!mapListfsf.isEmpty()) {
            //非水费当月
            List<Map> fsf_dy = mapListfsf.stream().filter(o -> cwrq.compareTo(o.get("cwrq").toString()) <= 0).collect(Collectors.toList());
            if (!fsf_dy.isEmpty()) {
                BigDecimal yswsf = fsf_dy.stream().filter(o -> !o.get("yswsf").equals("0")).map(o -> (BigDecimal) o.get("yswsf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysszyf = fsf_dy.stream().filter(o -> !o.get("ysszyf").equals("0")).map(o -> (BigDecimal) o.get("ysszyf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysecjyf = fsf_dy.stream().filter(o -> !o.get("ysecjyf").equals("0")).map(o -> (BigDecimal) o.get("ysecjyf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysfjf = fsf_dy.stream().filter(o -> !o.get("ysfjf").equals("0")).map(o -> (BigDecimal) o.get("ysfjf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysqt = fsf_dy.stream().filter(o -> !o.get("ysqt").equals("0")).map(o -> (BigDecimal) o.get("ysqt")).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (yswsf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("污水费(本月)", BigDecimal.ZERO, BigDecimal.ZERO, yswsf));
                }
                if (ysszyf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("水资源税(本月)", BigDecimal.ZERO, BigDecimal.ZERO, ysszyf));
                }
                if (ysecjyf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("二次加压费(本月)", BigDecimal.ZERO, BigDecimal.ZERO, ysecjyf));
                }
                if (ysfjf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("附加费(本月)", BigDecimal.ZERO, BigDecimal.ZERO, ysfjf));
                }
                if (ysqt.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("消防栓费(本月)", BigDecimal.ZERO, BigDecimal.ZERO, ysqt));
                }
            }
            //非水费非当月
            List<Map> fsf_yqy = mapListfsf.stream().filter(o -> cwrq.compareTo(o.get("cwrq").toString()) > 0).collect(Collectors.toList());
            if (!fsf_yqy.isEmpty()) {
                BigDecimal yswsf = fsf_yqy.stream().filter(o -> !o.get("yswsf").equals("0")).map(o -> (BigDecimal) o.get("yswsf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysszyf = fsf_yqy.stream().filter(o -> !o.get("ysszyf").equals("0")).map(o -> (BigDecimal) o.get("ysszyf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysecjyf = fsf_yqy.stream().filter(o -> !o.get("ysecjyf").equals("0")).map(o -> (BigDecimal) o.get("ysecjyf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysfjf = fsf_yqy.stream().filter(o -> !o.get("ysfjf").equals("0")).map(o -> (BigDecimal) o.get("ysfjf")).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ysqt = fsf_yqy.stream().filter(o -> !o.get("ysqt").equals("0")).map(o -> (BigDecimal) o.get("ysqt")).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (yswsf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("污水费(以前月)", BigDecimal.ZERO, BigDecimal.ZERO, yswsf));
                }
                if (ysszyf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("水资源税(以前月)", BigDecimal.ZERO, BigDecimal.ZERO, ysszyf));
                }
                if (ysecjyf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("二次加压费(以前月)", BigDecimal.ZERO, BigDecimal.ZERO, ysecjyf));
                }
                if (ysfjf.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("附加费(以前月)", BigDecimal.ZERO, BigDecimal.ZERO, ysfjf));
                }
                if (ysqt.compareTo(BigDecimal.ZERO) > 0) {
                    dailySummary.add(new YySspjxxDailyStat1("消防栓费(以前月)", BigDecimal.ZERO, BigDecimal.ZERO, ysqt));
                }
            }
            BigDecimal ycje = mapListfsf.stream().filter(o -> !o.get("bcyc").equals("0"))
                    .map(o -> (BigDecimal) o.get("bcyc")).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (ycje.compareTo(BigDecimal.ZERO) > 0) {
                dailySummary.add(new YySspjxxDailyStat1("预存款", BigDecimal.ZERO, BigDecimal.ZERO, ycje));
            }
            bckj = mapListfsf.stream().filter(o -> !o.get("bckj").equals("0"))
                    .map(o -> (BigDecimal) o.get("bckj")).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (bckj.compareTo(BigDecimal.ZERO) > 0) {
                dailySummary.add(new YySspjxxDailyStat1("冲预缴扣减（-）", BigDecimal.ZERO, BigDecimal.ZERO, bckj));
            }
        }
        if (!dailySummary.isEmpty()) {
            YySspjxxDailyStat1 dailyStat = new YySspjxxDailyStat1();
            dailyStat.setXmmc("合计");
            dailyStat.setJg(BigDecimal.ZERO);
            dailyStat.setSl(dailySummary.stream().map(YySspjxxDailyStat1::getSl).reduce(BigDecimal.ZERO, BigDecimal::add));
            dailyStat.setJe(dailySummary.stream().filter(o -> !o.getXmmc().equals("冲预缴扣减（-）"))
                    .map(YySspjxxDailyStat1::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).subtract(bckj));
            dailySummary.add(dailyStat);
        }
        return dailySummary;
    }

    /**
     * 批量收费合并票据打印
     */
    private String printReceipt(YySspjxx yySspjxx, String pjh, Plsfkhxx info) {
        StringBuilder str = new StringBuilder();

        BigDecimal yssl = checkNumber(yySspjxx.getYssl());
        BigDecimal yssf = checkNumber(yySspjxx.getYssf());

        BigDecimal ysecjyf = checkNumber(yySspjxx.getYsecjyf());
        BigDecimal ysfjf = checkNumber(yySspjxx.getYsfjf());
        BigDecimal ysqtf = checkNumber(yySspjxx.getYsqt());

        BigDecimal yswsf = checkNumber(yySspjxx.getYswsf());
        BigDecimal ysljf = checkNumber(yySspjxx.getYsljf());
        BigDecimal ysszyf = checkNumber(yySspjxx.getYsszyf());
        BigDecimal yswyj = checkNumber(yySspjxx.getZnj());
        BigDecimal ysje = checkNumber(yySspjxx.getBckj());
        BigDecimal sszje = checkNumber(yySspjxx.getSszje());
        BigDecimal scye = yySspjxx.getScye();
        BigDecimal ycje = yySspjxx.getBcye();
        String cbrybm = yySspjxx.getCbrybm();
        String sfrybm = yySspjxx.getSfrybm();
        String sfryxm = yySspjxx.getSfryxm();
        //水费
        if (yssf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "基本水费"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", yssf.divide(yssl, 2, RoundingMode.HALF_UP)));
            // 水费 = 基本水费+ 二次加压 + 附加 + 消防栓费
            if (ysecjyf.compareTo(BigDecimal.ZERO) > 0 || ysfjf.compareTo(BigDecimal.ZERO) > 0 || ysqtf.compareTo(BigDecimal.ZERO) > 0) {
                yssf = yssf.add(ysecjyf).add(ysfjf).add(ysqtf);
            }
            str.append(String.format("<td>%s</td>", yssf));
            str.append("</tr>");
        }
        //污水费
        if (yswsf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "污水处理费"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", yswsf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", yswsf));
            str.append("</tr>");
        }
        //水资源税
        if (ysszyf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "水资源税"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", ysszyf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", ysszyf));
            str.append("</tr>");
        }

        String htmlstr = getHtmlContent("templates/sspjxx.html");
        BmGs bmGs = bmGsService.getById("1");
        htmlstr = htmlstr.replace("{{title}}", String.format("%s水费专用收据", bmGs.getMc()));
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{yhxm}}", info.getGfxm());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(info.getGfdz()) ? "" : info.getGfdz());
        htmlstr = htmlstr.replace("{{sfrq}}", yySspjxx.getSfrq().toString());
        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(info.getGfdh()) ? "" : info.getGfdh());
        htmlstr = htmlstr.replace("{{sl}}", yssl.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{content}}", str.toString());
        //实际应收金额=应收金额+违约金-剩余金额
        htmlstr = htmlstr.replace("{{ysje}}", ysje.subtract(scye).setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sszje));
        htmlstr = htmlstr.replace("{{scjy}}", scye.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcjy}}", ycje.setScale(2, RoundingMode.HALF_UP).toString());
        //实际实收金额=应收金额+违约金-剩余金额+预存金额
        htmlstr = htmlstr.replace("{{sszje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(sfryxm) ? "" : sfryxm);
        htmlstr = htmlstr.replace("{{dysj}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        htmlstr = htmlstr.replace("{{fwzmc}}", "营业大厅");
        // 批量收费默认值
        htmlstr = htmlstr.replace("{{yhbh}}", "小区批量收费");
        htmlstr = htmlstr.replace("{{scds}}", "");
        htmlstr = htmlstr.replace("{{bcds}}", "");

        if (NumberUtil.isNumber(cbrybm)) {
            User user = userService.get(Long.valueOf(cbrybm));
            String cbrydh = "暂无";
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
            htmlstr = htmlstr.replace("{{cbrydh}}", cbrydh);
        }

        htmlstr = htmlstr.replace("{{sjh}}", pjh); // 收据号
        this.lambdaUpdate().setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getSflsbh, yySspjxx.getSflsbh())
                .update();
        return htmlstr;
    }

    /**
     * 批量缴费后总票据信息
     */
    private YySspjxx mergeDetailList(List<YyQfmx> dataList, String fffs, String sflsbh, Plsfkhxx info) {
        YySspjxx sspjxx = new YySspjxx();
        Date now = new Date();

        YyQfmx yyQfmx = dataList.get(0);
//        BeanUtils.copyProperties(qfmx, sspjxx);
        sspjxx.setFylx(String.valueOf(BcFylxEnum.Zhfy.getValue()));
        sspjxx.setJfqd("01");
        sspjxx.setJtzqljlJsq(BigDecimal.ZERO);
        sspjxx.setJtzqljl(BigDecimal.ZERO);
        sspjxx.setYhxm(info.getGfxm());
        sspjxx.setSfxh(1);
        sspjxx.setFylxmc(BcFylxEnum.Zhfy.getName());
        sspjxx.setSfbc(yyQfmx.getSfbc());
        // pl—批量用户id
        sspjxx.setYhbh("pl-" + info.getId());
        sspjxx.setSsgs(yyQfmx.getSsgs());
        sspjxx.setSscbpq(yyQfmx.getSscbpq());
        sspjxx.setSscbb(yyQfmx.getSscbb());
        sspjxx.setYsyf(yyQfmx.getYsyf());
        sspjxx.setCwrq(yyQfmx.getCwrq());
        sspjxx.setCbrybm(yyQfmx.getCbrybm());
        sspjxx.setCbryxm(yyQfmx.getCbryxm());
        sspjxx.setCbrq(yyQfmx.getCbrq());

        BigDecimal zje = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYsje()))
                .map(YyQfmx::getYsje).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal yssl = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYssl()))
                .map(YyQfmx::getYssl).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYssl(checkNumber(yssl));

        BigDecimal yssf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYssf()))
                .map(YyQfmx::getYssf).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYssf(checkNumber(yssf));

        BigDecimal ysecjyf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYsecjyf()))
                .map(YyQfmx::getYsecjyf).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYsecjyf(checkNumber(ysecjyf));

        BigDecimal ysfjf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYsfjf()))
                .map(YyQfmx::getYsfjf).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYsfjf(checkNumber(ysfjf));

        BigDecimal ysqtf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYsqt()))
                .map(YyQfmx::getYsqt).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYsqt(checkNumber(ysqtf));

        BigDecimal yswsf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYswsf()))
                .map(YyQfmx::getYswsf).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYswsf(checkNumber(yswsf));

        BigDecimal ysljf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYsljf()))
                .map(YyQfmx::getYsljf).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYsljf(checkNumber(ysljf));

        BigDecimal ysszyf = dataList.stream().filter(o -> ObjUtil.isNotNull(o.getYsszyf()))
                .map(YyQfmx::getYsszyf).reduce(BigDecimal.ZERO, BigDecimal::add);
        sspjxx.setYsszyf(checkNumber(ysszyf));

        //  本次扣减
        sspjxx.setBckj(zje);
        sspjxx.setSszje(zje);
        sspjxx.setScye(BigDecimal.ZERO);
        sspjxx.setBcye(BigDecimal.ZERO);
        sspjxx.setCbrybm(yyQfmx.getCbrybm());
        sspjxx.setQfid(StrUtil.EMPTY);

        sspjxx.setSflx(欠费收取);

        sspjxx.setFffs(fffs);
        sspjxx.setSflsbh(sflsbh);
        sspjxx.setSfrq(now);
        sspjxx.setSfsjrq(now);
        sspjxx.setChbz(PjztEnum.正常.getValue());
        sspjxx.setSfbz("1");
        sspjxx.setFph2(yyPjbhService.getPjh(SecurityUtils.getUserId().toString()));
        sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
        sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
        sspjxx.setKhbm("");
        return sspjxx;
    }

    private void printPjList(String dyfs, String currentUserId,
                             String sflsbh, YhKhjbxx yhKhjbxx, List<String> printpjList,
                             String type) throws Exception {
        // 票据打印
        List<YySspjxx> list = this.lambdaQuery()
                .eq(YySspjxx::getSflsbh, sflsbh)
                .orderByAsc(YySspjxx::getSfxh)
                .list();
        boolean islast = false;
        if (dyfs.equals("4") || dyfs.equals("5")) {
            String pjh = yyPjbhService.getPjh(currentUserId);
            if (dyfs.equals("4")) {
                String sspjhb = sspjhb(list, pjh, yhKhjbxx);
                printpjList.add(sspjhb);
            }
            YySspjxx sspjxx = list.stream().filter(o -> 预付费收取.equals(o.getSflx())).findFirst().orElse(null);
            if (StringUtil.isNotNull(sspjxx) && type.equals("dh")) {
                printpjList.add(yffpj(sspjxx));
            }
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .in(YySspjxx::getId, list.stream().map(YySspjxx::getId).collect(Collectors.toList()))
                    .update();
        } else {
            int ssxh = 1;
            for (YySspjxx sspjxx : list) {
                if (list.size() == ssxh) {
                    islast = true;
                }
                String pjh = yyPjbhService.getPjh(currentUserId);
                this.lambdaUpdate()
                        .set(YySspjxx::getFph2, pjh)
                        .eq(YySspjxx::getId, sspjxx.getId()).update();
                String sspj = sspj(sspjxx, islast, yhKhjbxx);
                printpjList.add(sspj);
                ssxh++;
            }
        }
    }

    //先扣后存方式
//    @Override
//    @DSTransactional
    public List<String> plsfsave1(@NotNull YySspjxxInsert insert) {
        try {
            List<String> qfids = insert.getQfids();
            String fffs = insert.getFffs();
            if (StringUtil.isEmpty(fffs))
                throw new FeesException("付费方式为空", BUSINESS_ERROR);
            String yhbh = insert.getYhbh();
            if (StringUtil.isEmpty(yhbh))
                throw new FeesException("用户编号不能为空", BUSINESS_ERROR);
            YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
            if (StringUtil.isNull(yhKhjbxx)) {
                throw new FeesException("用户不存在", BUSINESS_ERROR);
            }
            long count = yhGroupService.count(
                    Wrappers.<YhGroup>lambdaQuery()
                            .eq(YhGroup::getYhbh, yhbh)
            );
            if (count == 0) {
                throw new FeesException("用户不是群主用户，不能收费", BUSINESS_ERROR);
            }
            BigDecimal sszje = insert.getSszje();
            String sflsbh = GuidGenerator.getSflsbh();
            List<String> printpjList = new ArrayList<>();
            if (qfids == null || qfids.isEmpty()) {
                throw new FeesException("欠费明细ID为空", BUSINESS_ERROR);
            }
            List<YyQfmx> yyQfmxes = qfmxService.listByIds(qfids);
            if (yyQfmxes.isEmpty())
                throw new FeesException("欠费明细不存在", BUSINESS_ERROR);
            for (YyQfmx e : yyQfmxes) {
                if ("1".equals(e.getSfbz()))
                    throw new FeesException(String.format("已收费:%s", e.getId()), BUSINESS_ERROR);
                if ("1".equals(e.getChbz()))
                    throw new FeesException(String.format("已冲红:%s", e.getId()), BUSINESS_ERROR);
            }
            yyQfmxes = yyQfmxes.stream()
                    .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                    .collect(Collectors.toList());

            BigDecimal yhye = BigDecimal.ZERO;
            YyZjzh zjzh = zjzhService.getById(yhbh);//用户资金账号
            if (zjzh != null) {
                BigDecimal syje = zjzh.getSyje();
                yhye = syje == null ? BigDecimal.ZERO : syje;
            }
            YyQfmx firstQfmx = yyQfmxes.get(0);
            BigDecimal ysje = firstQfmx.getYsje();
            BigDecimal znj = firstQfmx.getZnj();
            ysje = ysje == null ? BigDecimal.ZERO : ysje;
            znj = znj == null ? BigDecimal.ZERO : znj;
            if (yhye.compareTo(ysje.add(znj)) > 0) {
                throw new FeesException("剩余预付费大于等于最早一笔欠费", BUSINESS_ERROR);
            }
            BigDecimal yszje = yyQfmxes.stream().map(e -> e.getYsje())
                    .filter(e -> e != null)
                    .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yszwyj = yyQfmxes.stream().map(e -> e.getZnj())
                    .filter(e -> e != null)
                    .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            yszje = yszje.add(yszwyj).subtract(yhye);//减去余额
            if (sszje.compareTo(yszje) < 0) {
                throw new FeesException("缴费金额低于欠费金额", BUSINESS_ERROR);
            }
            //BigDecimal bckj = yhye;//本次扣减
            //BigDecimal bcye = BigDecimal.ZERO;//本次余额
            BigDecimal bcyfje = sszje.subtract(yszje);//本次预付金额

            Date now = new Date();
            List<YySspjxx> list = new ArrayList<>();
            int sfxh = 1;
            for (YyQfmx qfmx : yyQfmxes) {
                //更新欠费明细
                qfmxService.lambdaUpdate()
                        .set(YyQfmx::getSfrq, now)
                        .set(YyQfmx::getSfbz, "1")
                        .set(YyQfmx::getSflsbh, sflsbh)
                        .eq(YyQfmx::getId, qfmx.getId())
                        .update();
                BigDecimal bckj1 = BigDecimal.ZERO;
                BigDecimal ysje1 = qfmx.getYsje();
                BigDecimal znj1 = qfmx.getZnj();
                BigDecimal sszje1 = null;
                BigDecimal bcjz1 = BigDecimal.ZERO;
                if (sfxh == 1) {
                    bckj1 = yhye;
                    sszje1 = ysje1.add(znj1).subtract(yhye);
                } else {
//                if (yyQfmxes.size() == sfxh) {
//                    bcjz1 = bcyfje;
//                }
                    sszje1 = ysje1.add(znj1);
                }
                YySspjxx sspjxx = new YySspjxx();
                BeanUtils.copyProperties(qfmx, sspjxx);
                sspjxx.setQfid(qfmx.getId());
                sspjxx.setSfxh(sfxh);//收费序号
                sspjxx.setBckj(bckj1);//本次扣减
                sspjxx.setBcye(bcjz1);//本次余额
                sspjxx.setScye(bckj1);//上次余额
                sspjxx.setSflx(欠费收取);
                sspjxx.setSszje(sszje1);
                sspjxx.setFffs(fffs);
                sspjxx.setSflsbh(sflsbh);
                sspjxx.setSfrq(now);
                sspjxx.setSfsjrq(now);
                sspjxx.setChbz(PjztEnum.正常.getValue());
                sspjxx.setSfbz("1");
                sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
                sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
                sspjxx.setQzhyhbh(yhbh);
                this.save(sspjxx);
                list.add(sspjxx);
                if (sfxh == 1) {
                    //用户余额不为零时
                    if (bckj1.compareTo(BigDecimal.ZERO) != 0) {
                        zjzhService.lambdaUpdate()
                                .setSql(String.format("syje = syje-(%s)", bckj1))
                                .setSql(String.format("kjje = kjje+(%s)", bckj1))
                                .eq(YyZjzh::getYhbh, yhbh)
                                .update();
                    }
                }
                sfxh++;
                if (yyQfmxes.size() + 1 == sfxh) {
                    if (bcyfje.compareTo(BigDecimal.ZERO) > 0) {
                        //更新资金账号
                        YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
                        zjzhUpdate.setYhbh(yhbh);
                        zjzhUpdate.setJe(bcyfje);
                        zjzhUpdate.setSfrq(now);
                        zjzhService.xgyck(zjzhUpdate, true, sfxh, fffs, sflsbh);
                    }
                }
            }
            boolean islast = false;
            if (insert.getDyfs().equals("4")) {
                String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
                printpjList.add(sspjhb(list, pjh, yhKhjbxx));
            } else {
                int ssxh = 1;
                for (YySspjxx sspjxx : list) {
                    if (list.size() == ssxh) {
                        islast = true;
                    }
                    String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
                    this.lambdaUpdate()
                            .set(YySspjxx::getFph2, pjh)
                            .eq(YySspjxx::getId, sspjxx.getId())
                            .update();
                    printpjList.add(sspj(sspjxx, islast, yhKhjbxx));
                    ssxh++;
                }
            }
            if (insert.getDyfs().equals("4"))
                //-------------------------------------EI数电发票数据添加---------------------
                yyQfmxes = qfmxService.lambdaQuery()
                        .in(YyQfmx::getId, qfids)
                        .eq(YyQfmx::getEiYkfpBz, "0")
                        .list();
            if (yyQfmxes.size() > 0) {
                invoiceService.addInvoiceData(yyQfmxes, list, yhKhjbxx, "1", insert.getSfkp());
            }
            return printpjList;
        } catch (Exception e) {
            throw new FeesException("批量收费失败", BUSINESS_ERROR);
        }
    }

    //先存后扣方式
    @Override
    @DSTransactional
    public List<String> payBysaveFirst(@NotNull YySspjxxInsert insert) throws Exception {
        List<String> qfids = insert.getQfids();
        String fffs = insert.getFffs();

        if (StringUtil.isEmpty(fffs)) {
            throw new FeesException("付费方式为空", BUSINESS_ERROR);
        }

        //if (!"1".equals(fffs)) throw new FeesException("付费方式暂不支持", FeesErrorCode.BUSINESS_ERROR);
        String yhbh = insert.getYhbh();
        if (this.sfsqzhgx(yhbh)) {
            throw new FeesException("用户存在群主户关系，请在群主户收费模块操作！", BUSINESS_ERROR);
        }

        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
        if (yhKhjbxx == null) {
            throw new FeesException("用户不存在", BUSINESS_ERROR);
        }

        BigDecimal sszje = insert.getSszje();
        String sflsbh = GuidGenerator.getSflsbh();

        List<String> printpjList = new ArrayList<>();
        Date now = new Date();

        YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
        zjzhUpdate.setYhbh(yhbh);
        zjzhUpdate.setJe(sszje);
        zjzhUpdate.setSfrq(now);

        // 没有欠费则预存
        if (CollectionUtil.isEmpty(qfids)) {
            zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);
            printpjList.add(yffpj(sflsbh, 预付费收取.getValue().toString(), ""));
            return printpjList;
        }

        List<YyQfmx> yyQfmxes = qfmxService.listByIds(qfids);
        if (yyQfmxes.isEmpty()) {
            throw new FeesException("欠费明细不存在", BUSINESS_ERROR);
        }

        for (YyQfmx e : yyQfmxes) {
            if ("1".equals(e.getSfbz())) {
                throw new FeesException(String.format("已收费:%s", e.getId()), BUSINESS_ERROR);
            }
            if ("1".equals(e.getChbz())) {
                throw new FeesException(String.format("已冲红:%s", e.getId()), BUSINESS_ERROR);
            }
        }

        yyQfmxes = yyQfmxes.stream()
                .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                .collect(Collectors.toList());

        BigDecimal yhye = BigDecimal.ZERO;
        if (StringUtil.isNotEmpty(insert.getYesfcyjs()) && insert.getYesfcyjs().equals("1")) {
            YyZjzh zjzh = zjzhService.getById(yhbh);//用户资金账号
            if (zjzh != null) {
                BigDecimal syje = zjzh.getSyje();
                yhye = syje == null ? BigDecimal.ZERO : syje;
            }
        }

        // 校验
        YyQfmx firstQfmx = yyQfmxes.get(0);
        BigDecimal ysje = firstQfmx.getYsje();
        BigDecimal znj = firstQfmx.getZnj();
        ysje = ysje == null ? BigDecimal.ZERO : ysje;
        znj = znj == null ? BigDecimal.ZERO : znj;
        if (yhye.compareTo(ysje.add(znj)) > 0) {
            throw new FeesException("剩余预付费大于等于最早一笔欠费", BUSINESS_ERROR);
        }

        BigDecimal yszje = yyQfmxes.stream().map(e -> e.getYsje())
                .filter(e -> e != null)
                .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
        BigDecimal yszwyj = yyQfmxes.stream().map(e -> e.getZnj())
                .filter(e -> e != null)
                .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
        yszje = yszje.add(yszwyj).subtract(yhye);//减去余额

        if (sszje.compareTo(yszje) < 0) {
            throw new FeesException("缴费金额低于欠费金额", BUSINESS_ERROR);
        }

        // 判断余额是否足够后，添加预存
        zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);
        return this.qfsf(yyQfmxes, yhKhjbxx, sflsbh, insert.getDyfs(), fffs, insert.getSfkp(), "0", now);
    }

    //先存后扣方式
    @Override
    @DSTransactional
    public List<String> plsfsave(@NotNull YySspjxxInsert insert) {
        try {
            List<String> qfids = insert.getQfids();
            String fffs = insert.getFffs();
            if (StringUtil.isEmpty(fffs))
                throw new FeesException("付费方式为空", BUSINESS_ERROR);

            String yhbh = insert.getYhbh();
            if (StringUtil.isEmpty(yhbh))
                throw new FeesException("用户编号不能为空", BUSINESS_ERROR);

            YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
            if (StringUtil.isNull(yhKhjbxx)) {
                throw new FeesException("用户不存在", BUSINESS_ERROR);
            }

            long count = yhGroupService.count(
                    Wrappers.<YhGroup>lambdaQuery()
                            .eq(YhGroup::getYhbh, yhbh)
            );
            if (count == 0) {
                throw new FeesException("用户不是群主用户，不能收费", BUSINESS_ERROR);
            }
            BigDecimal sszje = insert.getSszje();
            String sflsbh = GuidGenerator.getSflsbh();

            if (qfids == null || qfids.isEmpty()) {
                throw new FeesException("欠费明细ID为空", BUSINESS_ERROR);
            }
            List<YyQfmx> yyQfmxes = new ArrayList<>();
            //当欠费明细超过1000条时，分批处理
            List<List<String>> lists = Lists.partition(qfids, 1000);
            for (List<String> e : lists) {
                yyQfmxes.addAll(qfmxService.listByIds(e));
            }
            if (yyQfmxes.isEmpty())
                throw new FeesException("欠费明细不存在", BUSINESS_ERROR);
            for (YyQfmx e : yyQfmxes) {
                if ("1".equals(e.getSfbz()))
                    throw new FeesException(String.format("已收费:%s", e.getId()), BUSINESS_ERROR);
                if ("1".equals(e.getChbz()))
                    throw new FeesException(String.format("已冲红:%s", e.getId()), BUSINESS_ERROR);
            }
            yyQfmxes = yyQfmxes.stream()
                    .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                    .collect(Collectors.toList());

            BigDecimal yhye = BigDecimal.ZERO;
            List<YyZjzh> zjzhs = new ArrayList<>();
            if (StringUtil.isNotEmpty(insert.getYesfcyjs()) && insert.getYesfcyjs().equals("1")) {
                zjzhs = zjzhService.lambdaQuery()
                        .in(YyZjzh::getYhbh, yyQfmxes.stream().map(e -> e.getYhbh()).distinct().collect(Collectors.toList()))
                        .list();
                if (!zjzhs.isEmpty()) {
                    yhye = zjzhs.stream().map(e -> e.getSyje()).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                }
            }
            YyQfmx firstQfmx = yyQfmxes.get(0);
            BigDecimal ysje = firstQfmx.getYsje();
            BigDecimal znj = firstQfmx.getZnj();
            ysje = ysje == null ? BigDecimal.ZERO : ysje;
            znj = znj == null ? BigDecimal.ZERO : znj;
            if (yhye.compareTo(ysje.add(znj)) > 0) {
                throw new FeesException("剩余预付费大于等于最早一笔欠费", BUSINESS_ERROR);
            }
            BigDecimal yszje = yyQfmxes.stream().map(e -> e.getYsje())
                    .filter(e -> e != null)
                    .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yszwyj = yyQfmxes.stream().map(e -> e.getZnj())
                    .filter(e -> e != null)
                    .reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            yszje = yszje.add(yszwyj).subtract(yhye);//减去余额
            if (sszje.compareTo(yszje) < 0) {
                throw new FeesException("缴费金额低于欠费金额", BUSINESS_ERROR);
            }
            return this.qfsfpl(yyQfmxes, yhKhjbxx, sflsbh, insert.getDyfs(), fffs, insert.getSfkp(), "1", zjzhs);
        } catch (Exception e) {
            log.error("批量收费失败", e);
            throw new FeesException("批量收费失败", BUSINESS_ERROR);
        }
    }

    /**
     * 是否是群主户关系
     */
    private boolean sfsqzhgx(String yhbh) {
        List<YhGroup> yhGroupList = yhGroupService.list();
        int count = yhGroupList.stream().filter(yhGroup -> yhGroup.getYhbh().equals(yhbh)).collect(Collectors.toList()).size();
        if (count > 0) {
            return true;
        } else {
            List<YhGroupAccounts> yhGroupAccountsList = yhGroupAccountsService.lambdaQuery()
                    .eq(YhGroupAccounts::getYhbh, yhbh)
                    .list();
            if (yhGroupAccountsList.size() > 0) {
                YhGroupAccounts yhGroupAccount = yhGroupAccountsList.get(0);
                String yhGroupyhbh = yhGroupList.stream().filter(item -> item.getId().equals(yhGroupAccount.getGroupId()))
                        .map(YhGroup::getYhbh).findFirst().orElse("");
                if (StringUtil.isNotEmpty(yhGroupyhbh)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * 欠费收费处理
     */
    private List<String> qfsf(List<YyQfmx> yyQfmxes, YhKhjbxx yhKhjbxx,
                              String sflsbh, String dyfs, String fffs, String sfkp, String isplsf, Date now) throws Exception {
        //重新获取预存金额
        YyZjzh zjzh = zjzhService.getById(yhKhjbxx.getYhbh());
        BigDecimal yhye = zjzh.getSyje();

        int sfxh = 2;
        for (YyQfmx qfmx : yyQfmxes) {
            //更新欠费明细
            qfmxService.lambdaUpdate()
                    .set(YyQfmx::getSfrq, now)
                    .set(YyQfmx::getSfbz, "1")
                    .set(YyQfmx::getSflsbh, sflsbh)
                    .eq(YyQfmx::getId, qfmx.getId())
                    .update();

            BigDecimal ysje1 = qfmx.getYsje();
            BigDecimal znj1 = qfmx.getZnj();
            BigDecimal sszje1 = ysje1.add(znj1);
            BigDecimal bckj1 = sszje1;
            BigDecimal bcjz1 = yhye.subtract(sszje1);
            BigDecimal scjz1 = yhye;

            YySspjxx sspjxx = new YySspjxx();
            BeanUtils.copyProperties(qfmx, sspjxx);
            sspjxx.setQfid(qfmx.getId());
            sspjxx.setSfxh(sfxh);//收费序号
            sspjxx.setBckj(bckj1);//本次扣减
            sspjxx.setBcye(bcjz1);//本次余额
            sspjxx.setScye(scjz1);//上次余额
            sspjxx.setSflx(预存抵扣);
            sspjxx.setSszje(BigDecimal.ZERO);
            sspjxx.setFffs(fffs);
            sspjxx.setSflsbh(sflsbh);
            sspjxx.setSfrq(now);
            sspjxx.setSfsjrq(now);
            sspjxx.setSfyf(new SimpleDateFormat("yyyyMM").format(now));
            sspjxx.setChbz(PjztEnum.正常.getValue());
            sspjxx.setSfbz("1");
            sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
            sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
            if (isplsf.equals("1")) {
                sspjxx.setQzhyhbh(yhKhjbxx.getYhbh());
            }
            this.save(sspjxx);

            //扣减资金帐户的金额
            zjzhService.lambdaUpdate()
                    .setSql(String.format("syje = syje-(%s)", bckj1))
                    .setSql(String.format("kjje = kjje+(%s)", bckj1))
                    .eq(YyZjzh::getYhbh, yhKhjbxx.getYhbh())
                    .update();

            //扣减当前收费金额
            yhye = yhye.subtract(sszje1);
            sfxh++;
        }

        boolean islast = false;
        List<String> printpjList = new ArrayList<>();
        List<YySspjxx> list = this.lambdaQuery()
                .eq(YySspjxx::getSflsbh, sflsbh)
                .orderByAsc(YySspjxx::getSfxh)
                .list();

        if (dyfs.equals("4")) {
            String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
            printpjList.add(sspjhb(list, pjh, yhKhjbxx));
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .in(YySspjxx::getId, list.stream().map(YySspjxx::getId).collect(Collectors.toList()))
                    .update();
        } else {
            int ssxh = 1;
            for (YySspjxx sspjxx : list) {
                if (list.size() == ssxh) {
                    islast = true;
                }

                String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
                this.lambdaUpdate()
                        .set(YySspjxx::getFph2, pjh)
                        .eq(YySspjxx::getId, sspjxx.getId())
                        .update();
                if (ssxh == 1) {
                    printpjList.add(yffpj(sspjxx));
                } else {
                    printpjList.add(sspj(sspjxx, islast, yhKhjbxx));
                }
                ssxh++;
            }
        }

        //-------------------------------------EI数电发票数据添加---------------------
        this.dzfpcl(list, yhKhjbxx, now, sflsbh, sfkp, isplsf);
        return printpjList;
    }


    /**
     * 欠费收费批量处理
     */
    private List<String> qfsfpl(List<YyQfmx> yyQfmxes, YhKhjbxx yhKhjbxx,
                                String sflsbh, String dyfs, String fffs, String sfkp, String isplsf, List<YyZjzh> oldzjzhs) throws Exception {
        //分离出用户
        List<String> yhbhs = yyQfmxes.stream().map(YyQfmx::getYhbh).distinct().collect(Collectors.toList());
        Date now = new Date();
        for (String yhbh : yhbhs) {
            //获取当前用户的欠费明细
            List<YyQfmx> yhqfList = yyQfmxes.stream()
                    .filter(e -> e.getYhbh().equals(yhbh))
                    .sorted(Comparator.comparing(YyQfmx::getCbrq).thenComparing(YyQfmx::getCbkid))
                    .collect(Collectors.toList());
            //获取当前用户的欠费金额（应收金额+违约金）
            BigDecimal sszje = yhqfList.stream().map(YyQfmx::getYsje).reduce(BigDecimal.ZERO, BigDecimal::add)
                    .add(yhqfList.stream().map(YyQfmx::getZnj).reduce(BigDecimal.ZERO, BigDecimal::add));
            YyZjzh zjzh = oldzjzhs.stream().filter(e -> e.getYhbh().equals(yhbh)).findFirst().orElse(null);
            if (StringUtil.isNotNull(zjzh)) {
                sszje = sszje.subtract(zjzh.getSyje());
            }
            YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
            zjzhUpdate.setYhbh(yhbh);
            zjzhUpdate.setJe(sszje);
            zjzhUpdate.setSfrq(now);
            //判断余额是否足够后，添加预存
            zjzhService.xgyck(zjzhUpdate, true, 1, fffs, sflsbh);
            //重新获取预存金额
            zjzh = zjzhService.getById(yhbh);
            BigDecimal yhye = zjzh.getSyje();
            int sfxh = 2;
            for (YyQfmx qfmx : yhqfList) {
                //更新欠费明细
                qfmxService.lambdaUpdate()
                        .set(YyQfmx::getSfrq, now)
                        .set(YyQfmx::getSfbz, "1")
                        .set(YyQfmx::getSflsbh, sflsbh)
                        .eq(YyQfmx::getId, qfmx.getId())
                        .update();
                BigDecimal ysje1 = qfmx.getYsje();
                BigDecimal znj1 = qfmx.getZnj();
                BigDecimal sszje1 = ysje1.add(znj1);
                BigDecimal bckj1 = sszje1;
                BigDecimal bcjz1 = yhye.subtract(sszje1);
                BigDecimal scjz1 = yhye;
                YySspjxx sspjxx = new YySspjxx();
                BeanUtils.copyProperties(qfmx, sspjxx);
                sspjxx.setQfid(qfmx.getId());
                sspjxx.setSfxh(sfxh);//收费序号
                sspjxx.setBckj(bckj1);//本次扣减
                sspjxx.setBcye(bcjz1);//本次余额
                sspjxx.setScye(scjz1);//上次余额
                sspjxx.setSflx(预存抵扣);
                sspjxx.setSszje(BigDecimal.ZERO);
                sspjxx.setFffs(fffs);
                sspjxx.setSflsbh(sflsbh);
                sspjxx.setSfrq(now);
                sspjxx.setSfsjrq(now);
                sspjxx.setSfyf(new SimpleDateFormat("yyyyMM").format(now));
                sspjxx.setChbz(PjztEnum.正常.getValue());
                sspjxx.setSfbz("1");
                sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
                sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());
                if (isplsf.equals("1")) {
                    sspjxx.setQzhyhbh(yhKhjbxx.getYhbh());
                }
                this.save(sspjxx);

                //扣减资金帐户的金额
                zjzhService.lambdaUpdate()
                        .setSql(String.format("syje = syje-(%s)", bckj1))
                        .setSql(String.format("kjje = kjje+(%s)", bckj1))
                        .eq(YyZjzh::getYhbh, yhbh)
                        .update();

                //扣减当前收费金额
                yhye = yhye.subtract(sszje1);
                sfxh++;

            }
        }
        //处理预存记录没有保存群主户户号
        this.lambdaUpdate()
                .set(YySspjxx::getQzhyhbh, yhKhjbxx.getYhbh())
                .eq(YySspjxx::getSflsbh, sflsbh)
                .eq(YySspjxx::getSflx, 预付费收取)
                .update();

        boolean islast = false;
        List<String> printpjList = new ArrayList<>();
        List<YySspjxx> list = this.lambdaQuery()
                .eq(YySspjxx::getSflsbh, sflsbh)
                .orderByAsc(YySspjxx::getSfxh)
                .list();
        if (dyfs.equals("4")) {
            String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
            printpjList.add(sspjhb(list, pjh, yhKhjbxx));
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .in(YySspjxx::getId, list.stream().map(YySspjxx::getId).collect(Collectors.toList()))
                    .update();
        } else {
            int ssxh = 1;
            for (YySspjxx sspjxx : list) {
                if (list.size() == ssxh) {
                    islast = true;
                }
                String pjh = yyPjbhService.getPjh(SecurityUtils.getUserId().toString());
                this.lambdaUpdate()
                        .set(YySspjxx::getFph2, pjh)
                        .eq(YySspjxx::getId, sspjxx.getId())
                        .update();
                if (ssxh == 1) {
                    printpjList.add(yffpj(sspjxx));
                } else {
                    printpjList.add(sspj(sspjxx, islast, yhKhjbxx));
                }
                ssxh++;
            }
        }
        //-------------------------------------EI数电发票数据添加---------------------
        this.dzfpcl(list, yhKhjbxx, now, sflsbh, sfkp, isplsf);
        return printpjList;
    }

    /**
     * 电子发票处理
     *
     * @param list     实收集合
     * @param yhKhjbxx 用户信息
     * @param now      收费日期
     * @param sflsbh   收费流水编号
     * @param sfkp     是否开具发票
     * @param isplsf   是否批量收费
     */
    private void dzfpcl(List<YySspjxx> list, YhKhjbxx yhKhjbxx, Date now,
                        String sflsbh, String sfkp, String isplsf) {
        List<YyQfmx> yyQfmxes = qfmxService.lambdaQuery()
                .eq(YyQfmx::getSflsbh, sflsbh)
                .eq(YyQfmx::getEiYkfpBz, "0")
                .list();
        if (yyQfmxes.size() > 0) {
            if (isplsf.equals("1")) {
                invoiceService.addInvoiceData(yyQfmxes, list, yhKhjbxx, "2", sfkp);
            } else {
                invoiceService.addInvoiceData(yyQfmxes, list, yhKhjbxx, "0", sfkp);
            }
        }
        List<YyQfmx> yjfpYyqfmxes = qfmxService.lambdaQuery()
                .eq(YyQfmx::getSflsbh, sflsbh)
                .eq(YyQfmx::getEiYkfpBz, "1")
                .list();
        //判断是否存在预开发票，有则回写电子发票收费日期
        if (yjfpYyqfmxes.size() > 0) {
            eiFpkjRequestService.lambdaUpdate()
                    .set(EiFpkjRequest::getSfrq, now)
                    .inSql(EiFpkjRequest::getSfid, String.format("select fpglh from yy_qfmx where sflsbh='%s'", sflsbh))
                    .update();
            List<String> fpglhs = yjfpYyqfmxes.stream().map(YyQfmx::getFpglh).distinct().collect(Collectors.toList());
            for (String fpglh : fpglhs) {
                List<YyQfmx> yyQfmxList = yjfpYyqfmxes.stream().filter(e -> e.getFpglh().equals(fpglh)).collect(Collectors.toList());
                BigDecimal ysje = yyQfmxList.stream().map(YyQfmx::getYsje).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal znj = yyQfmxList.stream().map(YyQfmx::getZnj).reduce(BigDecimal.ZERO, BigDecimal::add);
                eiYkfpLogService.lambdaUpdate()
                        .set(EiYkfpLog::getXzsj, now)
                        .set(EiYkfpLog::getXzrybm, SecurityUtils.getUserId())
                        .set(EiYkfpLog::getXzryxm, SecurityUtils.getUser().getRealName())
                        .set(EiYkfpLog::getXzje, ysje.add(znj))
                        .set(EiYkfpLog::getSflx, 预存抵扣.getDesc())
                        .in(EiYkfpLog::getFpglh, fpglh)
                        .update();
            }
        }
    }

    @Override
    public List<String> yctf(YySspjxxyctj yySspjxxyctj) {
        if (StringUtil.isEmpty(yySspjxxyctj.getYhbh())) {
            throw new FeesException("用户编号不能为空", BUSINESS_ERROR);
        }
        if (yySspjxxyctj.getTfje().compareTo(BigDecimal.ZERO) <= 0) {
            throw new FeesException("退费金额必须大于0", BUSINESS_ERROR);
        }
        YyZjzh yyZjzh = zjzhService.getById(yySspjxxyctj.getYhbh());
        if (yyZjzh == null) {
            throw new FeesException("用户不存在", BUSINESS_ERROR);
        }
        if (yyZjzh.getSyje().compareTo(yySspjxxyctj.getTfje()) < 0) {
            throw new FeesException("用户余额不足", BUSINESS_ERROR);
        }
        String sflsbh = GuidGenerator.getSflsbh();
        YyZjzhUpdate zjzhUpdate = new YyZjzhUpdate();
        zjzhUpdate.setYhbh(yySspjxxyctj.getYhbh());
        zjzhUpdate.setJe(yySspjxxyctj.getTfje().multiply(BigDecimal.valueOf(-1)));
        zjzhUpdate.setBz("预存退费");
        zjzhUpdate.setSfrq(new Date());
        List<String> printpjList = new ArrayList<>();
        if (zjzhService.xgyck(zjzhUpdate, true, 1, yySspjxxyctj.getFffs(), sflsbh)) {
            printpjList.add(yffpj(sflsbh, 预存退费.getValue().toString(), ""));
        }
        return printpjList;
    }


    public String printPj(String ssid, String dyfsl) {
        try {
            if (StringUtil.isEmpty(ssid)) {
                throw new FeesException("参数实收ID或收费流水编号不能为空！", BUSINESS_ERROR);
            }
            if (StringUtil.isEmpty(dyfsl)) {
                throw new FeesException("参数打印方式不能为空！", BUSINESS_ERROR);
            }
            if (dyfsl.equals("4")) {
                List<YySspjxx> yySspjxxs = this.lambdaQuery()
                        .eq(YySspjxx::getSflsbh, ssid)
                        .list();
                if (yySspjxxs.size() == 0) {
                    throw new FeesException("实收记录不存在", BUSINESS_ERROR);
                }

                String yhbh = yySspjxxs.get(0).getQzhyhbh();
                if (StringUtil.isEmpty(yhbh)) {
                    yhbh = yySspjxxs.get(0).getYhbh();
                }
                YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
                long count = yySspjxxs.stream().filter(e ->
                                "6".equals(e.getCbjsbz()) &&
                                        e.getYsqt().compareTo(BigDecimal.ZERO) > 0)
                        .count();
                if (count > 0) {
                    return qfsfpj(yySspjxxs, yySspjxxs.get(0).getFph2(), yhKhjbxx);
                }
                return sspjhb(yySspjxxs, yySspjxxs.get(0).getFph2(), yhKhjbxx);
            } else {
                YySspjxx yySspjxx = this.getById(ssid);
                if (yySspjxx == null) {
                    throw new FeesException("实收记录不存在", BUSINESS_ERROR);
                }

                if (yySspjxx.getSflx().equals(预付费收取) || yySspjxx.getSflx().equals(余额转存)) {
                    return yffpj(yySspjxx);
                } else {
                    YhKhjbxx yhKhjbxx = khjbxxService.getById(yySspjxx.getYhbh());
                    if ("6".equals(yySspjxx.getCbjsbz()) && yySspjxx.getYsqt().compareTo(BigDecimal.ZERO) > 0) {

                    }
                    return sspj(yySspjxx, false, yhKhjbxx);
                }
            }
        } catch (Exception e) {
            log.error("票据打印失败 ====================> ", e);
            throw new FeesException(e.getMessage(), BUSINESS_ERROR);
        }
    }

    //先扣后存的票据打印
    private String sspj(YySspjxx sspjxx, boolean islast, YhKhjbxx yhKhjbxx) throws Exception {
        String ssid = sspjxx.getId();
//        String ssmxsql = String.format("with sssf as\n" +
//                " (select 1 xh,'阶梯1' as mc,sjbm,b.name sjmc,jt1sj sj,jt1sl sl,jt1sf sf\n" +
//                "    from yy_sspjxx a\n" +
//                "    left join bm_sj b\n" +
//                "      on a.sjbm = b.code\n" +
//                "   where id = '%s'\n" +
//                "     and sflx <> 3\n" +
//                "     and b.jtbz = 1\n" +
//                "  union\n" +
//                "  select 2 xh, '阶梯2', sjbm, b.name sjmc, jt2sj, jt2sl, jt2sf\n" +
//                "    from yy_sspjxx a\n" +
//                "    left join bm_sj b\n" +
//                "      on a.sjbm = b.code\n" +
//                "   where id = '%s'\n" +
//                "     and sflx <> 3\n" +
//                "     and b.jtbz = 1\n" +
//                "  union\n" +
//                "  select 3 xh, '阶梯3', sjbm, b.name sjmc, jt3sj, jt3sl, jt3sf\n" +
//                "    from yy_sspjxx a\n" +
//                "    left join bm_sj b\n" +
//                "      on a.sjbm = b.code\n" +
//                "   where id = '%s'\n" +
//                "     and sflx <> 3\n" +
//                "     and b.jtbz = 1\n" +
//                "  union\n" +
//                "  select 4 xh, '非居', a.sjbm, b.name sjmc, a.sj, a.sl, a.sf\n" +
//                "    from yy_sspjxx a\n" +
//                "    left join bm_sj b\n" +
//                "      on a.sjbm = b.code\n" +
//                "   where id = '%s'\n" +
//                "     and sflx <> 3\n" +
//                "     and nvl(b.jtbz, 0) = 0)\n" +
//                "select a.*\n" +
//                "  from sssf a\n" +
//                "  left join bm_sj b\n" +
//                "    on a.sjbm = b.code\n" +
//                " where nvl(a.sf, 0) > 0\n", ssid, ssid, ssid, ssid);
//
//        String qtfysql = String.format("select 5, '污水费' mc, wsfdj sj, yswsf sf, yssl sl\n" +
//                "  from yy_sspjxx\n" +
//                " where id = '%s'\n" +
//                "   and nvl(yswsf, 0) > 0\n" +
//                "union\n" +
//                "select 6, '水资源税', szyf_dj sj, ysszyf sf, yssl sl\n" +
//                "  from yy_sspjxx\n" +
//                " where id = '%s'\n" +
//                "   and nvl(ysszyf, 0) > 0\n" +
//                "union\n" +
//                "select 7, '垃圾费', ljfdj sj, ysljf sf, yssl sl\n" +
//                "  from yy_sspjxx\n" +
//                " where id = '%s'\n" +
//                "   and nvl(ysljf, 0) > 0\n" +
//                "union\n" +
//                "select 8, '违约金', 0, znj sf, 0 sl\n" +
//                "  from yy_sspjxx\n" +
//                " where id = '%s'\n" +
//                "   and nvl(znj, 0) > 0\n", ssid, ssid, ssid, ssid);
//        List<HashMap<String, Object>> sflist = DbHelper.getDbHelper().getList(ssmxsql);
//        StringBuilder str = new StringBuilder();
//        sflist.forEach(e -> {
//            str.append("<tr>");
//            str.append(String.format("<td>%s</td>", e.get("mc")));
//            str.append(String.format("<td>%s</td>", ""));
//            str.append(String.format("<td>%s</td>", ""));
//            str.append(String.format("<td>%s</td>", e.get("sl")));
//            str.append(String.format("<td>%s</td>", e.get("sj")));
//            str.append(String.format("<td>%s</td>", e.get("sf")));
//            str.append("</tr>");
//        });
//        List<HashMap<String, Object>> qtlist = DbHelper.getDbHelper().getList(qtfysql);
//        qtlist.forEach(e -> {
//            if (!e.get("mc").equals("垃圾费") && !e.get("mc").equals("违约金")) {
//                str.append("<tr>");
//                str.append(String.format("<td>%s</td>", e.get("mc")));
//                str.append(String.format("<td>%s</td>", ""));
//                str.append(String.format("<td>%s</td>", ""));
//                str.append(String.format("<td>%s</td>", e.get("sl")));
//                str.append(String.format("<td>%s</td>", e.get("sj")));
//                str.append(String.format("<td>%s</td>", e.get("sf")));
//                str.append("</tr>");
//            }
//        });
        StringBuilder str = new StringBuilder();
        BigDecimal yssl = sspjxx.getYssl();
        BigDecimal yswsf = sspjxx.getYswsf();
        BigDecimal ysszyf = sspjxx.getYsszyf();
//水费+二次加压分+附加费+消防栓费
        if (sspjxx.getYssf().compareTo(BigDecimal.ZERO) > 0 ||
                sspjxx.getYsecjyf().compareTo(BigDecimal.ZERO) > 0 ||
                sspjxx.getYsfjf().compareTo(BigDecimal.ZERO) > 0 ||
                sspjxx.getYsqt().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal sfhjje = sspjxx.getYssf().add(sspjxx.getYsecjyf()).add(sspjxx.getYsfjf()).add(sspjxx.getYsqt());
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "水费"));
            str.append(String.format("<td>%s</td>", sspjxx.getScds()));
            str.append(String.format("<td>%s</td>", sspjxx.getBcds()));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", sfhjje.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", sfhjje));
            str.append("</tr>");
        }
        //污水费
        if (yswsf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "污水处理费"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", yswsf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", yswsf));
            str.append("</tr>");
        }
        //水资源税
        if (ysszyf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "水资源税"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", ysszyf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", ysszyf));
            str.append("</tr>");
        }
        BigDecimal ycje = BigDecimal.ZERO;
        if (islast) {
            String ycjesql = String.format("select sum(NVL(sszje,0)) from yy_sspjxx " +
                            "where sflsbh='%s' and sflx=3  group by sflsbh"
                    , sspjxx.getSflsbh());
            String ycjestr = DbHelper.getDbHelper().getValue(ycjesql);
            if (StringUtil.isNotEmpty(ycjestr)) {
                ycje = BigDecimal.valueOf(Double.parseDouble(ycjestr));
            }
        }
        if ("9".equals(sspjxx.getFylx())) {
            ycje = sspjxx.getBcyc();
        }
        String pjh = sspjxx.getFph2();
        //判断票据是否存在，不存在更具收费人员获取票据号
        if (StringUtil.isEmpty(pjh)) {
            pjh = yyPjbhService.getPjh(sspjxx.getSfrybm());
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .eq(YySspjxx::getId, ssid)
                    .update();
        }
        //String htmlstr = DbHelper.getDbHelper().getValue(String.format("select printtemplate from print_template where id=%s", PjlxEnum.实收票据信息.getValue()));
        String htmlstr = getHtmlContent("templates/sspjxx.html");
        htmlstr = htmlstr.replace("{{title}}", "莱阳市自来水有限公司水费专用收据");
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{yhbh}}", sspjxx.getYhbh());
        htmlstr = htmlstr.replace("{{yhxm}}", sspjxx.getYhxm());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());
        htmlstr = htmlstr.replace("{{cwrq}}", sspjxx.getCwrq());
        htmlstr = htmlstr.replace("{{sfrq}}", sspjxx.getSfrq().toString());
        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());
        htmlstr = htmlstr.replace("{{scds}}", sspjxx.getScds().toString());
        htmlstr = htmlstr.replace("{{bcds}}", sspjxx.getBcds().toString());
        htmlstr = htmlstr.replace("{{sl}}", sspjxx.getSl().toString());
        htmlstr = htmlstr.replace("{{ljclf}}", sspjxx.getLjf().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{wyj}}", sspjxx.getZnj().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{content}}", str.toString());
        htmlstr = htmlstr.replace("{{ysje}}", sspjxx.getYsje().add(sspjxx.getZnj()).setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssje}}", sspjxx.getSszje().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sspjxx.getSszje()));
        htmlstr = htmlstr.replace("{{scjy}}", sspjxx.getScye().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcjy}}", ycje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sszje}}", sspjxx.getSszje().add(ycje).setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(sspjxx.getSfryxm()) ? "" : sspjxx.getSfryxm());
        htmlstr = htmlstr.replace("{{dysj}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        htmlstr = htmlstr.replace("{{fwzmc}}", "营业大厅");
        String cbrydh = "暂无";
        String cbrybm = sspjxx.getCbrybm();
        if (NumberUtil.isNumber(cbrybm)) {
            User user = userService.get(Long.valueOf(cbrybm));
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
        }
        htmlstr = htmlstr.replace("{{cbrydh}}", cbrydh);
        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate()
                .setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getId, sspjxx.getId())
                .update();
        return htmlstr;
    }

    //先扣后存的票据打印
    private String sspjhb(List<YySspjxx> yySspjxxs, String pjh, YhKhjbxx yhKhjbxx) throws Exception {
        StringBuilder str = new StringBuilder();
        BigDecimal yssl = yySspjxxs.stream().map(YySspjxx::getYssl).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yssf = yySspjxxs.stream().map(YySspjxx::getYssf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yswsf = yySspjxxs.stream().map(YySspjxx::getYswsf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysszyf = yySspjxxs.stream().map(YySspjxx::getYsszyf).reduce(BigDecimal.ZERO, BigDecimal::add);
        //BigDecimal yswyj = yySspjxxs.stream().map(YySspjxx::getZnj).reduce(BigDecimal.ZERO, BigDecimal::add);
        //BigDecimal ysljf = yySspjxxs.stream().map(YySspjxx::getYsljf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysje = yySspjxxs.stream().map(YySspjxx::getYsje).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal sszje = yySspjxxs.stream().map(YySspjxx::getSszje).reduce(BigDecimal.ZERO, BigDecimal::add);
        //二次加压费
        BigDecimal ysecjyf = yySspjxxs.stream().map(o -> checkNumber(o.getYsecjyf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        //附加费
        BigDecimal ysfjf = yySspjxxs.stream().map(o -> checkNumber(o.getYsfjf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        //消防费（其他费）
        BigDecimal ysqtf = yySspjxxs.stream().map(o -> checkNumber(o.getYsqt())).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal scye = yySspjxxs.get(0).getScye();
        BigDecimal ycje = BigDecimal.ZERO;
        String ycjesql = String.format("select sum(NVL(sszje,0)) from yy_sspjxx " +
                        "where sflsbh='%s' and sflx=3  group by sflsbh"
                , yySspjxxs.get(0).getSflsbh());
        String ycjestr = DbHelper.getDbHelper().getValue(ycjesql);
        if (StringUtil.isNotEmpty(ycjestr)) {
            ycje = BigDecimal.valueOf(Double.parseDouble(ycjestr));
        }

        String cbrybm = yySspjxxs.get(0).getCbrybm();
        String sfryxm = yySspjxxs.get(0).getSfryxm();

        //水费+二次加压分+附加费+消防栓费
        if (yssf.compareTo(BigDecimal.ZERO) > 0 ||
                ysecjyf.compareTo(BigDecimal.ZERO) > 0 ||
                ysfjf.compareTo(BigDecimal.ZERO) > 0 ||
                ysqtf.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal sfhjje = yssf.add(ysecjyf).add(ysfjf).add(ysqtf);
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "水费"));
            if ("1".equals(yhKhjbxx.getZhbz().toString())) {
                str.append(String.format("<td>%s</td>", ""));
                str.append(String.format("<td>%s</td>", ""));
            } else {
                str.append(String.format("<td>%s</td>", yySspjxxs.get(0).getScds().toString()));
                if (ycje.compareTo(BigDecimal.ZERO) > 0) {
                    str.append(String.format("<td>%s</td>", yySspjxxs.get(yySspjxxs.size() - 2).getBcds().toString()));
                } else {
                    str.append(String.format("<td>%s</td>", yySspjxxs.get(yySspjxxs.size() - 1).getBcds().toString()));
                }
            }
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", sfhjje.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", sfhjje));
            str.append("</tr>");
        }
        //污水费
        if (yswsf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "污水处理费"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", yswsf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", yswsf));
            str.append("</tr>");
        }
        //水资源税
        if (ysszyf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "水资源税"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", ysszyf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", ysszyf));
            str.append("</tr>");
        }

        String htmlstr = getHtmlContent("templates/sspjxx.html");
        BmGs bmGs = bmGsService.getById(yhKhjbxx.getSsgs());
        htmlstr = htmlstr.replace("{{title}}", String.format("%s水费专用收据", bmGs.getMc()));
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{yhxm}}", yhKhjbxx.getYhxm());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());
        if (yySspjxxs.size() > 1) {
            if (ycje.compareTo(BigDecimal.ZERO) > 0) {
                htmlstr = htmlstr.replace("{{cwrq}}", yySspjxxs.get(0).getCwrq() + "-"
                        + yySspjxxs.get(yySspjxxs.size() - 2).getCwrq());
            } else {
                htmlstr = htmlstr.replace("{{cwrq}}", yySspjxxs.get(0).getCwrq() + "-"
                        + yySspjxxs.get(yySspjxxs.size() - 1).getCwrq());
            }
        } else {
            htmlstr = htmlstr.replace("{{cwrq}}", yySspjxxs.get(0).getCwrq());
        }
        htmlstr = htmlstr.replace("{{sfrq}}", yySspjxxs.get(0).getSfrq().toString());
        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());

        if ("1".equals(yhKhjbxx.getZhbz().toString())) {
            htmlstr = htmlstr.replace("{{yhbh}}", yhKhjbxx.getYhbh() + "（主户）");
//            htmlstr = htmlstr.replace("{{scds}}", "");
//            htmlstr = htmlstr.replace("{{bcds}}", "");
        } else {
            htmlstr = htmlstr.replace("{{yhbh}}", yhKhjbxx.getYhbh());
//            htmlstr = htmlstr.replace("{{scds}}", yySspjxxs.get(0).getScds().toString());
//            htmlstr = htmlstr.replace("{{bcds}}", yySspjxxs.get(yySspjxxs.size() - 1).getBcds().toString());
        }
        htmlstr = htmlstr.replace("{{sl}}", yssl.setScale(2, RoundingMode.HALF_UP).toString());
        //htmlstr = htmlstr.replace("{{ljclf}}", ysljf.setScale(2, RoundingMode.HALF_UP).toString());
        //htmlstr = htmlstr.replace("{{wyj}}", yswyj.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{content}}", str.toString());
        htmlstr = htmlstr.replace("{{ysje}}", ysje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssje}}", ysje.add(ycje).setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{scjy}}", scye.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcjy}}", ycje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sszje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sszje));
        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(sfryxm) ? "" : sfryxm);
        htmlstr = htmlstr.replace("{{dysj}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        htmlstr = htmlstr.replace("{{fwzmc}}", "营业大厅");
        String cbrydh = "暂无";
        if (NumberUtil.isNumber(cbrybm)) {
            User user = userService.get(Long.valueOf(cbrybm));
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
        }
        htmlstr = htmlstr.replace("{{cbrydh}}", cbrydh);
        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate()
                .setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getSflsbh, yySspjxxs.get(0).getSflsbh())
                .update();
        return htmlstr;
    }

    //先存后扣的票据打印
    private String sspj1(YySspjxx sspjxx, boolean islast, YhKhjbxx yhKhjbxx) throws Exception {
        String ssid = sspjxx.getId();
        String ssmxsql = String.format("with sssf as\n" +
                " (select 1 xh,'阶梯1' as mc,sjbm,b.name sjmc,jt1sj sj,jt1sl sl,jt1sf sf\n" +
                "    from yy_sspjxx a\n" +
                "    left join bm_sj b\n" +
                "      on a.sjbm = b.code\n" +
                "   where id = '%s'\n" +
                "     and sflx <> 3\n" +
                "     and b.jtbz = 1\n" +
                "  union\n" +
                "  select 2 xh, '阶梯2', sjbm, b.name sjmc, jt2sj, jt2sl, jt2sf\n" +
                "    from yy_sspjxx a\n" +
                "    left join bm_sj b\n" +
                "      on a.sjbm = b.code\n" +
                "   where id = '%s'\n" +
                "     and sflx <> 3\n" +
                "     and b.jtbz = 1\n" +
                "  union\n" +
                "  select 3 xh, '阶梯3', sjbm, b.name sjmc, jt3sj, jt3sl, jt3sf\n" +
                "    from yy_sspjxx a\n" +
                "    left join bm_sj b\n" +
                "      on a.sjbm = b.code\n" +
                "   where id = '%s'\n" +
                "     and sflx <> 3\n" +
                "     and b.jtbz = 1\n" +
                "  union\n" +
                "  select 4 xh, '非居', a.sjbm, b.name sjmc, a.sj, a.sl, a.sf\n" +
                "    from yy_sspjxx a\n" +
                "    left join bm_sj b\n" +
                "      on a.sjbm = b.code\n" +
                "   where id = '%s'\n" +
                "     and sflx <> 3\n" +
                "     and nvl(b.jtbz, 0) = 0)\n" +
                "select a.*\n" +
                "  from sssf a\n" +
                "  left join bm_sj b\n" +
                "    on a.sjbm = b.code\n" +
                " where nvl(a.sf, 0) > 0\n", ssid, ssid, ssid, ssid);

        String qtfysql = String.format("select 5, '污水费' mc, wsfdj sj, yswsf sf, yssl sl\n" +
                "  from yy_sspjxx\n" +
                " where id = '%s'\n" +
                "   and nvl(yswsf, 0) > 0\n" +
                "union\n" +
                "select 6, '水资源税', szyf_dj sj, ysszyf sf, yssl sl\n" +
                "  from yy_sspjxx\n" +
                " where id = '%s'\n" +
                "   and nvl(ysszyf, 0) > 0\n" +
                "union\n" +
                "select 7, '垃圾费', ljfdj sj, ysljf sf, yssl sl\n" +
                "  from yy_sspjxx\n" +
                " where id = '%s'\n" +
                "   and nvl(ysljf, 0) > 0\n" +
                "union\n" +
                "select 8, '违约金', 0, znj sf, 0 sl\n" +
                "  from yy_sspjxx\n" +
                " where id = '%s'\n" +
                "   and nvl(znj, 0) > 0\n", ssid, ssid, ssid, ssid);

        List<HashMap<String, Object>> sflist = DbHelper.getDbHelper().getList(ssmxsql);
        StringBuilder str = new StringBuilder();
        sflist.forEach(e -> {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", e.get("mc")));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", e.get("sl")));
            str.append(String.format("<td>%s</td>", e.get("sj")));
            str.append(String.format("<td>%s</td>", e.get("sf")));
            str.append("</tr>");
        });

        List<HashMap<String, Object>> qtlist = DbHelper.getDbHelper().getList(qtfysql);
        qtlist.forEach(e -> {
            if (!e.get("mc").equals("垃圾费") && !e.get("mc").equals("违约金")) {
                str.append("<tr>");
                str.append(String.format("<td>%s</td>", e.get("mc")));
                str.append(String.format("<td>%s</td>", ""));
                str.append(String.format("<td>%s</td>", ""));
                str.append(String.format("<td>%s</td>", e.get("sl")));
                str.append(String.format("<td>%s</td>", e.get("sj")));
                str.append(String.format("<td>%s</td>", e.get("sf")));
                str.append("</tr>");
            }
        });
        BigDecimal ycje = sspjxx.getBcye();
        String pjh = sspjxx.getFph2();
        //判断票据是否存在，不存在根据收费人员获取票据号
        if (StringUtil.isEmpty(pjh)) {
            pjh = yyPjbhService.getPjh(sspjxx.getSfrybm());
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .eq(YySspjxx::getId, ssid)
                    .update();
        }
        //String htmlstr = DbHelper.getDbHelper().getValue(String.format("select printtemplate from print_template where id=%s", PjlxEnum.实收票据信息.getValue()));
        String htmlstr = getHtmlContent("templates/sspjxx.html");
        BmGs bmGs = bmGsService.getById(yhKhjbxx.getSsgs());
        htmlstr = htmlstr.replace("{{title}}", String.format("%s水费专用收据", bmGs.getMc()));
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{yhbh}}", sspjxx.getYhbh());
        htmlstr = htmlstr.replace("{{yhxm}}", sspjxx.getYhxm());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());
//        htmlstr = htmlstr.replace("{{cwrq}}", sspjxx.getYsyf());
        htmlstr = htmlstr.replace("{{sfrq}}", sspjxx.getSfrq().toString());
        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());
        htmlstr = htmlstr.replace("{{scds}}", sspjxx.getScds().toString());
        htmlstr = htmlstr.replace("{{bcds}}", sspjxx.getBcds().toString());
        htmlstr = htmlstr.replace("{{sl}}", sspjxx.getSl().toString());
//        htmlstr = htmlstr.replace("{{ljclf}}", sspjxx.getLjf().setScale(2, RoundingMode.HALF_UP).toString());
//        htmlstr = htmlstr.replace("{{wyj}}", sspjxx.getZnj().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{content}}", str.toString());

        htmlstr = htmlstr.replace("{{ysje}}", sspjxx.getYsje().add(sspjxx.getZnj()).setScale(2, RoundingMode.HALF_UP).toString());
        BigDecimal sszje = sspjxx.getSszje();
        htmlstr = htmlstr.replace("{{ssje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());

        // 实收金额转换大写：金额中会有负数情况,单独判断
        if (sszje.compareTo(BigDecimal.ZERO) < 0) {
            htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sszje.abs()));
        } else {
            htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sszje));
        }

        htmlstr = htmlstr.replace("{{scjy}}", sspjxx.getScye().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcjy}}", ycje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sszje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(sspjxx.getSfryxm()) ? "" : sspjxx.getSfryxm());
        htmlstr = htmlstr.replace("{{dysj}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        htmlstr = htmlstr.replace("{{fwzmc}}", "营业大厅");
//        User user = userService.get(Long.valueOf(sspjxx.getCbrybm()));
//        //String cbrydh = DbHelper.getDbHelper().getValue(String.format("select olxdh from  sys_operators where ocode = (select cby from bm_cbb where cbbbm='%s')", sspjxx.getSscbb()));
//        String cbrydh = "暂无";
//        if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
//            cbrydh = user.getPhone();
//        }
//        htmlstr = htmlstr.replace("{{cbrydh}}", cbrydh);
        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate()
                .setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getId, sspjxx.getId())
                .update();
        return htmlstr;
    }

    //先存后扣的票据打印
    private String sspjhb1(List<YySspjxx> yySspjxxs, String pjh, YhKhjbxx yhKhjbxx) {
        if (CollectionUtil.isEmpty(yySspjxxs)) {
            throw new FeesException("未找到收费信息!", BUSINESS_ERROR);
        }

        YySspjxx yySspjxx = yySspjxxs.get(0);

        StringBuilder str = new StringBuilder();

        BigDecimal yssl = yySspjxxs.stream().map(o -> checkNumber(o.getYssl())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yssf = yySspjxxs.stream().map(o -> checkNumber(o.getYssf())).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 二次加压+附加+消防栓 与水费合并打印
        BigDecimal ysecjyf = yySspjxxs.stream().map(o -> checkNumber(o.getYsecjyf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysfjf = yySspjxxs.stream().map(o -> checkNumber(o.getYsfjf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysqtf = yySspjxxs.stream().map(o -> checkNumber(o.getYsqt())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yswsf = yySspjxxs.stream().map(o -> checkNumber(o.getYswsf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysljf = yySspjxxs.stream().map(o -> checkNumber(o.getYsljf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysszyf = yySspjxxs.stream().map(o -> checkNumber(o.getYsszyf())).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yswyj = yySspjxxs.stream().map(o -> checkNumber(o.getZnj())).reduce(BigDecimal.ZERO, BigDecimal::add);

//        BigDecimal ysje = yySspjxxs.stream().map(o -> checkNumber(o.getBckj())).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 应收金额=水费(基本水费+二次加压+附加+消防栓费)+污水+水资源
        BigDecimal ysje = yssf.add(ysecjyf).add(ysfjf).add(ysqtf).add(yswsf).add(ysszyf);
        BigDecimal sszje = yySspjxxs.stream().map(o -> checkNumber(o.getSszje())).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal scye = yySspjxx.getScye();
        BigDecimal ycje = yySspjxxs.get(yySspjxxs.size() - 1).getBcye();

        String cbrybm = yySspjxx.getCbrybm();
        String sfrybm = yySspjxx.getSfrybm();
        String sfryxm = yySspjxx.getSfryxm();
        //水费 [莱阳票据打印 水费= 基本水费+二次加压费+附加费+消防栓费]
        if (yssf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "基本水费"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", yssf.divide(yssl, 2, RoundingMode.HALF_UP)));

            if (ysecjyf.compareTo(BigDecimal.ZERO) > 0 || ysfjf.compareTo(BigDecimal.ZERO) > 0 || ysqtf.compareTo(BigDecimal.ZERO) > 0) {
                yssf = yssf.add(ysecjyf).add(ysfjf).add(ysqtf);
            }
            str.append(String.format("<td>%s</td>", yssf));
            str.append("</tr>");
        }
        //污水费
        if (yswsf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "污水处理费"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", yswsf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", yswsf));
            str.append("</tr>");
        }
        //水资源税
        if (ysszyf.compareTo(BigDecimal.ZERO) > 0) {
            str.append("<tr>");
            str.append(String.format("<td>%s</td>", "水资源税"));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", ""));
            str.append(String.format("<td>%s</td>", yssl));
            str.append(String.format("<td>%s</td>", ysszyf.divide(yssl, 2, RoundingMode.HALF_UP)));
            str.append(String.format("<td>%s</td>", ysszyf));
            str.append("</tr>");
        }

        String htmlstr = getHtmlContent("templates/sspjxx.html");
        BmGs bmGs = bmGsService.getById(yhKhjbxx.getSsgs());
        htmlstr = htmlstr.replace("{{title}}", String.format("%s水费专用收据", bmGs.getMc()));
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{yhxm}}", yhKhjbxx.getYhxm());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());

        htmlstr = htmlstr.replace("{{sfrq}}", yySspjxx.getSfrq().toString());
        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());

        long count = yhGroupService.lambdaQuery()
                .eq(YhGroup::getYhbh, yhKhjbxx.getYhbh())
                .count();
        if (count > 0) {
            htmlstr = htmlstr.replace("{{yhbh}}", yhKhjbxx.getYhbh() + "（群主户）");
            htmlstr = htmlstr.replace("{{scds}}", "");
            htmlstr = htmlstr.replace("{{bcds}}", "");
        } else {
            htmlstr = htmlstr.replace("{{yhbh}}", yhKhjbxx.getYhbh());
            htmlstr = htmlstr.replace("{{scds}}", yySspjxxs.get(0).getScds().toString());
            htmlstr = htmlstr.replace("{{bcds}}", yySspjxxs.get(yySspjxxs.size() - 1).getBcds().toString());
        }

        htmlstr = htmlstr.replace("{{sl}}", yssl.setScale(2, RoundingMode.HALF_UP).toString());
//        屏蔽垃圾处理费、违约金
//        htmlstr = htmlstr.replace("{{ljclf}}", ysljf.setScale(2, RoundingMode.HALF_UP).toString());
//        htmlstr = htmlstr.replace("{{wyj}}", yswyj.setScale(2, RoundingMode.HALF_UP).toString());

        htmlstr = htmlstr.replace("{{content}}", str.toString());
        //实际应收金额=应收金额+违约金-剩余金额
        htmlstr = htmlstr.replace("{{ysje}}", ysje.subtract(scye).setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sszje));

        htmlstr = htmlstr.replace("{{scjy}}", scye.setScale(2, RoundingMode.HALF_UP).toString());

        // 最新实收的余额
        YySspjxx latested = yySspjxxs.stream().sorted(Comparator.comparing(YySspjxx::getSfrq).reversed()
                        .thenComparing(YySspjxx::getSfxh).reversed())
                .collect(Collectors.toList()).get(0);
        htmlstr = htmlstr.replace("{{bcjy}}", latested.getBcye().setScale(2, RoundingMode.HALF_UP).toString());


        //实际实收金额=应收金额+违约金-剩余金额+预存金额
        htmlstr = htmlstr.replace("{{sszje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(sfryxm) ? "" : sfryxm);
        htmlstr = htmlstr.replace("{{dysj}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        htmlstr = htmlstr.replace("{{fwzmc}}", "营业大厅");
        String cbrydh = "暂无";
        if (NumberUtil.isNumber(cbrybm)) {
            User user = userService.get(Long.valueOf(cbrybm));
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
        }
        htmlstr = htmlstr.replace("{{cbrydh}}", cbrydh);

        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate().setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getSflsbh, yySspjxx.getSflsbh())
                .update();
        return htmlstr;
    }

    //预付费票据打印
    private String yffpj(YySspjxx yySspjxx) {
        YhKhjbxx yhKhjbxx = khjbxxService.getById(yySspjxx.getYhbh());
        if (yhKhjbxx == null)
            throw new FeesException("客户信息不存在", BUSINESS_ERROR);
        String cbrydh = "暂无";
        if (NumberUtil.isNumber(yySspjxx.getCbrybm())) {
            User user = userService.get(Long.valueOf(yySspjxx.getCbrybm()));
            //String cbrydh = DbHelper.getDbHelper().getValue(String.format("select olxdh from  sys_operators where ocode = (select cby from bm_cbb where cbbbm='%s')", sspjxx.getSscbb()));
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
        }
        String pjh = yySspjxx.getFph2();
        //判断票据是否存在，不存在更具收费人员获取票据号
        if (StringUtil.isEmpty(pjh)) {
            pjh = yyPjbhService.getPjh(yySspjxx.getSfrybm());
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .eq(YySspjxx::getId, yySspjxx.getId())
                    .update();
        }

        //String htmlstr = DbHelper.getDbHelper().getValue(String.format("select printtemplate from print_template where id=%s", PjlxEnum.预付费票据信息.getValue()));
        String htmlstr = getHtmlContent("templates/yffpjxx.html");
        BmGs bmGs = bmGsService.getById(yhKhjbxx.getSsgs());
        htmlstr = htmlstr.replace("{{title}}", String.format("%s水费预付费收据", bmGs.getMc()));
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{tip}}", "如有疑问请拨打");
        htmlstr = htmlstr.replace("{{tip1}}", String.format("片区管理员电话：%s", cbrydh));
        htmlstr = htmlstr.replace("{{yhbh}}", yySspjxx.getYhbh());
        htmlstr = htmlstr.replace("{{yhxm}}", yySspjxx.getYhxm());
        htmlstr = htmlstr.replace("{{cwyf}}", yySspjxx.getCwrq());
        htmlstr = htmlstr.replace("{{sfrq}}", new SimpleDateFormat("yyyy-MM-dd").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{year}}", new SimpleDateFormat("yyyy").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{month}}", new SimpleDateFormat("MM").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{day}}", new SimpleDateFormat("dd").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{lsbh}}", (yySspjxx.getDycs().compareTo(BigDecimal.ZERO) > 1 ? "【补】" : "") + yySspjxx.getSflsbh());


        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());

        htmlstr = htmlstr.replace("{{scjy}}", yySspjxx.getScye().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcyc}}", yySspjxx.getBcyc().setScale(2, RoundingMode.HALF_UP).toString());
        //htmlstr = htmlstr.replace("{{bcycdx}}", NumberHelper.CmycurD(yySspjxx.getBcyc()));

        htmlstr = htmlstr.replace("{{bckj}}", yySspjxx.getBckj().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sszje}}", yySspjxx.getSszje().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcye}}", yySspjxx.getBcye().setScale(2, RoundingMode.HALF_UP).toString());

        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(yySspjxx.getSfryxm()) ? "" : yySspjxx.getSfryxm());
        htmlstr = htmlstr.replace("{{sfdw}}", "营业大厅");
        htmlstr = htmlstr.replace("{{tip2}}", "请扫“二维码”关注微信公众号");

        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate()
                .setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getId, yySspjxx.getId())
                .update();
        return htmlstr;
    }

    //预付费票据打印
    private String yffpj(String sflsbh, String sflx, String ssid) {
        YySspjxx yySspjxx = null;
        if (StringUtil.isNotEmpty(ssid)) {
            yySspjxx = this.getById(ssid);
        } else {
            yySspjxx = this.getOne(
                    new QueryWrapper<YySspjxx>().lambda()
                            .eq(YySspjxx::getSflsbh, sflsbh)
                            .eq(YySspjxx::getSflx, sflx)
            );
        }
        if (yySspjxx == null)
            throw new FeesException("实收记录不存在", BUSINESS_ERROR);
        YhKhjbxx yhKhjbxx = khjbxxService.getById(yySspjxx.getYhbh());
        if (yhKhjbxx == null)
            throw new FeesException("客户信息不存在", BUSINESS_ERROR);
        String cbrydh = "暂无";
        if (NumberUtil.isNumber(yySspjxx.getCbrybm())) {
            User user = userService.get(Long.valueOf(yySspjxx.getCbrybm()));
            //String cbrydh = DbHelper.getDbHelper().getValue(String.format("select olxdh from  sys_operators where ocode = (select cby from bm_cbb where cbbbm='%s')", sspjxx.getSscbb()));
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
        }
        String pjh = yySspjxx.getFph2();
        //判断票据是否存在，不存在更具收费人员获取票据号
        if (StringUtil.isEmpty(pjh)) {
            pjh = yyPjbhService.getPjh(yySspjxx.getSfrybm());
            this.lambdaUpdate()
                    .set(YySspjxx::getFph2, pjh)
                    .eq(YySspjxx::getId, ssid)
                    .update();
        }

        //String htmlstr = DbHelper.getDbHelper().getValue(String.format("select printtemplate from print_template where id=%s", PjlxEnum.预付费票据信息.getValue()));
        String htmlstr = getHtmlContent("templates/yffpjxx.html");
        BmGs bmGs = bmGsService.getById(yhKhjbxx.getSsgs());

        String mc = String.format("%s水费预付费收据", bmGs.getMc());
        if (预存退费.equals(yySspjxx.getSflx())) {
            mc = String.format("%s水费退费收据", bmGs.getMc());
        }

        htmlstr = htmlstr.replace("{{title}}", mc);
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{tip}}", "如有疑问请拨打");
        htmlstr = htmlstr.replace("{{tip1}}", String.format("片区管理员电话：%s", cbrydh));
        htmlstr = htmlstr.replace("{{yhbh}}", yySspjxx.getYhbh());
        htmlstr = htmlstr.replace("{{yhxm}}", yySspjxx.getYhxm());
        htmlstr = htmlstr.replace("{{cwyf}}", yySspjxx.getCwrq());


        htmlstr = htmlstr.replace("{{sfrq}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{year}}", new SimpleDateFormat("yyyy").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{month}}", new SimpleDateFormat("MM").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{day}}", new SimpleDateFormat("dd").format(yySspjxx.getSfrq()));
        htmlstr = htmlstr.replace("{{lsbh}}", (yySspjxx.getDycs().compareTo(BigDecimal.ZERO) > 1 ? "【补】" : "") + sflsbh);


        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());

        htmlstr = htmlstr.replace("{{scjy}}", yySspjxx.getScye().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcyc}}", yySspjxx.getBcyc().setScale(2, RoundingMode.HALF_UP).toString());
        //htmlstr = htmlstr.replace("{{bcycdx}}", NumberHelper.CmycurD(yySspjxx.getBcyc()));

        htmlstr = htmlstr.replace("{{bckj}}", yySspjxx.getBckj().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sszje}}", yySspjxx.getSszje().setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcye}}", yySspjxx.getBcye().setScale(2, RoundingMode.HALF_UP).toString());

        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(yySspjxx.getSfryxm()) ? "" : yySspjxx.getSfryxm());
        htmlstr = htmlstr.replace("{{sfdw}}", "营业大厅");
        htmlstr = htmlstr.replace("{{tip2}}", "请扫“二维码”关注微信公众号");

        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate()
                .setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getId, yySspjxx.getId())
                .update();
        return htmlstr;
    }

    private String qfsfpj(List<YySspjxx> yySspjxxs, String pjh, YhKhjbxx yhKhjbxx) throws Exception {
        StringBuilder str = new StringBuilder();
        BigDecimal ysje = yySspjxxs.stream().map(YySspjxx::getYsje).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal sszje = yySspjxxs.stream().map(YySspjxx::getSszje).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysqtf = yySspjxxs.stream().map(o -> checkNumber(o.getYsqt())).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal scye = yySspjxxs.get(0).getScye();
        BigDecimal ycje = BigDecimal.ZERO;
        String ycjesql = String.format("select sum(NVL(sszje,0)) from yy_sspjxx " +
                        "where sflsbh='%s' and sflx=3  group by sflsbh"
                , yySspjxxs.get(0).getSflsbh());
        String ycjestr = DbHelper.getDbHelper().getValue(ycjesql);
        if (StringUtil.isNotEmpty(ycjestr)) {
            ycje = BigDecimal.valueOf(Double.parseDouble(ycjestr));
        }

        for (YySspjxx sspjxx : yySspjxxs) {
            str.append("<tr>");
            str.append(String.format("<td colspan='2'>%s</td>", sspjxx.getFylxmc()));
            str.append(String.format("<td colspan='2'>%s</td>", sspjxx.getCwrq()));
            str.append(String.format("<td colspan='2'>%s</td>", sspjxx.getYsqt()));
            str.append("</tr>");
        }


        String cbrybm = yySspjxxs.get(0).getCbrybm();
        String sfryxm = yySspjxxs.get(0).getSfryxm();


        String htmlstr = getHtmlContent("templates/qtfsspjxx.html");
        BmGs bmGs = bmGsService.getById(yhKhjbxx.getSsgs());
        htmlstr = htmlstr.replace("{{title}}", String.format("%s水费专用收据", bmGs.getMc()));
        htmlstr = htmlstr.replace("{{pjh}}", pjh);
        htmlstr = htmlstr.replace("{{yhxm}}", yhKhjbxx.getYhxm());
        htmlstr = htmlstr.replace("{{addr}}", StringUtil.isEmpty(yhKhjbxx.getYhdz()) ? "" : yhKhjbxx.getYhdz());
        htmlstr = htmlstr.replace("{{cwrq}}", yySspjxxs.get(0).getCwrq());
        htmlstr = htmlstr.replace("{{sfrq}}", yySspjxxs.get(0).getSfrq().toString());
        htmlstr = htmlstr.replace("{{lxdh}}", StringUtil.isEmpty(yhKhjbxx.getLxdh()) ? "" : yhKhjbxx.getLxdh());
        htmlstr = htmlstr.replace("{{yhbh}}", yhKhjbxx.getYhbh());
        htmlstr = htmlstr.replace("{{content}}", str.toString());
        htmlstr = htmlstr.replace("{{ysje}}", ysje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssje}}", ysje.add(ycje).setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{scjy}}", scye.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{bcjy}}", ycje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{sszje}}", sszje.setScale(2, RoundingMode.HALF_UP).toString());
        htmlstr = htmlstr.replace("{{ssjedx}}", NumberHelper.toChineseMoney(sszje));
        htmlstr = htmlstr.replace("{{sfry}}", StringUtil.isEmpty(sfryxm) ? "" : sfryxm);
        htmlstr = htmlstr.replace("{{dysj}}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        htmlstr = htmlstr.replace("{{fwzmc}}", "营业大厅");
        String cbrydh = "暂无";
        if (NumberUtil.isNumber(cbrybm)) {
            User user = userService.get(Long.valueOf(cbrybm));
            if (user != null && StringUtil.isNotEmpty(user.getPhone())) {
                cbrydh = user.getPhone();
            }
        }
        htmlstr = htmlstr.replace("{{cbrydh}}", cbrydh);
        htmlstr = htmlstr.replace("{{sjh}}", pjh);//收据号
        this.lambdaUpdate()
                .setSql("dycs=dycs+" + 1)
                .eq(YySspjxx::getSflsbh, yySspjxxs.get(0).getSflsbh())
                .update();
        return htmlstr;
    }


    /**
     * 获取Html文件内容
     *
     * @param relativePath 文件路径
     * @return
     */
    private String getHtmlContent(String relativePath) {
        String content = "";
        InputStream inputStream = ResourceReader.class.getClassLoader().getResourceAsStream(relativePath);
        // 确保资源存在
        if (inputStream != null) {
            // 使用BufferedReader读取内容
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line;
            try {
                while ((line = reader.readLine()) != null) {
                    content += line;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return content;
    }

    /**
     * 生成预付费票据信息
     */
    private YySspjxx createYffsq(YhKhjbxx yhxx, String ysyf, BigDecimal scye, BigDecimal bcye, BigDecimal yc, int sfxh, String fffs) {
        YySspjxx zsspjxx = new YySspjxx();
        String cwrq = gdcsbService.selectCwrq();
        BeanUtils.copyProperties(yhxx, zsspjxx, "fffs");
        zsspjxx.setSfxh(sfxh);
        zsspjxx.setSflx(预付费收取);
        zsspjxx.setYsyf(ysyf);
        zsspjxx.setBz("YFF");
        zsspjxx.setScye(scye);
        zsspjxx.setBcye(bcye);
        zsspjxx.setBcyc(yc);
        zsspjxx.setCwrq(cwrq);
        zsspjxx.setSszje(yc);
        zsspjxx.setSfbc("0");
        zsspjxx.setSfbz("1");
        zsspjxx.setFffs(fffs);
        return zsspjxx;
    }

    private YySspjxx createYezc(YhKhjbxx yhxx, String ysyf, BigDecimal scye, BigDecimal bcye, BigDecimal yc, int sfxh, String fffs) {
        YySspjxx zsspjxx = new YySspjxx();
        String cwrq = gdcsbService.selectCwrq();
        BeanUtils.copyProperties(yhxx, zsspjxx, "fffs");

        zsspjxx.setSfxh(sfxh);//收费序号
        zsspjxx.setSflx(余额转存);
        zsspjxx.setYsyf(ysyf);
        zsspjxx.setBz("YEZC");
        zsspjxx.setScye(scye);
        zsspjxx.setBcye(bcye);
        zsspjxx.setBckj(BigDecimal.ZERO);
        zsspjxx.setZyc(yc);
        zsspjxx.setCwrq(cwrq);
        zsspjxx.setSszje(BigDecimal.ZERO);
        zsspjxx.setSfbc("1");
        zsspjxx.setSfbz("1");
        zsspjxx.setFffs(fffs);
        return zsspjxx;
    }

    @Override
    public List<JrtjSelect> jrtj(String sfrybm) {
        return this.baseMapper.jrtj(sfrybm);
    }

    @Override
    public BigDecimal sbje(String yhbh) {
        return this.baseMapper.sbje(yhbh);
    }

    @Override
    public void addYffsq(String yhbh, BigDecimal scye, BigDecimal bcye, BigDecimal sszje, Date sfrq, String bz, int sfxh, String fffs, String sflsbh) {
        String ysyf = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        YhKhjbxx yhxx = khjbxxService.getById(yhbh);
        YySspjxx sspjxx = createYffsq(yhxx, ysyf, scye, bcye, sszje, sfxh, fffs);
        BmCbb bmCbb = bmCbbService.getById(yhxx.getSscbb());

        if (ObjectUtil.isNotNull(bmCbb)) {
            sspjxx.setCbrybm(bmCbb.getCby());
            if (StringUtil.isNotEmpty(bmCbb.getCby())) {
                User user = userService.get(Long.valueOf(bmCbb.getCby()));
                if (ObjUtil.isNotNull(user)) {
                    sspjxx.setCbryxm(user.getRealName());
                }
            }
            sspjxx.setQyfzrbm(bmCbb.getQyfzr());
            sspjxx.setQyfzrxm(bmCbb.getQyfzrxm());
        }

        if (StringUtil.isEmpty(sflsbh)) {
            sflsbh = GuidGenerator.getSflsbh();
        }

        sspjxx.setSflsbh(sflsbh);
        sspjxx.setQflsbh(sflsbh);
        sspjxx.setQfid(sflsbh);
        sspjxx.setSfrq(sfrq);
        sspjxx.setSfsjrq(sfrq);

        if (StringUtil.isNotEmpty(bz) && bz.equals("预存退费")) {
            sspjxx.setSflx(预存退费);
        }

        sspjxx.setBz(bz);
        YhCbkxx yhcbkxx = yhCbkxxService.getOne(new QueryWrapper<YhCbkxx>().lambda()
                .eq(YhCbkxx::getYhbh, yhbh)
                .eq(YhCbkxx::getCbkh, "1")
        );

        sspjxx.setCbkid(yhcbkxx.getCbkid());
        sspjxx.setCbkh(yhcbkxx.getCbkh());
        //智能表
        if (yhcbkxx.getSblb().equals("2") || yhcbkxx.getSblb().equals("3")) {
            if (bcye.compareTo(BigDecimal.ZERO) > 0) {
                ZnbZlLog znbZlLog = new ZnbZlLog();
                znbZlLog.setYhbh(sspjxx.getYhbh());
                znbZlLog.setPch(sflsbh);
                znbZlLog.setSsgs(yhxx.getSsgs());
                znbZlLog.setCbkh(yhcbkxx.getCbkh());
                znbZlLog.setCbkid(yhcbkxx.getCbkid());
                znbZlLog.setSccj(yhcbkxx.getSbsccj());
                znbZlLog.setCzry(String.valueOf(SecurityUtils.getUserId()));
                znbZlLog.setCzsj(LocalDateTime.now());
                znbZlLog.setClLock("0");
                znbZlLog.setClCljg("0");
                znbZlLog.setZltype("1");//阀控
                znbZlLog.setZlvalue("1");//开阀
                znbZlLog.setBjbh(yhcbkxx.getSbbh());
                iZnbZlLogService.save(znbZlLog);
            }
        }

        sspjxx.setFph2(yyPjbhService.getPjh(SecurityUtils.getUserId().toString()));
        sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
        sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());

        this.save(sspjxx);
    }

    @Override
    public void addZyc(String yhbh, BigDecimal scye, BigDecimal bcye, BigDecimal zyc, Date sfrq, String bz, int sfxh, String fffs, String sflsbh) {
        String ysyf = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        YhKhjbxx yhxx = khjbxxService.getById(yhbh);
        YySspjxx sspjxx = createYezc(yhxx, ysyf, scye, bcye, zyc, sfxh, fffs);
        if (StringUtil.isEmpty(sflsbh))
            sflsbh = GuidGenerator.getSflsbh();
        sspjxx.setSflsbh(sflsbh);
        sspjxx.setQflsbh(sflsbh);
        sspjxx.setQfid(sflsbh);
        sspjxx.setSfrq(sfrq);
        sspjxx.setBz(bz);
        YhCbkxx yhcbkxx = yhCbkxxService.getOne(new QueryWrapper<YhCbkxx>().lambda()
                .eq(YhCbkxx::getYhbh, yhbh)
                .eq(YhCbkxx::getCbkh, "1")
        );
        sspjxx.setCbkid(yhcbkxx.getCbkid());
        sspjxx.setCbkh(yhcbkxx.getCbkh());
//        if (yhcbkxx.getSblb().equals("2") || yhcbkxx.getSblb().equals("3")) {
//            ZnbZlLog znbZlLog = new ZnbZlLog();
//            znbZlLog.setYhbh(yhxx.getYhbh());
//            // znbZlLog.setPch(yhxx.getJdpcxlh());
//            znbZlLog.setSsgs(yhxx.getSsgs());
//            znbZlLog.setCbkh(yhcbkxx.getCbkh());
//            znbZlLog.setCbkid(yhcbkxx.getCbkid());
//            znbZlLog.setSccj(yhcbkxx.getSbsccj());
//            znbZlLog.setCzry(String.valueOf(SecurityUtils.getUserId()));
//            znbZlLog.setCzsj(LocalDateTime.now());
//            znbZlLog.setClLock("0");
//            znbZlLog.setClCljg("0");
//            znbZlLog.setZltype("2");
//            znbZlLog.setBjbh(yhcbkxx.getSbbh());
//            znbZlLog.setPch(ToolsUtils.getGuid());
//            znbZlLog.setId(ToolsUtils.getGuid());
//            iZnbZlLogService.save(znbZlLog);
//        }
        sspjxx.setSfrybm(String.valueOf(SecurityUtils.getUserId()));
        sspjxx.setSfryxm(SecurityUtils.getUser().getRealName());

        this.save(sspjxx);
    }

    @Override
    @Transactional
    public Integer pjCh(PjCh pjch) {
        return pjChCl(pjch, "");
    }

    public Integer pjChCl(PjCh pjch, String clly) {
        String sflsbh = pjch.getSflsbh();

        if (StringUtil.isEmpty(sflsbh))
            throw new FeesException("收费流水编号为空", FeesErrorCode.BUSINESS_ERROR);
        if (StringUtil.isEmpty(pjch.getYhbh()))
            throw new FeesException("用户编号为空", FeesErrorCode.BUSINESS_ERROR);
        if (StringUtil.isEmpty(pjch.getChtype()))
            throw new FeesException("冲红类型为空", FeesErrorCode.BUSINESS_ERROR);

        // 1.检查发票状态
        List<EiFpkjRequest> eiFpkjRequestList = eiFpkjRequestService.list(
                new QueryWrapper<EiFpkjRequest>().lambda()
                        .eq(EiFpkjRequest::getYhbh, pjch.getYhbh())
                        .eq(EiFpkjRequest::getSfid, sflsbh)
        );
        long count = eiFpkjRequestList.stream()
                .filter(
                        e -> !e.getClCljg().equals("1")
                                && !e.getClCljg().equals("0")
                ).count();
        if (count > 0) {
            throw new FeesException("无法进行冲红操作:存在正在进行开票的记录，请在发票管理查询！", FeesErrorCode.BUSINESS_ERROR);
        }

        // 2.校验冲红人员、收费人员
        String yhbh = pjch.getYhbh();
        String chrybm = String.valueOf(SecurityUtils.getUserId());
        String chryxm = SecurityUtils.getUser().getRealName();
        List<YySspjxx> sspjxxList = this.lambdaQuery()
                .eq(YySspjxx::getYhbh, yhbh)
                .eq(YySspjxx::getSflsbh, sflsbh)
                .list();
        count = sspjxxList.stream().filter(e -> !e.getSfrybm().equals(chrybm)).count();
        if (count > 0) {
            throw new FeesException("无法进行冲红操作:存在收费人员不是当前冲红人员！", FeesErrorCode.BUSINESS_ERROR);
        }

        if ("1".equals(clly)) {
            //10135->微信账号ID
            count = sspjxxList.stream().filter(item -> !"10135".equals(item.getSfrybm())).count();
            if (count > 0) {
                throw new FeesException("非微信收费不能进行微信退费！", FeesErrorCode.BUSINESS_ERROR);
            }
        }

        Date chsj = new Date();
        Integer re = 0;
        String sflsbh1 = GuidGenerator.getSflsbh();

        // 获取客户编码(仅大客户存在编码)
//        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
//        String khbm = yhKhjbxx.getKhbm();
//        if (StrUtil.isEmpty(khbm)) {
//            khbm = StrUtil.EMPTY;
//        }
        String khbm = "";

//        Map<String, Object> result = new HashMap<>();
        if (pjch.getChtype().equals("0")) {
            BigDecimal sszje = baseMapper.sszje(sflsbh);
// 原存储过程冲红
//            result.put("yhbh", yhbh);
//            result.put("sflsbh", sflsbh);
//            result.put("sszje", sszje);
//            result.put("chrybm", chrybm);
//            result.put("chryxm", chryxm);
//            result.put("sflsbh1", sflsbh1);
//            result.put("chsj", chsj);
//            this.baseMapper.pjCh(result);
//            re = (Integer) result.get("result");

            // 存储过程替换为程序处理
            PjchDto pjchDto = PjchDto.build(yhbh, sflsbh, sszje, chrybm, chryxm, sflsbh1, chsj, khbm);
            re = pjchByCode(pjchDto);
        } else if (pjch.getChtype().equals("1")) {
            List<Map> list = baseMapper.yhsszje(sflsbh);
            if (CollUtil.isEmpty(list)) {
                list = baseMapper.yhkjje(sflsbh);
            }

            for (Map map : list) {
                String fzyhbh = map.get("yhbh").toString();
                BigDecimal sszje = (BigDecimal) map.get("je");
                // 原存储过程
//                result = new HashMap<>();
//                result.put("yhbh", fzyhbh);
//                result.put("sflsbh", sflsbh);
//                result.put("sszje", sszje);
//                result.put("chrybm", chrybm);
//                result.put("chryxm", chryxm);
//                result.put("sflsbh1", sflsbh1);
//                result.put("chsj", chsj);
//                this.baseMapper.pjCh(result);
//                re = (Integer) result.get("result");
                PjchDto pjchDto = PjchDto.build(fzyhbh, sflsbh, sszje, chrybm, chryxm, sflsbh1, chsj, khbm);
                re = pjchByCode(pjchDto);

                if (re != 1) {
                    log.error(String.format("pjCh用户编号：%s冲红失败,失败编码%s", fzyhbh, re));
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            }
        }
        if (re == 1) {
            invoiceService.InvoiceRed(eiFpkjRequestList);
        }
        return re;
    }


    /**
     * @param pjch
     * @param clly 处理来源 1为微信退费
     * @return
     */

    private Integer PjChClS(PjCh pjch, String clly) {
        String sflsbh = pjch.getSflsbh();
        if (StringUtil.isEmpty(sflsbh))
            throw new FeesException("收费流水编号为空", FeesErrorCode.BUSINESS_ERROR);
        if (StringUtil.isEmpty(pjch.getYhbh()))
            throw new FeesException("用户编号为空", FeesErrorCode.BUSINESS_ERROR);
        if (StringUtil.isEmpty(pjch.getChtype()))
            throw new FeesException("冲红类型为空", FeesErrorCode.BUSINESS_ERROR);
        List<EiFpkjRequest> eiFpkjRequestList = eiFpkjRequestService.list(
                new QueryWrapper<EiFpkjRequest>().lambda()
                        .eq(EiFpkjRequest::getYhbh, pjch.getYhbh())
                        .eq(EiFpkjRequest::getSfid, sflsbh)
        );
        long count = eiFpkjRequestList.stream()
                .filter(
                        e -> !e.getClCljg().equals("1")
                                && !e.getClCljg().equals("0")
                ).count();
        if (count > 0) {
            throw new FeesException("无法进行冲红操作:存在正在进行开票的记录，请在发票管理查询！", FeesErrorCode.BUSINESS_ERROR);
        }
        String yhbh = pjch.getYhbh();
        String chrybm = String.valueOf(SecurityUtils.getUserId());
        String chryxm = SecurityUtils.getUser().getRealName();
        List<YySspjxx> sspjxxList = this.lambdaQuery()
                .eq(YySspjxx::getYhbh, yhbh)
                .eq(YySspjxx::getSflsbh, sflsbh)
                .list();
        count = sspjxxList.stream().filter(e -> !e.getSfrybm().equals(chrybm)).count();
        if (count > 0) {
            throw new FeesException("无法进行冲红操作:存在收费人员不是当前冲红人员！", FeesErrorCode.BUSINESS_ERROR);
        }
        if ("1".equals(clly)) {
            //10135->微信账号ID
            count = sspjxxList.stream().filter(item -> !"10135".equals(item.getSfrybm())).count();
            if (count > 0) {
                throw new FeesException("非微信收费不能进行微信退费！", FeesErrorCode.BUSINESS_ERROR);
            }
        }
        Date chsj = new Date();
        Map<String, Object> result = new HashMap<>();
        result.put("khbm", StrUtil.EMPTY);
        Integer re = 0;
        String sflsbh1 = GuidGenerator.getSflsbh();
        // 获取大户客户编码
        YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
        String khbm = yhKhjbxx.getKhbm();
        if (StrUtil.isNotEmpty(khbm)) {
            result.put("khbm", khbm);
        }

        if (pjch.getChtype().equals("0")) {
            BigDecimal sszje = this.baseMapper.sszje(sflsbh);
            result.put("yhbh", yhbh);
            result.put("sflsbh", sflsbh);
            result.put("sszje", sszje);
            result.put("chrybm", chrybm);
            result.put("chryxm", chryxm);
            result.put("sflsbh1", sflsbh1);
            result.put("chsj", chsj);
            this.baseMapper.pjCh(result);
            re = (Integer) result.get("result");
        } else if (pjch.getChtype().equals("1")) {
            List<Map> list = this.baseMapper.yhsszje(sflsbh);
            if (StringUtil.isNull(list) || list.isEmpty()) {
                list = this.baseMapper.yhkjje(sflsbh);
            }
            for (Map map : list) {
                String fzyhbh = map.get("yhbh").toString();
                BigDecimal sszje = (BigDecimal) map.get("je");
                result = new HashMap<>();
                result.put("yhbh", fzyhbh);
                result.put("sflsbh", sflsbh);
                result.put("sszje", sszje);
                result.put("chrybm", chrybm);
                result.put("chryxm", chryxm);
                result.put("sflsbh1", sflsbh1);
                result.put("chsj", chsj);
                this.baseMapper.pjCh(result);
                re = (Integer) result.get("result");
                if (re != 1) {
                    log.info(String.format("pjCh用户编号：%s冲红失败、失败编码%s", fzyhbh, re));
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            }
        }
        if (re == 1) {
            invoiceService.InvoiceRed(eiFpkjRequestList);
        }
        return re;
    }


    /**
     * 票据冲红
     * 将数据库存储过程转化为代码
     */
    public Integer pjchByCode(PjchDto pjchDto) {
        // 判断大户、小户冲红
        ChSspjData chSspjData = baseMapper.selectSspjData(pjchDto);
        if (chSspjData.getNum() < 1) {
            return 9;
        }

        YyZjzh zjzh = zjzhService.selectByChDto(pjchDto);
        Integer zxsfCount = baseMapper.selectByZxsfrq(chSspjData.getZxsfrq(), pjchDto);

        // 数据校验
        Integer checkReuslt = checkSspjxxData(chSspjData, pjchDto, zjzh, zxsfCount);
        if (checkReuslt != 1) {
            return checkReuslt;
        }

        // 根据收费类型退费
        refundBySflx(chSspjData, pjchDto, zjzh);
        return 1;
    }

    /***
     * 校验要冲红的实收数据
     */
    public Integer checkSspjxxData(ChSspjData chSspjData, PjchDto pjchDto, YyZjzh zjzh, Integer zxsfCount) {
        String khbm = pjchDto.getKhbm();
        String sflsbh = pjchDto.getSflsbh();
        String yhbh = pjchDto.getYhbh();

        Integer num = chSspjData.getNum();
        if (num <= 0) {
            return 9;
        }

        BigDecimal sszje = chSspjData.getSszje();
        if (pjchDto.getSszje().compareTo(sszje) != 0) {
            return 2;
        }

        if (zxsfCount > 0) {
            return 3;
        }

        BigDecimal syje = BigDecimal.ZERO;
        if (zjzh != null) {
            syje = zjzh.getNbsyje();
        }
        BigDecimal zxbcye;
        if (StrUtil.isNotEmpty(khbm)) {
            zxbcye = baseMapper.selectZxbcye(khbm, sflsbh, 1);
        } else {
            zxbcye = baseMapper.selectZxbcye(yhbh, sflsbh, 0);
        }
        if (syje.compareTo(zxbcye) != 0) {
            return 4;
        }

        return 1;
    }

    /**
     * 根据收费类型退费
     */
    @Transactional
    public void refundBySflx(ChSspjData chSspjData, PjchDto pjchDto, YyZjzh zjzh) {
        String khbm = pjchDto.getKhbm();
        String yhbh = pjchDto.getYhbh();
        String sflsbh = pjchDto.getSflsbh();

        Integer minSflx = chSspjData.getSflx();
        BigDecimal sszje = chSspjData.getSszje();

        String cwrq = gdcsbService.selectCwrq();
        BigDecimal syje = BigDecimal.ZERO;
        if (zjzh != null) {
            syje = zjzh.getNbsyje();
        }

        if (minSflx == 3) { // 只有预存冲红
            baseMapper.addYcChjl(pjchDto, cwrq, syje);
            zjzhService.ycch(pjchDto, sszje);
            baseMapper.gxchbz(pjchDto, sflsbh);
        } else if (minSflx == 2) { // 营业厅缴费可能含预存
            List<YySspjxx> chpjxxList = getChPjxxList(khbm, yhbh, sflsbh);
            if (CollUtil.isEmpty(chpjxxList)) {
                return;
            }

            Integer chCount = baseMapper.selectCountBySflsbh(pjchDto);
            int xh = 1;
            for (YySspjxx chpjData : chpjxxList) {
                SflxEnum sflx = chpjData.getSflx();
                if (sflx.getValue() == 3) {
                    ycch(chpjData, pjchDto, cwrq);
                }
                if (sflx.getValue() == 2) {
                    yytkfch(chpjData, pjchDto, cwrq);
                }
                if (sflx.getValue() == 2 && xh == chCount) {
                    BigDecimal bckj = chpjData.getBckj();
                    zjzhService.updateByKfch(bckj, pjchDto);
                }
                xh++;
            }
        } else if (minSflx == 1) {// 预存抵扣冲红
            List<YySspjxx> chpjxxList = getChPjxxList(khbm, yhbh, sflsbh);
            if (CollUtil.isEmpty(chpjxxList)) {
                return;
            }

            Integer chCount = baseMapper.selectCountBySflsbh(pjchDto);
            int xh = 1;
            for (YySspjxx yySspjxx : chpjxxList) {
                SflxEnum sflx = yySspjxx.getSflx();
                if (sflx.getValue() == 1) {
                    ycdkch(yySspjxx, pjchDto, cwrq);
                }
                if (sflx.getValue() == 3 && xh == chCount) {
                    // 第一条预存
                    firstYcch(yySspjxx, pjchDto, cwrq);
                }
                xh++;
            }
        }
    }

    /**
     * 第一条预存冲红
     */
    public void firstYcch(YySspjxx yySspjxx, PjchDto pjchDto, String cwrq) {
        baseMapper.firstYcch(yySspjxx, pjchDto, cwrq);

        BigDecimal sszje = yySspjxx.getSszje();
        zjzhService.ycch(pjchDto, sszje);

        yySspjxx.setChbz("1");
        updateById(yySspjxx);
    }

    /**
     * 预存抵扣冲红
     */
    public void ycdkch(YySspjxx yySspjxx, PjchDto pjchDto, String cwrq) {
        // 预存抵扣冲红记录
        baseMapper.ycdkch(yySspjxx, pjchDto, cwrq);
        yySspjxx.setChbz("1");
        updateById(yySspjxx);

        // 扣费冲红更新账户
        BigDecimal bckj = yySspjxx.getBckj();
        zjzhService.updateByKfch(bckj, pjchDto);

        qfmxService.ycdkch(yySspjxx, pjchDto, cwrq);
    }

    /**
     * 营业厅扣费冲红
     */
    public void yytkfch(YySspjxx chpjData, PjchDto pjchDto, String cwrq) {
        baseMapper.yytkfch(chpjData, pjchDto, cwrq);

        chpjData.setChbz("1");
        chpjData.setChsj(pjchDto.getChsj());
        chpjData.setChrybm(pjchDto.getChrybm());
        chpjData.setChryxm(pjchDto.getChryxm());
        baseMapper.updateById(chpjData);

        // 欠费明细冲红
        qfmxService.yytkfch(chpjData, pjchDto, cwrq);
    }

    /**
     * 扣费后再预存冲红
     */
    public void ycch(YySspjxx chpjData, PjchDto pjchDto, String cwrq) {
        baseMapper.kfhycch(chpjData, pjchDto, cwrq);
        BigDecimal sszje = chpjData.getSszje();
        zjzhService.ycch(pjchDto, sszje);

        chpjData.setChbz("1");
        chpjData.setChsj(pjchDto.getChsj());
        chpjData.setChrybm(pjchDto.getChrybm());
        chpjData.setChryxm(pjchDto.getChryxm());
        baseMapper.updateById(chpjData);
    }

    /**
     * 获取要冲红的票据信息
     */
    public List<YySspjxx> getChPjxxList(String khbm, String yhbh, String sflsbh) {
        LambdaQueryWrapper<YySspjxx> wrapper = Wrappers.<YySspjxx>lambdaQuery()
                .eq(YySspjxx::getSflsbh, sflsbh)
                .eq(YySspjxx::getSfbz, "1")
                .eq(YySspjxx::getChbz, "0");

        if (StrUtil.isNotEmpty(khbm)) {
            wrapper.eq(YySspjxx::getKhbm, khbm);
        } else {
            wrapper.eq(YySspjxx::getYhbh, yhbh);
        }
        wrapper.orderByDesc(YySspjxx::getSfxh);
        return baseMapper.selectList(wrapper);
    }

    @Override
    public List<YySspjxxSelect> getList(YySspjxxFilter filter, String sffl, String chbz) {
        if (StringUtil.isEmpty(filter.getUserId())) {
            filter.setUserId(SecurityUtils.getUserId().toString());
        }
        List<YySspjxxSelect> list = this.baseMapper.getPageList(filter, sffl, chbz);
        if (!list.isEmpty()) {
            Map<String, String> sjMap = getSjMap();
            list = list.stream().sorted(Comparator.comparing(YySspjxxSelect::getYhbh)).collect(Collectors.toList());
            list.forEach(e -> {
                setYslx(e, sjMap);
                if (!"1".equals(e.getFylx()) && !"2".equals(e.getFylx())) {
                    e.setYssl(BigDecimal.ZERO);
                }
            });
        }
        return list;
    }

    @Override
    public YySspjxxSelectCount getPageList(PageDto pageDto, YySspjxxFilter filter, String sffl, String chbz) {
        List<Order> orders = pageDto.getOrders();
        orders = orders.stream().map(item -> {
            if (item.getColumn().equals("yhbh")) {
                Order order = new Order();
                order.setColumn("a.yhbh");
                order.setAsc(item.isAsc());
                return order;
            }
            return item;
        }).collect(Collectors.toList());


        if (StringUtil.isEmpty(filter.getUserId())) {
            filter.setUserId(SecurityUtils.getUserId().toString());
        }

        PageDto<YySspjxxSelect> page = null;
        if (filter.getDhkh() != null && filter.getDhkh().equals("0")) {
            pageDto.setOrders(orders);
            page = baseMapper.getPageList(pageDto, filter, sffl, chbz);

            Map<String, String> sjMap = getSjMap();
            page.getRecords().forEach(e -> {
                setYslx(e, sjMap);
                if (!"1".equals(e.getFylx()) && !"2".equals(e.getFylx())) {
                    e.setYssl(BigDecimal.ZERO);
                }
            });
        } else if (filter.getDhkh() != null && filter.getDhkh().equals("1")) {
            pageDto.setOrders(null);
            page = baseMapper.getPageListByKhbm(pageDto, filter, sffl, chbz);
        }


        YySspjxxSelectCount yySspjxxSelectCount = new YySspjxxSelectCount();
        yySspjxxSelectCount.setList(page.toVo());
        //所有页合计
        YySspjxxSelectCount tempModel = baseMapper.getPageCount(filter, sffl, chbz);
        if (StringUtil.isNotNull(tempModel)) {
            BeanUtils.copyProperties(tempModel, yySspjxxSelectCount);
            yySspjxxSelectCount.setList(page.toVo());
            //当前页合计
            List<YySspjxxSelect> records = page.getRecords();
            countPjxx(records, yySspjxxSelectCount);
        }
        return yySspjxxSelectCount;
    }

    private void countPjxx(List<YySspjxxSelect> records, YySspjxxSelectCount yySspjxxSelectCount) {
        if (CollectionUtil.isEmpty(records)) {
            yySspjxxSelectCount.setYssf(BigDecimal.ZERO);
            yySspjxxSelectCount.setYssl(BigDecimal.ZERO);
            yySspjxxSelectCount.setYswsf(BigDecimal.ZERO);
            yySspjxxSelectCount.setYsljf(BigDecimal.ZERO);
            yySspjxxSelectCount.setYsszyf(BigDecimal.ZERO);
            yySspjxxSelectCount.setZnj(BigDecimal.ZERO);
            yySspjxxSelectCount.setYsje(BigDecimal.ZERO);
            yySspjxxSelectCount.setBcyc(BigDecimal.ZERO);
            yySspjxxSelectCount.setBckj(BigDecimal.ZERO);
            yySspjxxSelectCount.setSszje(BigDecimal.ZERO);
        } else {
            BigDecimal yssfSum = records.stream().map(o -> checkNumber(o.getYssf())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setYssf(yssfSum);

            BigDecimal ysslSum = records.stream().map(o -> checkNumber(o.getYssl())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setYssl(ysslSum);

            BigDecimal yswsfSum = records.stream().map(o -> checkNumber(o.getYswsf())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setYswsf(yswsfSum);

            BigDecimal ysljfSum = records.stream().map(o -> checkNumber(o.getYsljf())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setYsljf(ysljfSum);

            BigDecimal ysszyfSum = records.stream().map(o -> checkNumber(o.getYsszyf())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setYsszyf(ysszyfSum);

            BigDecimal znjSum = records.stream().map(o -> checkNumber(o.getZnj())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setZnj(znjSum);

            BigDecimal ysjeSum = records.stream().map(o -> checkNumber(o.getYsje())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setYsje(ysjeSum);

            BigDecimal bcycSum = records.stream().map(o -> checkNumber(o.getBcyc())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setBcyc(bcycSum);

            BigDecimal bckjSum = records.stream().map(o -> checkNumber(o.getBckj())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setBckj(bckjSum);

            BigDecimal sszjeSum = records.stream().map(o -> checkNumber(o.getSszje())).reduce(BigDecimal.ZERO, BigDecimal::add);
            yySspjxxSelectCount.setSszje(sszjeSum);
        }
    }

    @Override
    public List<JzhztjDto> sscxby(YySspjxxFilter filter) {
        if (StringUtil.isEmpty(filter.getCwrq()) && StringUtil.isEmpty(filter.getNf())) {
            throw new FeesException("参数错误，年份与财务日期不能同时为空", BUSINESS_ERROR);
        }
//        if (StringUtil.isNotEmpty(filter.getCwrq())) {
//            String cwrq = filter.getCwrq();
//            String tempStartSfrq = cwrq.substring(0, 4) + "-" + cwrq.substring(4, 6) + "-01 00:00:00";
//            String tempEndSfrq = cwrq.substring(0, 4) + "-" + cwrq.substring(4, 6) + "-01 23:59:59";
//            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
//            LocalDateTime dt_tempStartSfrq = LocalDateTime.parse(tempStartSfrq, formatter);
//            LocalDateTime dt_tempEndSfrq = LocalDateTime.parse(tempEndSfrq, formatter).plusMonths(1).plusDays(-1);
//
//            filter.setSfrqStart(DateUtils.convertLDTToDate(dt_tempStartSfrq));
//            filter.setSfrqEnd(DateUtils.convertLDTToDate(dt_tempEndSfrq));
//        }
//        if (StringUtil.isNotEmpty(filter.getNf())) {
//            String nf = filter.getNf();
//            String tempStartSfrq = nf + "-01-01 00:00:00";
//            String tempEndSfrq = nf + "-12-31 23:59:59";
//            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
//            LocalDateTime dt_tempStartSfrq = LocalDateTime.parse(tempStartSfrq, formatter);
//            LocalDateTime dt_tempEndSfrq = LocalDateTime.parse(tempEndSfrq, formatter);
//
//            filter.setSfrqStart(DateUtils.convertLDTToDate(dt_tempStartSfrq));
//            filter.setSfrqEnd(DateUtils.convertLDTToDate(dt_tempEndSfrq));
//        }
        List<YyQfmxJzhzSelect> lists = new ArrayList<>();
        List<YyQfmxJzhzSelect> jzhztjList1 = baseMapper.sscxby(filter, "");
        List<YyQfmxJzhzSelect> jzhztjList2 = baseMapper.sscxby(filter, "1");
        List<YyQfmxJzhzSelect> jzhztjList3 = baseMapper.sscxby(filter, "2");
        if (!jzhztjList1.isEmpty())
            lists.addAll(jzhztjList1);
        if (!jzhztjList2.isEmpty())
            lists.addAll(jzhztjList2);
        if (!jzhztjList3.isEmpty())
            lists.addAll(jzhztjList3);
        List<JzhztjDto> dataList = new ArrayList<>();
        if (!lists.isEmpty()) {
            dataList = this.jsjzhzmx(lists);
        }
        return dataList;
    }

    private List<JzhztjDto> jsjzhzmx(List<YyQfmxJzhzSelect> qfmxList) {
        List<JzhztjDto> details = new ArrayList<>();
        Map<String, List<YyQfmxJzhzSelect>> ysxzMaps = qfmxList.stream()
                .collect(Collectors.groupingBy(YyQfmxJzhzSelect::getSjmc));
        List<Jzhztjmx> sflist = new ArrayList<>();
        List<Jzhztjmx> wsflist = new ArrayList<>();
        List<Jzhztjmx> szyflist = new ArrayList<>();
        ysxzMaps.forEach((key, value) -> {
            BigDecimal sf = value.stream().filter(o -> ObjUtil.isNotNull(o.getSf()))
                    .map(YyQfmxJzhzSelect::getSf)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal sfsl = value.stream().filter(o -> ObjUtil.isNotNull(o.getSfsl()))
                    .map(YyQfmxJzhzSelect::getSfsl)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer sfhs = value.stream().filter(o -> ObjUtil.isNotNull(o.getSfhs()))
                    .map(YyQfmxJzhzSelect::getSfhs)
                    .reduce(0, Integer::sum);
            List<BigDecimal> sjList = value.stream().filter(o -> ObjUtil.isNotNull(o.getSj()) && o.getSj().compareTo(BigDecimal.ZERO) != 0)
                    .map(YyQfmxJzhzSelect::getSj)
                    .distinct().sorted(Comparator.comparing(BigDecimal::doubleValue))
                    .collect(Collectors.toList());
            BigDecimal sj = sjList.size() > 0 ? sjList.get(0) : BigDecimal.ZERO;
            if (sf.compareTo(BigDecimal.ZERO) != 0) {
                Jzhztjmx sfmx = this.getJzhztjmx(key, sfhs, "吨", sfsl, sj, sf);
                sflist.add(sfmx);
            }

            BigDecimal wsf = value.stream().filter(o -> ObjUtil.isNotNull(o.getWsf()))
                    .map(YyQfmxJzhzSelect::getWsf)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal wsfsl = value.stream().filter(o -> ObjUtil.isNotNull(o.getWsfsl()))
                    .map(YyQfmxJzhzSelect::getWsfsl)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer wsfhs = value.stream().filter(o -> ObjUtil.isNotNull(o.getWsfhs()))
                    .map(YyQfmxJzhzSelect::getWsfhs)
                    .reduce(0, Integer::sum);
            List<BigDecimal> wsfdjList = value.stream().filter(o -> ObjUtil.isNotNull(o.getWsf()) && o.getWsf().compareTo(BigDecimal.ZERO) != 0)
                    .map(YyQfmxJzhzSelect::getWsf)
                    .distinct().sorted(Comparator.comparing(BigDecimal::doubleValue))
                    .collect(Collectors.toList());
            BigDecimal wsfdj = wsfdjList.size() > 0 ? wsfdjList.get(0) : BigDecimal.ZERO;
            if (wsf.compareTo(BigDecimal.ZERO) != 0) {
                Jzhztjmx wsfmx = this.getJzhztjmx(key, wsfhs, "吨", wsfsl, wsfdj, wsf);
                wsflist.add(wsfmx);
            }

            BigDecimal syzf = value.stream().filter(o -> ObjUtil.isNotNull(o.getSzyf()))
                    .map(YyQfmxJzhzSelect::getSzyf)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal syzfsl = value.stream().filter(o -> ObjUtil.isNotNull(o.getSzyfsl()))
                    .map(YyQfmxJzhzSelect::getSzyfsl)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer syzfhs = value.stream().filter(o -> ObjUtil.isNotNull(o.getSzyfhs()))
                    .map(YyQfmxJzhzSelect::getSzyfhs)
                    .reduce(0, Integer::sum);
            List<BigDecimal> szyfdjList = value.stream().filter(o -> ObjUtil.isNotNull(o.getSzyf()) && o.getSzyf().compareTo(BigDecimal.ZERO) != 0)
                    .map(YyQfmxJzhzSelect::getSzyf)
                    .distinct().sorted(Comparator.comparing(BigDecimal::doubleValue))
                    .collect(Collectors.toList());
            BigDecimal szyfdj = szyfdjList.size() > 0 ? szyfdjList.get(0) : BigDecimal.ZERO;
            if (syzf.compareTo(BigDecimal.ZERO) != 0) {
                Jzhztjmx szyfmx = this.getJzhztjmx(key, syzfhs, "吨", syzfsl, szyfdj, syzf);
                szyflist.add(szyfmx);
            }
        });
        BigDecimal ecjyf = qfmxList.stream().filter(o -> ObjUtil.isNotNull(o.getEcjyf()))
                .map(YyQfmxJzhzSelect::getEcjyf)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fjf = qfmxList.stream().filter(o -> ObjUtil.isNotNull(o.getFjf()))
                .map(YyQfmxJzhzSelect::getFjf)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal xfsf = qfmxList.stream().filter(o -> ObjUtil.isNotNull(o.getXfsf()))
                .map(YyQfmxJzhzSelect::getXfsf)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        Integer ecjyfhs = qfmxList.stream().filter(o -> ObjUtil.isNotNull(o.getEcjyfhs()))
                .map(YyQfmxJzhzSelect::getEcjyfhs)
                .reduce(0, Integer::sum);
        Integer fjfhs = qfmxList.stream().filter(o -> ObjUtil.isNotNull(o.getFjfhs()))
                .map(YyQfmxJzhzSelect::getFjfhs)
                .reduce(0, Integer::sum);
        Integer xfsfhs = qfmxList.stream().filter(o -> ObjUtil.isNotNull(o.getXfsfhs()))
                .map(YyQfmxJzhzSelect::getXfsfhs)
                .reduce(0, Integer::sum);
        if (ecjyf.compareTo(BigDecimal.ZERO) != 0) {
            Jzhztjmx ecjyfmx = this.getJzhztjmx("二次加压费", ecjyfhs, "吨", BigDecimal.ZERO, BigDecimal.ZERO, ecjyf);
            sflist.add(ecjyfmx);
        }
        if (fjf.compareTo(BigDecimal.ZERO) != 0) {
            Jzhztjmx fjfmx = this.getJzhztjmx("附加费", fjfhs, "吨", BigDecimal.ZERO, BigDecimal.ZERO, fjf);
            sflist.add(fjfmx);
        }
        if (xfsf.compareTo(BigDecimal.ZERO) != 0) {
            Jzhztjmx xfsfmx = this.getJzhztjmx("消防栓费", xfsfhs, "吨", BigDecimal.ZERO, BigDecimal.ZERO, xfsf);
            sflist.add(xfsfmx);
        }

        if (!sflist.isEmpty()) {
            details.add(this.getJzhztjDto(1, sflist));
        }
        if (!wsflist.isEmpty()) {
            details.add(this.getJzhztjDto(2, wsflist));
        }
        if (!szyflist.isEmpty()) {
            details.add(this.getJzhztjDto(3, szyflist));
        }
        return details;
    }

    private Jzhztjmx getJzhztjmx(String xm, Integer hs, String dw, BigDecimal sl, BigDecimal dj, BigDecimal je) {
        Jzhztjmx mx = new Jzhztjmx();
        mx.setXm(xm);
        mx.setHs(hs);
        mx.setDw(dw);
        mx.setSl(sl);
        mx.setDj(dj);
        mx.setJe(je);
        return mx;
    }

    private JzhztjDto getJzhztjDto(Integer type, List<Jzhztjmx> qfmxList) {
        JzhztjDto jzhztjDto = new JzhztjDto();
        jzhztjDto.setType(type);
        jzhztjDto.setDetails(qfmxList);
        jzhztjDto.setHjhs(qfmxList.stream().mapToInt(Jzhztjmx::getHs).sum());
        jzhztjDto.setHjsl(qfmxList.stream().map(Jzhztjmx::getSl).reduce(BigDecimal.ZERO, BigDecimal::add));
        jzhztjDto.setHjje(qfmxList.stream().map(Jzhztjmx::getJe).reduce(BigDecimal.ZERO, BigDecimal::add));
        return jzhztjDto;
    }

    private BigDecimal checkNumber(BigDecimal number) {
        if (ObjectUtil.isNotNull(number)) {
            return number;
        }
        return BigDecimal.ZERO;
    }

    @Override
    public PageResult<PjmxSelectVo> getPjmxPage(PageDto pageDto, YySspjxxFilter filter) {
        PageDto<PjmxSelectVo> page = this.baseMapper.getPjmxPage(pageDto, filter);
        return page.toVo();
    }


    public List<YySspjxxSelect> getDsftj(YySspjxxFilter filter) {
        List<YySspjxxSelect> list = this.baseMapper.getDsftj(filter);
        Map<String, String> sjMap = getSjMap();
        list.forEach(e -> setYslx(e, sjMap));
        return list;
    }

    public List<DsfhzSelect> getDsfHztj(YySspjxxFilter filter) {
        List<DsfhzSelect> list = this.baseMapper.getDsfHztj(filter);
        return list;
    }

    @Override
    public List<YySspjxxDailyStat2> dailyStat2(YySspjxxStatFilter filter) {
        List<YySspjxxDailyStat2> list = this.baseMapper.dailyStat2(filter);
        if (!list.isEmpty()) {
            Integer sfbs = list.stream().map(e -> e.getSfbs()).filter(e -> e != null).reduce(0, (x, y) -> x + y);
            Integer tfbs = list.stream().map(e -> e.getTfbs()).filter(e -> e != null).reduce(0, (x, y) -> x + y);
            BigDecimal yssl = list.stream().map(e -> e.getYssl()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yssf = list.stream().map(e -> e.getYssf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yswsf = list.stream().map(e -> e.getYswsf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yslfj = list.stream().map(e -> e.getYsljf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal ysszyf = list.stream().map(e -> e.getYsszyf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal bckj = list.stream().map(e -> e.getBckj()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal zyc = list.stream().map(e -> e.getZyc()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal bcyc = list.stream().map(e -> e.getBcyc()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal fsszje = list.stream().map(e -> e.getFsszje()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal sszje = list.stream().map(e -> e.getSszje()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));

            BigDecimal ecjyf = list.stream().map(e -> e.getYsecjyf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal fjf = list.stream().map(e -> e.getYsfjf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal qtf = list.stream().map(e -> e.getYsqt()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));

            list.add(new YySspjxxDailyStat2("合计", sfbs, tfbs, yssl, yssf, yswsf, yslfj, ysszyf, bckj, zyc, bcyc, fsszje, sszje, ecjyf, fjf, qtf));
        }
        return list;
    }

    @Override
    public List<YySspjxxZhSfStat> zhSfStat(YySspjxxStatFilter filter) {
        List<YySspjxxZhSfStat> list = this.baseMapper.zhSfStat(filter);
        if (!list.isEmpty()) {
            Integer pjs = list.stream().map(e -> e.getPjs()).filter(e -> e != null).reduce(0, (x, y) -> x + y);
            BigDecimal yssl = list.stream().map(e -> e.getYssl()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yssf = list.stream().map(e -> e.getYssf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yswsf = list.stream().map(e -> e.getYswsf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal yslfj = list.stream().map(e -> e.getYsljf()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal bckj = list.stream().map(e -> e.getBckj()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal bcyc = list.stream().map(e -> e.getBcyc()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal zyc = list.stream().map(e -> e.getZyc()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal sszje = list.stream().map(e -> e.getSszje()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal zsl = list.stream().map(e -> e.getZsl()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            BigDecimal ssznj = list.stream().map(e -> e.getSsznj()).filter(e -> e != null).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
            list.add(new YySspjxxZhSfStat("合计", pjs, yssl, yssf, yswsf, yslfj, bckj, bcyc, zyc, ssznj, zsl, sszje));
        }
        return list;
    }

    @Override
    public List<YySspjxxMonthlyStat> monthlyStat(YySspjxxStatFilter filter) {
        List<YySjStat> list0 = this.baseMapper.sjStat(filter, "", "ysyf,");
        List<YySjStat> list1 = this.baseMapper.sjStat(filter, "1", "ysyf,");
        List<YySjStat> list2 = this.baseMapper.sjStat(filter, "2", "ysyf,");
        //List<YySjStat> list3 = this.baseMapper.sjStat(filter, "3", "ysyf,");
        //BigDecimal znj = this.baseMapper.qtStat(filter, "znj");//违约金
        BigDecimal yff = this.baseMapper.qtStat(filter, "yff");//预交水费
        //BigDecimal yckj = this.baseMapper.qtStat(filter, "yckj");//预存扣款金额
        BigDecimal bc = this.baseMapper.qtStat(filter, "sfbc");//水费补差
        List<YySjStat> list = new ArrayList<>();
        if ((long) list0.size() != 0) {
            list.addAll(list0);
        }
        if ((long) list1.size() != 0) {
            list.addAll(list1);
        }

        if ((long) list2.size() != 0) {
            list.addAll(list2);
        }
//        if ((long) list3.size() != 0) {
//            list.addAll(list3);
//        }

        Map<String, List<YySjStat>> cwrqMap = list.stream()
                .filter(e -> StringUtil.isNotEmpty(e.getYsyf()))
                // 显式指定类型 + 倒序排序
                //.sorted(Comparator.comparingInt((YySjStat e) -> Integer.parseInt(e.getYsyf())).reversed())
                .collect(Collectors.groupingBy(YySjStat::getYsyf, LinkedHashMap::new, Collectors.toList()));

        //阶梯费用 (重新计算 污水费 垃圾费 只取一行sum 后面不计算)
        List<YySjStat> list4 = this.baseMapper.sjjtStat(filter, "1", "cwrq,");
        List<YySjStat> list5 = this.baseMapper.sjjtStat(filter, "2", "cwrq,");
        List<YySjStat> list6 = this.baseMapper.sjjtStat(filter, "3", "cwrq,");
        List<YySjStat> jtlist = new ArrayList<>();
        if ((long) list4.size() != 0) {
            jtlist.addAll(list4);
        }
        if ((long) list5.size() != 0) {
            jtlist.addAll(list5);
        }
        if ((long) list6.size() != 0) {
            jtlist.addAll(list6);
        }

        Map<String, List<YySjStat>> cwrqjtMap = jtlist.stream()
                .filter(e -> StringUtil.isNotEmpty(e.getCwrq()))
                // 显式指定类型 + 倒序排序
                //.sorted(Comparator.comparingInt((YySjStat e) -> Integer.parseInt(e.getCwrq())).reversed())
                .collect(Collectors.groupingBy(YySjStat::getCwrq, LinkedHashMap::new, Collectors.toList()));

        List<YySspjxxMonthlyStat> results = new ArrayList<>();
        List<BmSj> sjList = getSjMap1();

        // 用水月份/财务日期倒序排序
        List<String> cwrqlist = new ArrayList<>();
        cwrqlist.addAll(list.stream().map(e -> e.getYsyf()).distinct().collect(Collectors.toList()));
        cwrqlist.addAll(jtlist.stream().map(e -> e.getCwrq()).distinct().collect(Collectors.toList()));
        cwrqlist = cwrqlist.stream().distinct()
                .sorted(Comparator.comparingInt((String e) -> Integer.parseInt(e)).reversed())
                .collect(Collectors.toList());

        //月份循环
        cwrqlist.forEach(key -> {
            List<YySspjxxMonthlyStat> result = new ArrayList<>();

            Map<String, List<YySjStat>> jtSjmxMap = Optional.ofNullable(cwrqjtMap)
                    .map(m -> m.getOrDefault(key, new ArrayList<>()))
                    .orElse(new ArrayList<>()).stream()
                    .filter(e -> StringUtil.isNotEmpty(e.getSjbm()))
                    .collect(Collectors.groupingBy(x -> x.getSjbm()));

            List<YySjStat> value = Optional.ofNullable(cwrqMap)
                    .map(m -> m.getOrDefault(key, new ArrayList<>()))
                    .orElse(new ArrayList<>());
            Map<String, List<YySjStat>> sjmxMap = value.stream()
                    .filter(e -> StringUtil.isNotEmpty(e.getSjbm()))
                    .collect(Collectors.groupingBy(x -> x.getSjbm()));

            for (BmSj bmsj : sjList) {
                List<YySjStat> sjmxs = sjmxMap.getOrDefault(bmsj.getCode(), new ArrayList<>());

                BigDecimal sl = sjmxs.stream().map(YySjStat::getSl).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal sf = sjmxs.stream().map(YySjStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal wsf = sjmxs.stream().map(YySjStat::getWsf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ljf = sjmxs.stream().map(YySjStat::getLjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal szyf = sjmxs.stream().map(YySjStat::getSzyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal jt1sf = sjmxs.stream().map(YySjStat::getJt1sf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal znj = sjmxs.stream().map(YySjStat::getZnj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                // 二次加压费、附加费、消防栓费
                BigDecimal ecjyfs = sjmxs.stream().map(YySjStat::getEcjyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal fjfs = sjmxs.stream().map(YySjStat::getFjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal qtfs = sjmxs.stream().map(YySjStat::getQtf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

                BigDecimal zje = sf.add(wsf).add(ljf).add(szyf).add(znj).add(ecjyfs).add(fjfs).add(qtfs);
                if (zje.compareTo(BigDecimal.ZERO) != 0) {
                    BigDecimal hjsj = bmsj.getSj().add(bmsj.getWsfdj()).add(bmsj.getSzyfdj());
                    if (bmsj.getJtbz().equals("0")) {
                        // 非阶梯
                        YySspjxxMonthlyStat monthlyStat = new YySspjxxMonthlyStat(key, bmsj.getName(), bmsj.getSj(), hjsj, sl, sf, wsf, ljf, szyf, znj, zje, ecjyfs, fjfs, qtfs);
                        result.add(monthlyStat);
                    } else {
                        //只存在一种阶梯 直接保存不用重新分组查询
                        if (jt1sf.equals(sf)) {
                            YySspjxxMonthlyStat monthlyStat = new YySspjxxMonthlyStat(key, bmsj.getName(), bmsj.getJt1Sj(), hjsj, sl, sf, wsf, ljf, szyf, znj, zje, ecjyfs, fjfs, qtfs);
                            result.add(monthlyStat);
                        } else {
                            // 多种阶梯
                            List<YySjStat> jtsjmxlist = jtSjmxMap.getOrDefault(bmsj.getCode(), new ArrayList<>());
                            Map<BigDecimal, List<YySjStat>> jtsjmxsMap = jtsjmxlist.stream()
                                    .filter(e -> StringUtil.isNotEmpty(e.getSjbm()))
                                    .collect(Collectors.groupingBy(YySjStat::getSj));

                            for (List<YySjStat> yySjStats : jtsjmxsMap.values()) {
                                BigDecimal jtsl = yySjStats.stream().map(YySjStat::getSl).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal jtsf = yySjStats.stream().map(YySjStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal jtwsf = yySjStats.stream().map(YySjStat::getWsf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal jtljf = yySjStats.stream().map(YySjStat::getLjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal jtszyf = yySjStats.stream().map(YySjStat::getSzyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal jtznj = yySjStats.stream().map(YySjStat::getZnj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

                                // 二次加压费、附加费、消防栓费
                                BigDecimal ecjyfss = yySjStats.stream().map(YySjStat::getEcjyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal fjfss = yySjStats.stream().map(YySjStat::getFjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                                BigDecimal qtfss = yySjStats.stream().map(YySjStat::getQtf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

                                BigDecimal jthjysje = jtsf.add(jtwsf).add(jtljf).add(jtszyf).add(jtznj).add(ecjyfss).add(fjfss).add(qtfss);
                                if (jthjysje.compareTo(BigDecimal.ZERO) != 0) {
                                    BigDecimal jthjsj = yySjStats.get(0).getSj().add(bmsj.getWsfdj()).add(bmsj.getSzyfdj());
                                    YySspjxxMonthlyStat monthlyStat = new YySspjxxMonthlyStat(key, bmsj.getName(), yySjStats.get(0).getSj(), jthjsj, jtsl, jtsf, jtwsf, jtljf, jtszyf, jtznj, jthjysje, ecjyfss, fjfss, qtfss);
                                    result.add(monthlyStat);
                                }
                            }
                        }
                    }
                }
            }
            //小计
            if (!result.isEmpty()) {
                BigDecimal sl = result.stream().map(YySspjxxMonthlyStat::getSl).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal sf = result.stream().map(YySspjxxMonthlyStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal wsf = result.stream().map(YySspjxxMonthlyStat::getWsf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal ljf = result.stream().map(YySspjxxMonthlyStat::getLjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal szyf = result.stream().map(YySspjxxMonthlyStat::getSzyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal hj = result.stream().map(YySspjxxMonthlyStat::getHj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal znj = result.stream().map(YySspjxxMonthlyStat::getZnj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                // 二次加压费、附加费、消防栓费
                BigDecimal ecjyfs = result.stream().map(YySspjxxMonthlyStat::getEcjyfs).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal fjfs = result.stream().map(YySspjxxMonthlyStat::getFjfs).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal qtfs = result.stream().map(YySspjxxMonthlyStat::getQtfs).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                result.add(new YySspjxxMonthlyStat(key, "小计", null, null, sl, sf, wsf, ljf, szyf, znj, hj, ecjyfs, fjfs, qtfs));
            }
            results.addAll(result);
        });
//        if (znj.compareTo(BigDecimal.ZERO) != 0) {
//            results.add(new YySspjxxMonthlyStat(null, "违约金", BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, znj));
//        }
        if (yff.compareTo(BigDecimal.ZERO) != 0) {
            //results.add(new YySspjxxMonthlyStat(null, "预交水费", BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, yff));
        }

        if (bc.compareTo(BigDecimal.ZERO) != 0) {
            results.add(new YySspjxxMonthlyStat(null, "水费补差", BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, bc));
        }

        BigDecimal hjsl = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getSl).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjsf = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getSf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjwsf = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getWsf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjljf = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getLjf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjszyf = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getSzyf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjznj = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getZnj).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal zhj = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计") && !e.getYsxm().equals("预交水费")).map(YySspjxxMonthlyStat::getHj).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 二次加压、附加费、其他费（消防栓）
        BigDecimal ecjyfs = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getEcjyfs).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal fjfs = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getFjfs).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal qtfs = results.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getQtfs).reduce(BigDecimal.ZERO, BigDecimal::add);

        if (zhj.compareTo(BigDecimal.ZERO) != 0) {
            results.add(new YySspjxxMonthlyStat(null, "合计", null, null, hjsl, hjsf, hjwsf, hjljf, hjszyf, hjznj, zhj, ecjyfs, fjfs, qtfs));
        }

        return results;
    }

    @Override
    public List<YySspjxxMonthlyStat> monthlyStatSummary(YySspjxxStatFilter filter) {
        List<YySjStat> list0 = this.baseMapper.sjStat(filter, "", "");
        List<YySjStat> list1 = this.baseMapper.sjStat(filter, "1", "");
        List<YySjStat> list2 = this.baseMapper.sjStat(filter, "2", "");
        //List<YySjStat> list3 = this.baseMapper.sjStat(filter, "3", "");
        //BigDecimal znj = this.baseMapper.qtStat(filter, "znj");//违约金
        BigDecimal yff = this.baseMapper.qtStat(filter, "yff");//预交水费
        //BigDecimal yckj = this.baseMapper.qtStat(filter, "yckj");//预存扣款金额
        BigDecimal bc = this.baseMapper.qtStat(filter, "sfbc");//水费补差
        List<YySjStat> list = new ArrayList<>();
        if ((long) list0.size() != 0) {
            list.addAll(list0);
        }
        if ((long) list1.size() != 0) {
            list.addAll(list1);
        }
        if ((long) list2.size() != 0) {
            list.addAll(list2);
        }
//        if ((long) list3.size() != 0) {
//            list.addAll(list3);
//        }

        List<BmSj> sjList = getSjMap1();

        List<YySspjxxMonthlyStat> result = new ArrayList<>();
        Map<String, List<YySjStat>> sjmxMap = list.stream()
                .filter(e -> StringUtil.isNotEmpty(e.getSjbm()))
                .collect(Collectors.groupingBy(x -> x.getSjbm()));
        for (BmSj bmsj : sjList) {
            List<YySjStat> sjmxs = sjmxMap.getOrDefault(bmsj.getCode(), new ArrayList<>());
            BigDecimal sl = sjmxs.stream().map(YySjStat::getSl).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal sf = sjmxs.stream().map(YySjStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal wsf = sjmxs.stream().map(YySjStat::getWsf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal ljf = sjmxs.stream().map(YySjStat::getLjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal szyf = sjmxs.stream().map(YySjStat::getSzyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal znj = sjmxs.stream().map(YySjStat::getZnj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            //
            BigDecimal ecjyf = sjmxs.stream().map(YySjStat::getEcjyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal fjf = sjmxs.stream().map(YySjStat::getFjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal qtf = sjmxs.stream().map(YySjStat::getQtf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);


            if (sf.add(wsf).add(ljf).add(szyf).compareTo(BigDecimal.ZERO) != 0) {
                if (bmsj.getJtbz().equals("0")) {
                    BigDecimal hjsj = bmsj.getSj().add(bmsj.getWsfdj()).add(bmsj.getSzyfdj());
                    result.add(new YySspjxxMonthlyStat(null, bmsj.getName(), bmsj.getSj(), hjsj, sl, sf, wsf, ljf, szyf, znj, sf.add(wsf).add(ljf).add(szyf).add(znj).add(ecjyf).add(fjf).add(qtf), ecjyf, fjf, qtf));
                } else {
                    //阶梯费用 (重新计算 污水费 垃圾费 只取一行sum 后面不计算)
                    List<YySjStat> list4 = this.baseMapper.sjjtStat(filter, "1", "");
                    List<YySjStat> list5 = this.baseMapper.sjjtStat(filter, "2", "");
                    List<YySjStat> list6 = this.baseMapper.sjjtStat(filter, "3", "");
                    List<YySjStat> jtlist = new ArrayList<>();

                    if ((long) list4.size() != 0) {
                        jtlist.addAll(list4);
                    }
                    if ((long) list5.size() != 0) {
                        jtlist.addAll(list5);
                    }
                    if ((long) list6.size() != 0) {
                        jtlist.addAll(list6);
                    }

                    Map<BigDecimal, List<YySjStat>> jtsjmxMap = jtlist.stream()
                            .filter(e -> StringUtil.isNotEmpty(e.getSjbm()))
                            .collect(Collectors.groupingBy(x -> x.getSj()));
                    for (List<YySjStat> yySjStats : jtsjmxMap.values()) {
                        BigDecimal jtsl = yySjStats.stream().map(YySjStat::getSl).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal jtsf = yySjStats.stream().map(YySjStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal jtwsf = yySjStats.stream().map(YySjStat::getWsf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal jtljf = yySjStats.stream().map(YySjStat::getLjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal jtszyf = yySjStats.stream().map(YySjStat::getSzyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal jtznj = yySjStats.stream().map(YySjStat::getZnj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                        if (jtsf.add(jtwsf).add(jtljf).add(jtszyf).compareTo(BigDecimal.ZERO) != 0) {
                            BigDecimal jthjsj = yySjStats.get(0).getSj().add(bmsj.getWsfdj()).add(bmsj.getSzyfdj());
                            result.add(new YySspjxxMonthlyStat(null, bmsj.getName(), yySjStats.get(0).getSj(), jthjsj, jtsl, jtsf, jtwsf, jtljf, jtszyf, jtznj, jtsf.add(jtwsf).add(jtljf).add(jtszyf).add(jtznj), ecjyf, fjf, qtf));
                        }
                    }
                }
            }
        }
        //小计
        if (!result.isEmpty()) {
            BigDecimal sl = result.stream().map(YySspjxxMonthlyStat::getSl).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal sf = result.stream().map(YySspjxxMonthlyStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal wsf = result.stream().map(YySspjxxMonthlyStat::getWsf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal ljf = result.stream().map(YySspjxxMonthlyStat::getLjf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal szyf = result.stream().map(YySspjxxMonthlyStat::getSzyf).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal hj = result.stream().map(YySspjxxMonthlyStat::getHj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal znj = result.stream().map(YySspjxxMonthlyStat::getZnj).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal ecjyf = result.stream().map(YySspjxxMonthlyStat::getEcjyfs).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal fjf = result.stream().map(YySspjxxMonthlyStat::getFjfs).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal qtfs = result.stream().map(YySspjxxMonthlyStat::getQtfs).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

            result.add(new YySspjxxMonthlyStat(null, "小计", null, null, sl, sf, wsf, ljf, szyf, znj, hj, ecjyf, fjf, qtfs));
        }

        if (yff.compareTo(BigDecimal.ZERO) != 0) {
            //result.add(new YySspjxxMonthlyStat(null, "预交水费", BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, yff));
        }
        if (bc.compareTo(BigDecimal.ZERO) != 0) {
            result.add(new YySspjxxMonthlyStat(null, "水费补差", BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, bc));
        }

        BigDecimal hjsl = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getSl).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjsf = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getSf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjwsf = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getWsf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjljf = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getLjf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjszyf = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getSzyf).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjznj = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getZnj).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal hjecjyf = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getEcjyfs).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjfjf = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getFjfs).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal hjqtfs = result.stream().filter(Objects::nonNull).filter(e -> !e.getYsxm().equals("小计")).map(YySspjxxMonthlyStat::getQtfs).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal zhj = result.stream().filter(Objects::nonNull)
                .filter(e -> !e.getYsxm().equals("小计") && !e.getYsxm().equals("预交水费"))
                .map(YySspjxxMonthlyStat::getHj).reduce(BigDecimal.ZERO, BigDecimal::add);

        if (zhj.compareTo(BigDecimal.ZERO) != 0) {
            result.add(new YySspjxxMonthlyStat(null, "合计", null, null, hjsl,
                    hjsf, hjwsf, hjljf, hjszyf, hjznj, zhj, hjecjyf, hjfjf, hjqtfs));
        }

        return result;
    }

    @Override
    public YyStat stat(YySspjxxStatFilter filter) {
        return this.baseMapper.stat(filter);
    }

    private YySspjxxSelect setYslx(YySspjxxSelect e, Map<String, String> sjMap) {
        if (e == null) return null;
        e.setYsxz(e.getSjbm() == null ? "预付费" : sjMap.get(e.getSjbm()));
        return e;
    }

    private YySspjxxDailyStat.SrxmStat getZj(Map<String, String> fffsMap, List<YySspjxxDailyStat.SrxmStat> srxmStats) {
        Map<String, BigDecimal> zjSlMap = new LinkedHashMap<>();
        Map<String, BigDecimal> zjJeMap = new LinkedHashMap<>();
        srxmStats.forEach(e -> {
            e.getFffsStats().forEach(f -> {
                BigDecimal sumSl = zjSlMap.getOrDefault(f.getFffsmc(), BigDecimal.ZERO);
                zjSlMap.put(f.getFffsmc(), sumSl.add(f.getSl()));
                BigDecimal sumJe = zjJeMap.getOrDefault(f.getFffsmc(), BigDecimal.ZERO);
                zjJeMap.put(f.getFffsmc(), sumJe.add(f.getJe()));
            });
        });

        List<YySspjxxDailyStat.FffsStat> zjFffsStats = new ArrayList<>();
        fffsMap.forEach((fffs, fffsmc) -> {
            BigDecimal sl = zjSlMap.getOrDefault(fffsmc, BigDecimal.ZERO);
            BigDecimal je = zjJeMap.getOrDefault(fffsmc, BigDecimal.ZERO);
            zjFffsStats.add(new YySspjxxDailyStat.FffsStat(fffsmc, sl, je));
        });

        BigDecimal slTotal = zjFffsStats.stream().map(e -> e.getSl()).reduce(BigDecimal.ZERO, (item, total) -> total.add(item));
        BigDecimal jeTotal = zjFffsStats.stream().map(e -> e.getJe()).reduce(BigDecimal.ZERO, (item, total) -> total.add(item));
        zjFffsStats.add(new YySspjxxDailyStat.FffsStat("合计", slTotal, jeTotal));

        return new YySspjxxDailyStat.SrxmStat("总计", zjFffsStats);
    }

    private List<YySspjxxDailyStat.SrxmStat> getSfsr(YySspjxxDailyStatFilter filter, Map<String, String> fffsMap) {
        List<YySjFffsStat> list = new ArrayList<>();

        List<YySjFffsStat> list0 = this.baseMapper.sjSffsStat(filter, "");
        List<YySjFffsStat> list1 = this.baseMapper.sjSffsStat(filter, "1");
        List<YySjFffsStat> list2 = this.baseMapper.sjSffsStat(filter, "2");
        //List<YySjFffsStat> list3 = this.baseMapper.sjSffsStat(filter, "3");
        if (CollectionUtil.isNotEmpty(list0)) {
            list.addAll(list0);
        }
        if (CollectionUtil.isNotEmpty(list1)) {
            list.addAll(list1);
        }
        if (CollectionUtil.isNotEmpty(list2)) {
            list.addAll(list2);
        }
//        if (CollectionUtil.isNotEmpty(list3)) {
//            list.addAll(list3);
//        }

//        BigDecimal d=list.stream().map(YySjFffsStat::getSf).filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);
//        log.info(d.toString());

        Map<String, List<YySjFffsStat>> sjStatMap = list.stream().map(item -> {
                    item.setSjbm(Optional.ofNullable(item.getSjbm()).orElse("-999"));
                    return item;
                }).collect(Collectors.toList()).stream()
                .filter(e -> StrUtil.isNotEmpty(e.getSjbm()))
                .filter(e -> e.getSf().compareTo(BigDecimal.ZERO) != 0)
                .collect(Collectors.groupingBy(YySjFffsStat::getSjbm));

        Map<String, String> sjMap = getSjMap();
        List<YySspjxxDailyStat.SrxmStat> sfsr = new ArrayList<>();

        for (Map.Entry<String, List<YySjFffsStat>> entry : sjStatMap.entrySet()) {
            String sjbm = entry.getKey();
            List<YySjFffsStat> tjlist = entry.getValue();
            String sjmc = sjMap.get(sjbm);

            Map<String, List<YySjFffsStat>> fffstjMap = tjlist.stream().collect(Collectors.groupingBy(YySjFffsStat::getFffs));
            List<YySspjxxDailyStat.FffsStat> fffsStats = YySspjxxDailyStat.FffsStat.buildByFffstjMap(fffstjMap, fffsMap);

            sfsr.add(new YySspjxxDailyStat.SrxmStat(sjmc, fffsStats));
        }

        addHjXj(fffsMap, sfsr);
        return sfsr;
    }


    private List<YySjFffsStat> ConvertListFffs(List<YySjFffsStat> lst) {

        List<YySjFffsStat> newlst = lst.stream().map(m -> {
            YySjFffsStat yystate = new YySjFffsStat();
            yystate = m;
            yystate.setFffs(m.getFffs().replace("1", "01"));
            return yystate;
        }).collect(Collectors.toList());
        return newlst;
    }


    private List<YyFjFffsStat> ConvertListFffs2(List<YyFjFffsStat> lst) {

        List<YyFjFffsStat> newlst = lst.stream().map(m -> {
            YyFjFffsStat yystate = new YyFjFffsStat();
            yystate = m;
            switch (m.getFffs()) {
                case "1":
                    yystate.setFffs("01");
                    break;
                case "2":
                    yystate.setFffs("02");
                    break;
                case "3":
                    yystate.setFffs("03");
                    break;
                case "4":
                    yystate.setFffs("04");
                    break;
                case "5":
                    yystate.setFffs("05");
                    break;
            }
            ;
            return yystate;
        }).collect(Collectors.toList());
        return newlst;
    }


    private BigDecimal add(BigDecimal v1, BigDecimal v2) {
        if (v1 == null || v2 == null) return null;
        return v1.add(v2);
    }

    /***
     * 小计
     */
    private void addHjXj(Map<String, String> fffsMap, List<YySspjxxDailyStat.SrxmStat> srxmStats) {
        Map<String, BigDecimal> xjSlMap = new LinkedHashMap<>();
        Map<String, BigDecimal> xjJeMap = new LinkedHashMap<>();

        srxmStats.forEach(e -> {
            e.getFffsStats().forEach(f -> {
                BigDecimal sumSl = xjSlMap.getOrDefault(f.getFffsmc(), BigDecimal.ZERO);
                // xjSlMap.put(f.getFffsmc(), sumSl.add(f.getSl()));
                BigDecimal sumJe = xjJeMap.getOrDefault(f.getFffsmc(), BigDecimal.ZERO);
                //冲预缴扣减
                if (!StringUtil.isEmpty(e.getSrxm()) && e.getSrxm().equals(SysConstant.BBTJ_SFRJ_CYJSF)) {
                    xjJeMap.put(f.getFffsmc(), sumJe.subtract(f.getJe()));
                    xjSlMap.put(f.getFffsmc(), sumSl.subtract(f.getSl()));
                } else {
                    xjJeMap.put(f.getFffsmc(), sumJe.add(f.getJe()));
                    xjSlMap.put(f.getFffsmc(), sumSl.add(f.getSl()));
                }
            });
        });

        List<YySspjxxDailyStat.FffsStat> xjFffsStats = new ArrayList<>();
        fffsMap.forEach((fffs, fffsmc) -> {
            BigDecimal sl = xjSlMap.getOrDefault(fffsmc, BigDecimal.ZERO);
            BigDecimal je = xjJeMap.getOrDefault(fffsmc, BigDecimal.ZERO);
            xjFffsStats.add(new YySspjxxDailyStat.FffsStat(fffsmc, sl, je));
        });

        srxmStats.add(new YySspjxxDailyStat.SrxmStat("小计", xjFffsStats));
    }

    private List<YySspjxxDailyStat.SrxmStat> getYjCyjmx(YySspjxxDailyStatFilter filter, Map<String, String> fffsMap) {
        List<YySspjxxDailyStat.SrxmStat> yjcyj = new ArrayList<>();

        // 账户充值(预交)
        List<YjcyjFffsStat> yjjelist = baseMapper.getYjje(filter);
        YySspjxxDailyStat.SrxmStat yjjeStat = getYjjeStat(yjjelist, fffsMap);
        yjcyj.add(yjjeStat);

        // 账户扣减(冲预交)
        List<YjcyjFffsStat> cyjjelist = baseMapper.getCyjje(filter);
        YySspjxxDailyStat.SrxmStat cyjjeStat = getCyjjeStat(cyjjelist, fffsMap);
        yjcyj.add(cyjjeStat);

        return yjcyj;
    }

    private YySspjxxDailyStat.SrxmStat getCyjjeStat(List<YjcyjFffsStat> cyjjelist, Map<String, String> fffsMap) {
        YySspjxxDailyStat.SrxmStat srxmStat = new YySspjxxDailyStat.SrxmStat();
        srxmStat.setSrxm(SysConstant.BBTJ_SFRJ_CYJSF);

        List<YySspjxxDailyStat.FffsStat> fffsStats = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(cyjjelist)) {
            Map<String, List<YjcyjFffsStat>> fffsYjMap = cyjjelist.stream().collect(Collectors.groupingBy(YjcyjFffsStat::getFffs));
            fffsStats = YySspjxxDailyStat.FffsStat.buildByFffsCyjMap(fffsYjMap, fffsMap);
        }

        srxmStat.setFffsStats(fffsStats);
        return srxmStat;
    }


    private YySspjxxDailyStat.SrxmStat getYjjeStat(List<YjcyjFffsStat> yjjelist, Map<String, String> fffsMap) {
        YySspjxxDailyStat.SrxmStat srxmStat = new YySspjxxDailyStat.SrxmStat();
        srxmStat.setSrxm(SysConstant.BBTJ_SFRJ_YJSF);

        List<YySspjxxDailyStat.FffsStat> fffsStats = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(yjjelist)) {
            Map<String, List<YjcyjFffsStat>> fffsYjMap = yjjelist.stream().collect(Collectors.groupingBy(YjcyjFffsStat::getFffs));
            fffsStats = YySspjxxDailyStat.FffsStat.buildByFffsYjMap(fffsYjMap, fffsMap);
        }

        srxmStat.setFffsStats(fffsStats);
        return srxmStat;
    }

    private List<YySspjxxDailyStat.SrxmStat> getFjjdsf(YySspjxxDailyStatFilter filter, Map<String, String> fffsMap) {
        List<YyFjFffsStat> dataList = baseMapper.fjFffsStat(filter);

//        if (CollectionUtil.isEmpty(dataList)) {
//            return new ArrayList<>();
//        }

        List<YySspjxxDailyStat.SrxmStat> fjfStats = new ArrayList<>();

        YySspjxxDailyStat.SrxmStat wsfStat = getFjfSrxmStat(dataList, fffsMap, "yswsf", "污水费");
        if (wsfStat.getFffsStats().stream().map(YySspjxxDailyStat.FffsStat::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0) {
            fjfStats.add(wsfStat);
        }

        YySspjxxDailyStat.SrxmStat ljfStat = getFjfSrxmStat(dataList, fffsMap, "ysljf", "垃圾费");
        if (ljfStat.getFffsStats().stream().map(YySspjxxDailyStat.FffsStat::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0) {
            fjfStats.add(ljfStat);
        }

        YySspjxxDailyStat.SrxmStat zyfStat = getFjfSrxmStat(dataList, fffsMap, "ysszyf", "水资源费");
        if (zyfStat.getFffsStats().stream().map(YySspjxxDailyStat.FffsStat::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0) {
            fjfStats.add(zyfStat);
        }


        YySspjxxDailyStat.SrxmStat ecjyfStat = getFjfSrxmStat(dataList, fffsMap, "ysecjyf", "二次加压费");
        if (ecjyfStat.getFffsStats().stream().map(YySspjxxDailyStat.FffsStat::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0) {
            fjfStats.add(ecjyfStat);
        }

        YySspjxxDailyStat.SrxmStat fjfStat = getFjfSrxmStat(dataList, fffsMap, "ysfjf", "附加费");
        if (fjfStat.getFffsStats().stream().map(YySspjxxDailyStat.FffsStat::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0) {
            fjfStats.add(fjfStat);
        }

        YySspjxxDailyStat.SrxmStat xfsfStat = getFjfSrxmStat(dataList, fffsMap, "ysqt", "消防栓费");
        if (xfsfStat.getFffsStats().stream().map(YySspjxxDailyStat.FffsStat::getJe).reduce(BigDecimal.ZERO, BigDecimal::add).compareTo(BigDecimal.ZERO) > 0) {
            fjfStats.add(xfsfStat);
        }


        // 预交：账户充值的金额；冲预交：账户支付的金额（系统自动扣减+账户抵扣）
        List<YySspjxxDailyStat.SrxmStat> yjcyjmx = getYjCyjmx(filter, fffsMap);
        // if(yjcyjmx.stream().map(YySspjxxDailyStat.SrxmStat::).reduce(BigDecimal.ZERO,BigDecimal::add) .compareTo(BigDecimal.ZERO)>0) {
        fjfStats.addAll(yjcyjmx);
        //}
        addHjXj(fffsMap, fjfStats);
        return fjfStats;
    }

    private YySspjxxDailyStat.SrxmStat getFjfSrxmStat(List<YyFjFffsStat> dataList, Map<String, String> fffsMap,
                                                      String propertyName, String srxm) {
        Map<String, Double> fffsSfMap = dataList.stream()
                .filter(e -> StrUtil.isNotEmpty(e.getFffs()))
                .collect(Collectors.groupingBy(YyFjFffsStat::getFffs, Collectors.summingDouble((s) -> getValue(s, propertyName).doubleValue())));

        List<YySspjxxDailyStat.FffsStat> fffsStats = new ArrayList<>();

        fffsMap.forEach((fffs, fffsmc) -> {
            double sf = fffsSfMap.getOrDefault(fffs, 0D);
            fffsStats.add(new YySspjxxDailyStat.FffsStat(fffsmc, BigDecimal.ZERO, new BigDecimal(sf)));
        });

        return new YySspjxxDailyStat.SrxmStat(srxm, fffsStats);
    }


    public YffYeSeachSelectCount yffyeseach(PageDto pageDto, YffYeSeachFilter filter) {
        PageDto<YffYeSeachSelect> page = this.baseMapper.yffyeseach(pageDto, filter);

        YffYeSeachSelectCount yffYeSeachSelectCount = new YffYeSeachSelectCount();
        yffYeSeachSelectCount.setList(page.toVo());
        //所有页合计
        YffYeSeachSelectCount tempModel = this.baseMapper.yffyeseachCount(filter);
        if (StringUtil.isNotNull(tempModel)) {
            BeanUtils.copyProperties(tempModel, yffYeSeachSelectCount);
            yffYeSeachSelectCount.setList(page.toVo());
            //当前页合计
            yffYeSeachSelectCount.setKjje(page.getRecords().stream().map(YffYeSeachSelect::getKjje).reduce(BigDecimal.ZERO, BigDecimal::add));
            yffYeSeachSelectCount.setYfje(page.getRecords().stream().map(YffYeSeachSelect::getYfje).reduce(BigDecimal.ZERO, BigDecimal::add));
            yffYeSeachSelectCount.setZsye(page.getRecords().stream().map(YffYeSeachSelect::getZsye).reduce(BigDecimal.ZERO, BigDecimal::add));
            yffYeSeachSelectCount.setKyye(page.getRecords().stream().map(YffYeSeachSelect::getKyye).reduce(BigDecimal.ZERO, BigDecimal::add));
        }
        return yffYeSeachSelectCount;
    }

    public List<YffYeSeachSelect> yffyeseachList(YffYeSeachFilter filter) {
        List<YffYeSeachSelect> list = this.baseMapper.yffyeseachList(filter);
        return list;
    }

    private BigDecimal getValue(YyFjFffsStat stat, String propertyName) {
        Field field = null;
        try {
            field = stat.getClass().getDeclaredField(propertyName);
            field.setAccessible(true);
            return (BigDecimal) field.get(stat);
        } catch (NoSuchFieldException e) {
            return BigDecimal.ZERO;
        } catch (IllegalAccessException e) {
            return BigDecimal.ZERO;
        }
    }

    @Override
    public Map<String, String> getSjMap() {
        List<BmSj> list = sjService.lambdaQuery().orderByAsc(BmSj::getCzsj).list();
        return list.stream().collect(Collectors.toMap(BmSj::getCode, BmSj::getName, (u1, u2) -> u1, LinkedHashMap::new));
    }

    private List<BmSj> getSjMap1() {
        return sjService.list().stream().collect(Collectors.toList());
    }

    private Map<String, String> getFffsMapByDailyStat() {
        List<BmFffs> allBmFffs = bmFffsService.getAllBmFffs();
        if (CollectionUtil.isEmpty(allBmFffs)) {
            throw new FeesException("请先添加付费方式", BUSINESS_ERROR);
        }

        List<BmFffs> collect = allBmFffs.stream().filter(o -> SysConstant.SFRJBB_MRFFFS.contains(o.getCode())).collect(Collectors.toList());
        return collect.stream().collect(Collectors.toMap(BmFffs::getCode, BmFffs::getName));
    }

    /**
     * 实收月报表
     */
    public List<SsybbSelect> getSssf(YySspjxxFilter filter) {
        List<SsybbSelect> lst = this.baseMapper.getSssf(filter);
        if (!lst.isEmpty()) {
            lst.forEach(m -> {
                m.setLx("sf");
            });
        }

        List<SsybbFjfDto> fjf = this.baseMapper.getFjf(filter);
        if (!fjf.isEmpty()) {
            fjf.forEach(m -> {
                SsybbSelect ssybb = new SsybbSelect();
                ssybb.setSssl(BigDecimal.valueOf(0.00));
                ssybb.setName(m.getName());
                ssybb.setCode(m.getCode());
                ssybb.setSssf(m.getFy());
                ssybb.setLx("fjf");

                lst.add(ssybb);
            });
        }
        return lst;

    }

    @Override
    public PageResult<YffycmxcxSelect> yffycmxcx(PageDto pageDto, YffYeSeachFilter filter) {
        List<Order> orders = pageDto.getOrders();
        if (orders.size() > 0) {
            orders = orders.stream().map(item -> {
                if (item.getColumn().equals("yhbh")) {
                    Order order = new Order();
                    order.setColumn("a.yhbh");
                    order.setAsc(item.isAsc());
                    return order;
                }
                return item;
            }).collect(Collectors.toList());
        } else {
            orders.add(new Order("a.yhbh", true));
        }
        pageDto.setOrders(orders);
        PageDto<YffycmxcxSelect> yffycmxcxSelectPageDto = this.baseMapper.yffycmxcx(pageDto, filter);
        return yffycmxcxSelectPageDto.toVo();
    }

    @Override
    public List<YffycmxcxSelect> yffycmxcxlist(YffYeSeachFilter filter) {
        List<YffycmxcxSelect> list = this.baseMapper.yffycmxcx(filter);
        list.stream().sorted(Comparator.comparing(YffycmxcxSelect::getYhbh)).collect(Collectors.toList());
        if (!list.isEmpty()) {
            YffycmxcxSelect yffycmxcxSelect = new YffycmxcxSelect();
            yffycmxcxSelect.setYhbh("合计");
            yffycmxcxSelect.setYfje(list.stream().map(YffycmxcxSelect::getYfje).reduce(BigDecimal.ZERO, BigDecimal::add));
            list.add(yffycmxcxSelect);
        }
        return list;
    }

    @Override
    public PageResult<YffkjmxcxSelect> yffkjmxcx(PageDto pageDto, YffYeSeachFilter filter) {
        List<Order> orders = pageDto.getOrders();
        if (orders.size() > 0) {
            orders = orders.stream().map(item -> {
                if (item.getColumn().equals("yhbh")) {
                    Order order = new Order();
                    order.setColumn("a.yhbh");
                    order.setAsc(item.isAsc());
                    return order;
                }
                return item;
            }).collect(Collectors.toList());
        } else {
            orders.add(new Order("a.yhbh", true));
        }
        pageDto.setOrders(orders);
        PageDto<YffkjmxcxSelect> yffkjmxcxSelectPageDto = this.baseMapper.yffkjmxcx(pageDto, filter);
        return yffkjmxcxSelectPageDto.toVo();
    }

    @Override
    public List<YffkjmxcxSelect> yffkjmxcxlist(YffYeSeachFilter filter) {
        List<YffkjmxcxSelect> list = this.baseMapper.yffkjmxcx(filter);
        list.stream().sorted(Comparator.comparing(YffkjmxcxSelect::getYhbh)).collect(Collectors.toList());
        return list;
    }

    @Override
    public boolean fpbk(FpbkInsert insert) {
        try {
            long count = 0;
            if (StringUtil.isNull(insert.getSflsbh())) {
                throw new FeesException("收费流水编号不能为空！", BUSINESS_ERROR);
            }
            if (StringUtil.isNull(insert.getCwrq())) {
                throw new FeesException("财务日期不能为空！", BUSINESS_ERROR);
            }
            if (StringUtil.isNull(insert.getYhbh())) {
                throw new FeesException("用户编号不能为空！", BUSINESS_ERROR);
            }
            YhKhjbxx yhKhjbxx = khjbxxService.getById(insert.getYhbh());
            if (StringUtil.isNull(yhKhjbxx)) {
                throw new FeesException("用户信息不存在！", BUSINESS_ERROR);
            }
            count = yhGroupAccountsService.lambdaQuery()
                    .apply(String.format("yhbh = '%s' and yhbh not in (select yhbh from yh_group where id=group_id)", yhKhjbxx.getYhbh()))
                    .count();
            if (count > 0) {
                throw new FeesException("该记录是群主户子户不能申请发票，请使用群主户用户编号！", BUSINESS_ERROR);
            }
            count = this.count(
                    new QueryWrapper<YySspjxx>().lambda()
                            .eq(YySspjxx::getSflsbh, insert.getSflsbh())
            );
            if (count == 0) {
                throw new FeesException("未找到该记录对应的实收记录", BUSINESS_ERROR);
            }
            count = eiFpkjRequestService.count(
                    new QueryWrapper<EiFpkjRequest>().lambda()
                            .eq(EiFpkjRequest::getSflsbh, insert.getSflsbh())
                            .eq(EiFpkjRequest::getCwrq, insert.getCwrq())
            );
            if (count > 0) {
                throw new FeesException("该记录已存在正常申请的发票申请", BUSINESS_ERROR);
            }
            List<YySspjxx> yySspjxxList = this.lambdaQuery()
                    .eq(YySspjxx::getSflsbh, insert.getSflsbh())
                    .eq(YySspjxx::getCwrq, insert.getCwrq())
                    .orderByAsc(YySspjxx::getSfrq)
                    .list();
            List<YyQfmx> yyQfmxList = qfmxService.lambdaQuery()
                    .eq(YyQfmx::getId, yySspjxxList.stream().map(YySspjxx::getQfid).collect(Collectors.toList()))
                    .list();
            invoiceService.addInvoiceData(yyQfmxList, yySspjxxList, yhKhjbxx, "0", insert.getSfkp());
        } catch (FeesException e) {
            return false;
        }
        return true;
    }

    @Override
    public void yffzdkj() {
        List<Map> list = this.baseMapper.kkjQfmx();
        if (list.size() > 0) {
            AtomicInteger count = new AtomicInteger();
            StringBuilder yhbhs = new StringBuilder();
            // 创建可配置线程池
            ThreadPoolExecutor executor = new ThreadPoolExecutor(
                    Runtime.getRuntime().availableProcessors() * 2,  // 核心线程数
                    Runtime.getRuntime().availableProcessors() * 4,  // 最大线程数
                    60L, TimeUnit.SECONDS,
                    new ArrayBlockingQueue<>(2000),
                    new ThreadPoolExecutor.CallerRunsPolicy()
            );
            List<CompletableFuture<Void>> futureList = list.stream()
                    .map(map -> CompletableFuture.runAsync(() -> {
                        String yhbh = map.get("yhbh").toString();
                        BigDecimal syje = (BigDecimal) map.get("nbsyje");
                        List<YyQfmx> yyQfmxes = qfmxService.lambdaQuery()
                                .eq(YyQfmx::getSfbz, "0")
                                .eq(YyQfmx::getChbz, "0")
                                .eq(YyQfmx::getYhbh, yhbh)
                                .list();
                        int i = yffkj(yhbh, syje, yyQfmxes);
                        synchronized (yhbhs) {
                            if (i == 0) {
                                yhbhs.append(yhbh).append(",");
                            }
                        }
                        count.addAndGet(i); // 保持与原逻辑一致
                    }, executor))
                    .collect(Collectors.toList());

            CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
            executor.shutdown();
            String msg = "";
            if (StringUtil.isNotEmpty(yhbhs.toString())) {
                msg = String.format("扣减失败户号：%s！", yhbhs);
            }
            String remark = String.format("预付费自动扣减：共%s户，成功扣减%s户,失败%s户；%s", list.size(), count, list.size() - count.get(), msg);
            syscommlogService.xz("yy_sspjxx", "预付费自动扣减yyfkjTask", remark, "3");
        }
    }

    @Override
    public int yffkj(String yhbh, BigDecimal syje, List<YyQfmx> yyQfmxList) {

        int ret = transactionTemplate.execute(status -> {
            try {
                List<YyQfmx> yyQfmxes = yyQfmxList;
                YhKhjbxx yhKhjbxx = khjbxxService.getById(yhbh);
                if (yhKhjbxx == null) {
                    log.info("用户信息不存在！");
                    return 0;
                }

                if (yyQfmxes.isEmpty()) {
                    log.info("欠费明细不存在！");
                    return 0;
                }
                String sflsbh = GuidGenerator.getSflsbh(yhbh);
                yyQfmxes = yyQfmxes.stream()
                        .sorted(Comparator.comparing(YyQfmx::getCbrq))
                        .collect(Collectors.toList());
                BigDecimal yhye = syje == null ? BigDecimal.ZERO : syje;
                Date now = new Date();
                List<YySspjxx> list = new ArrayList<>();
                int sfxh = 1;
                List<String> qfidlist = new ArrayList<>();
                for (YyQfmx qfmx : yyQfmxes) {
                    BigDecimal ysje = qfmx.getYsje();
                    BigDecimal znj = qfmx.getZnj();
                    BigDecimal bckj = ysje.add(znj);
                    BigDecimal bcjz = yhye.subtract(bckj);

                    if (bcjz.compareTo(BigDecimal.ZERO) < 0) {
                        break;
                    }
                    //更新欠费明细
                    qfmxService.lambdaUpdate()
                            .set(YyQfmx::getSfrq, now)
                            .set(YyQfmx::getSfbz, "1")
                            .set(YyQfmx::getSflsbh, sflsbh)
                            .eq(YyQfmx::getId, qfmx.getId())
                            .update();
                    YySspjxx sspjxx = new YySspjxx();
                    BeanUtils.copyProperties(qfmx, sspjxx);
                    sspjxx.setQfid(qfmx.getId());
                    sspjxx.setSfxh(sfxh);//收费序号
                    sspjxx.setBckj(bckj);//本次扣减
                    sspjxx.setBcye(bcjz);//本次余额
                    sspjxx.setScye(yhye);//上次余额
                    sspjxx.setSflx(预存抵扣);
                    sspjxx.setSszje(BigDecimal.ZERO);
                    sspjxx.setFffs("9");
                    sspjxx.setSflsbh(sflsbh);
                    sspjxx.setSfrq(now);
                    sspjxx.setChbz(PjztEnum.正常.getValue());
                    sspjxx.setSfbz("1");
                    sspjxx.setFph2(yyPjbhService.getPjh("3"));
                    sspjxx.setSfrybm("3");
                    sspjxx.setSfryxm("系统机器");

                    this.save(sspjxx);
                    list.add(sspjxx);

                    zjzhService.lambdaUpdate()
                            .setSql("syje = syje -" + bckj)
                            .setSql("nbsyje = nbsyje -" + bckj)
                            .setSql("kjje = kjje +" + bckj)
                            .eq(YyZjzh::getYhbh, yhbh)
                            .update();
                    yhye = yhye.subtract(bckj);
                    qfidlist.add(qfmx.getId());
                }
                //-------------------------------------EI数电发票数据添加---------------------
                yyQfmxes = qfmxService.lambdaQuery()
                        .in(YyQfmx::getId, qfidlist)
                        .eq(YyQfmx::getEiYkfpBz, "0")
                        .list();
                if (yyQfmxes.size() > 0) {
                    invoiceService.addInvoiceData(yyQfmxes, list, yhKhjbxx, "0", "0");
                }
                List<YyQfmx> yjfpYyqfmxes = qfmxService.lambdaQuery()
                        .eq(YyQfmx::getSflsbh, sflsbh)
                        .eq(YyQfmx::getEiYkfpBz, "1")
                        .list();
                //判断是否存在预开发票，有则回写电子发票收费日期
                if (yjfpYyqfmxes.size() > 0) {
                    eiFpkjRequestService.lambdaUpdate()
                            .set(EiFpkjRequest::getSfrq, now)
                            .inSql(EiFpkjRequest::getSfid, String.format("select fpglh from yy_qfmx where sflsbh='%s'", sflsbh))
                            .update();
                    List<String> fpglhs = yjfpYyqfmxes.stream().map(YyQfmx::getFpglh).distinct().collect(Collectors.toList());
                    for (String fpglh : fpglhs) {
                        List<YyQfmx> yyQfmxList1 = yjfpYyqfmxes.stream().filter(e -> e.getFpglh().equals(fpglh)).collect(Collectors.toList());
                        BigDecimal ysje = yyQfmxList1.stream().map(YyQfmx::getYsje).reduce(BigDecimal.ZERO, BigDecimal::add);
                        BigDecimal znj = yyQfmxList1.stream().map(YyQfmx::getZnj).reduce(BigDecimal.ZERO, BigDecimal::add);
                        eiYkfpLogService.lambdaUpdate()
                                .set(EiYkfpLog::getXzsj, now)
                                .set(EiYkfpLog::getXzrybm, "3")
                                .set(EiYkfpLog::getXzryxm, "系统机器")
                                .set(EiYkfpLog::getXzje, ysje.add(znj))
                                .set(EiYkfpLog::getSflx, 预存抵扣)
                                .set(EiYkfpLog::getSfbz, "1")
                                .in(EiYkfpLog::getFpglh, fpglh)
                                .update();
                    }
                }
                return 1;
            } catch (Exception e) {
                status.setRollbackOnly();
                log.info("自动扣费失败！" + e.getMessage());
                return 0;
            }
        });
        return ret;
    }


    @Override
    public YySspjxxSelect1Count getQzhpjglPage(PageDto pageDto, YySspjxxFilter filter) {
        if (StringUtil.isEmpty(filter.getYhbh())) {
            throw new FeesException("用户编号不能为空！", BUSINESS_ERROR);
        }
        List<YhGroup> yhGroupList = yhGroupService.list();
        int count = yhGroupList.stream().filter(yhGroup -> yhGroup.getYhbh().equals(filter.getYhbh())).collect(Collectors.toList()).size();
        if (count == 0) {
            List<YhGroupAccounts> yhGroupAccountsList = yhGroupAccountsService.lambdaQuery()
                    .eq(YhGroupAccounts::getYhbh, filter.getYhbh())
                    .list();
            if (yhGroupAccountsList.size() > 0) {
                YhGroupAccounts yhGroupAccount = yhGroupAccountsList.get(0);
                String yhGroupyhbh = yhGroupList.stream().filter(item -> item.getId().equals(yhGroupAccount.getGroupId()))
                        .map(YhGroup::getYhbh).findFirst().orElse("");
                if (StringUtil.isNotEmpty(yhGroupyhbh)) {
                    filter.setYhbh(yhGroupyhbh);
                } else {
                    throw new FeesException("该用户编号不存群主户关系！", BUSINESS_ERROR);
                }
            } else {
                throw new FeesException("该用户编号不存群主户关系！", BUSINESS_ERROR);
            }
        }
        YySspjxxSelect1Count yySspjxxSelect1Count = this.baseMapper.getQzhpjglPageCount(filter);
        PageDto<YySspjxxSelect1> page = this.baseMapper.getQzhpjglPage(pageDto, filter);
        if (!page.getRecords().isEmpty()) {
            yySspjxxSelect1Count.setList(page.toVo());
        }
        return yySspjxxSelect1Count;
    }

    @Override
    public BigDecimal getYszje() {
        return this.baseMapper.getYszje();
    }

    @Override
    public Map getDrystj() {
        return this.baseMapper.getDrystj();
    }

    @Override
    public List<YsartjSelect> getYsartj(YsartjFilter filter) {
        return this.baseMapper.getYsartj(filter);
    }

    @Override
    public List<Map> getYssfzb(YsartjFilter filter) {
        return this.baseMapper.getYssfzb(filter);
    }

    public List<YsartjSelect> getYsaytj() {
        return this.baseMapper.getYsaytj();
    }

    @Override
    public YysSsbbSelectCount getYsSsbb(YysSsbbFilter filter) {
        if (StringUtil.isEmpty(filter.getUserId())) {
            filter.setUserId(SecurityUtils.getUserId().toString());
        }
        YysSsbbSelectCount yysSsbbSelectCount = new YysSsbbSelectCount();
        List<Map> ysmxMaplist = qfmxService.getYsbbmxList(filter);
        List<Map> ssmxMapList = this.baseMapper.getYsSsbb(filter);
        String cwrq = bmYmjzConfigService.getCwrq(filter.getStartTime());
        if (!ssmxMapList.isEmpty()) {

            Map<String, List<Map>> ssGroup = ssmxMapList.stream().collect(Collectors.groupingBy(o -> o.get("yhbh").toString()));
            Map<String, List<Map>> ysGroup = ysmxMaplist.stream().collect(Collectors.groupingBy(o -> o.get("yhbh").toString()));

            Map<Boolean, List<Map>> ssmxPartition = ssmxMapList.stream()
                    .collect(Collectors.partitioningBy(o -> cwrq.compareTo(o.get("cwrq").toString()) <= 0));
            List<Map> ssmxMapList_dy = ssmxPartition.get(true);
            List<Map> ssmxMapList_yqy = ssmxPartition.get(false);

            Stream<String> ssYhbhStream = ssmxMapList.stream().map(o -> o.get("yhbh").toString());
            Stream<String> ysYhbhStream = ysmxMaplist.stream().map(o -> o.get("yhbh").toString());
            List<String> yhbhs = Stream.concat(ssYhbhStream, ysYhbhStream)
                    .distinct()
                    .sorted()
                    .collect(Collectors.toList());

            List<YysSsbbSelect> yysSsbbSelects = new ArrayList<>(yhbhs.size());
            for (String yhbh : yhbhs) {
                List<Map> items_ss = ssGroup.getOrDefault(yhbh, Collections.emptyList());
                List<Map> items_ys = ysGroup.getOrDefault(yhbh, Collections.emptyList());

                YysSsbbSelect item = new YysSsbbSelect();
                item.setYhbh(yhbh);

                // 姓名、地址
                if (!items_ys.isEmpty()) {
                    item.setYhxm(getFirstValue(items_ys, "yhxm"));
                    item.setYhdz(getFirstValue(items_ys, "yhdz"));
                } else {
                    item.setYhxm(getFirstValue(items_ss, "yhxm"));
                    item.setYhdz(getFirstValue(items_ss, "yhdz"));
                }

                // 金额汇总
                item.setYsje(sumBigDecimal(items_ys, "ysje"));
                item.setSsjeby(sumBigDecimal(ssmxMapList_dy.stream().filter(m -> m.get("yhbh").equals(yhbh))
                        .collect(Collectors.toList()), "sszje"));
                item.setSsjeyqy(sumBigDecimal(ssmxMapList_yqy.stream().filter(m -> m.get("yhbh").equals(yhbh))
                        .collect(Collectors.toList()), "sszje"));
                item.setKjje(sumBigDecimal(items_ss, "bckj"));
                item.setYcje(sumBigDecimal(items_ss, "bcyc"));

                yysSsbbSelects.add(item);
            }

            // 汇总统计
            yysSsbbSelectCount.setYysSsbbSelects(yysSsbbSelects);
            yysSsbbSelectCount.setZysje(sumList(yysSsbbSelects, YysSsbbSelect::getYsje));
            yysSsbbSelectCount.setZssjeby(sumList(yysSsbbSelects, YysSsbbSelect::getSsjeby));
            yysSsbbSelectCount.setZssjeyqy(sumList(yysSsbbSelects, YysSsbbSelect::getSsjeyqy));
            yysSsbbSelectCount.setZkjje(sumList(yysSsbbSelects, YysSsbbSelect::getKjje));
            yysSsbbSelectCount.setZycje(sumList(yysSsbbSelects, YysSsbbSelect::getYcje));
        }
        return yysSsbbSelectCount;
    }

    /**
     * 安全获取集合中第一个字段值
     */
    private String getFirstValue(List<Map> list, String key) {
        return list.stream()
                .map(map -> map.get(key))
                .filter(Objects::nonNull)
                .map(Object::toString)
                .findFirst()
                .orElse("");
    }

    /**
     * 对 List<Map> 中指定 key 的数值求和
     */
    private BigDecimal sumBigDecimal(List<Map> list, String key) {
        return list.stream()
                .map(map -> map.get(key))
                .filter(Objects::nonNull)
                .map(obj -> new BigDecimal(obj.toString()))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 对实体列表的某个 BigDecimal 字段汇总
     */
    private BigDecimal sumList(List<YysSsbbSelect> list, Function<YysSsbbSelect, BigDecimal> mapper) {
        return list.stream()
                .map(mapper)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}


