platformx-business-finance-biz/src/main/java/com/by4cloud/platformx/business/service/impl/PaymentConfirmServiceImpl.java
@@ -1,12 +1,49 @@
package com.by4cloud.platformx.business.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.by4cloud.platformx.business.entity.PaymentConfirm;
import com.by4cloud.platformx.business.mapper.PaymentConfirmMapper;
import com.by4cloud.platformx.admin.api.entity.SysDept;
import com.by4cloud.platformx.admin.api.feign.RemoteDeptService;
import com.by4cloud.platformx.business.dto.AgingQueryDTO;
import com.by4cloud.platformx.business.dto.PaymentConfirmAddDTO;
import com.by4cloud.platformx.business.dto.SyncPaymentRecepitDTO;
import com.by4cloud.platformx.business.entity.*;
import com.by4cloud.platformx.business.mapper.*;
import com.by4cloud.platformx.business.service.BusinessCustomerService;
import com.by4cloud.platformx.business.service.ContractService;
import com.by4cloud.platformx.business.service.PaymentConfirmService;
import com.by4cloud.platformx.business.utils.SignHelper;
import com.by4cloud.platformx.business.vo.AgingAnalysisVo;
import com.by4cloud.platformx.business.vo.AgingCompanyVo;
import com.by4cloud.platformx.business.vo.AgingVo;
import com.by4cloud.platformx.common.core.util.R;
import com.by4cloud.platformx.common.data.datascope.DataScope;
import com.by4cloud.platformx.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
;
/**
 * 收款确认
@@ -14,12 +51,500 @@
 * @author syt
 * @date 2026-04-29 11:33:26
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PaymentConfirmServiceImpl extends ServiceImpl<PaymentConfirmMapper, PaymentConfirm> implements PaymentConfirmService {
   private final ContractService contractService;
   private final BusinessCustomerService businessCustomerService;
   private final ContractPaymentScheduleMapper contractPaymentScheduleMapper;
   private final CurrentOverdueMapper currentOverdueMapper;
   private final HistoryOverdueMapper historyOverdueMapper;
   private final PaymentSlipMapper paymentSlipMapper;
   private final BipRequestRecordMapper bipRequestRecordMapper;
   private final ContractExecDateMapper contractExecDateMapper;
   private final MeterReadRecordMapper meterReadRecordMapper;
   private final BankStatementMapper bankStatementMapper;
   private final RemoteDeptService remoteDeptService;
   private final StringRedisTemplate redisTemplate;
   @Value("${bip.url}")
   private String url;
   @Value("${bip.codes}")
   private String codes;
   @Value("${bip.appKey}")
   private String appKey;
   @Value("${bip.appSecret}")
   private String appSecret;
   @Override
   public boolean save(PaymentConfirm entity) {
   public R add(PaymentConfirmAddDTO addDTO) {
      if (StrUtil.isNotBlank(addDTO.getContractNo())) {
         Contract contract = contractService.getOne(Wrappers.<Contract>lambdaQuery().eq(Contract::getContractNo, addDTO.getContractNo()));
         if (ObjUtil.isNull(contract)) {
            return R.failed("合同查询失败,请检查合同编号");
         }
         BusinessCustomer customer = businessCustomerService.getById(contract.getPartyAId());
         if (ObjUtil.isNull(customer)) {
            return R.failed("客商查询失败,请检查客商");
         }
         //转入
         if (StrUtil.equals(addDTO.getInOrOut(), "1")) {
            //保存收款单
            savePaymentSlip(addDTO,customer,contract);
            //保存收款单
            savePaymentConfirm(addDTO,contract,customer);
            //处理收款
            handleSlipToSchedule(addDTO,contract);
            //更新状态
            updateContractStatus(addDTO,contract);
         }
         //转出
         if (StrUtil.equals(addDTO.getInOrOut(), "2")) {
            return handleBackSlip(addDTO,contract,customer);
         }
      }
      return R.ok();
   }
   private R handleBackSlip(PaymentConfirmAddDTO addDTO,Contract contract,BusinessCustomer customer) {
      PaymentConfirm lastConfirm = baseMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
            .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
      PaymentConfirm entity = new PaymentConfirm();
      entity.setContractId(contract.getId());
      entity.setContractName(contract.getContractName());
      entity.setContractNo(contract.getContractNo());
      entity.setBusGuestId(customer.getId());
      entity.setBusGuestName(customer.getCompanyName());
      entity.setBusinessType("退款");
      entity.setTransationAmount(addDTO.getTransationAmount());
      BigDecimal newtotal = addDTO.getTransationAmount().multiply(new BigDecimal("-1")).add(lastConfirm.getTotalAmount());
      if (newtotal.compareTo(new BigDecimal("0")) > 0) {
         entity.setAdvanceAmount(newtotal);
         entity.setTotalAmount(newtotal);
      } else if (newtotal.compareTo(new BigDecimal("0")) == 0) {
         entity.setTotalAmount(newtotal);
      } else {
         return R.failed("当前客户余额为" + lastConfirm.getTotalAmount() + "不足以满足当前发生金额,无法操作");
      }
      entity.setConfirmTime(new Date());
      return super.save(entity);
      baseMapper.insert(entity);
      contract.setPaidAmount(contract.getPaidAmount().subtract(addDTO.getTransationAmount()));
      contract.setContractStatus(2);
      contractService.updateById(contract);
      return R.ok();
   }
   private void updateContractStatus(PaymentConfirmAddDTO addDTO,Contract contract) {
      //非房屋租赁 水电
      if (!StrUtil.equals(contract.getContractCategory(), "water_house")) {
         //更新合同已付款
         BigDecimal paid = new BigDecimal("0");
         if (ObjUtil.isNotNull(contract.getPaidAmount())) {
            paid = contract.getPaidAmount();
         }
         paid = paid.add(addDTO.getTransationAmount());
         contract.setPaidAmount(paid);
         if (paid.compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0&&contract.getBillingAmout().compareTo(contract.getAmount())==0) {
            contract.setContractStatus(3);
            contract.setPaidAmount(contract.getAmount().subtract(contract.getDropAmount()));
         }
         contractService.updateById(contract);
      }else {
         List<ContractExecDate> execDateList = contractExecDateMapper.selectList(Wrappers.<ContractExecDate>lambdaQuery().eq(ContractExecDate::getContractId,contract.getId())
               .eq(ContractExecDate::getGenFlag,"0"));
         if (CollUtil.isEmpty(execDateList)){
            //更新合同已付款
            BigDecimal paid = new BigDecimal("0");
            if (ObjUtil.isNotNull(contract.getPaidAmount())) {
               paid = contract.getPaidAmount();
            }
            paid = paid.add(addDTO.getTransationAmount());
            contract.setPaidAmount(paid);
            if (contract.getBillingAmout().compareTo(contract.getAmount())==0&&paid.compareTo(contract.getAmount().subtract(contract.getDropAmount())) >= 0) {
               contract.setContractStatus(3);
               contract.setPaidAmount(contract.getAmount());
            }
            contractService.updateById(contract);
         }
      }
   }
   private void handleSlipToSchedule(PaymentConfirmAddDTO addDTO,Contract contract) {
      //更新付款阶段付款
      List<ContractPaymentSchedule> scheduleList = contractPaymentScheduleMapper.selectList(Wrappers.<ContractPaymentSchedule>lambdaQuery()
            .eq(ContractPaymentSchedule::getContractId, contract.getId()).ne(ContractPaymentSchedule::getPaymentStatus, 2).ne(ContractPaymentSchedule::getPaymentStatus, 3)
            .orderByAsc(ContractPaymentSchedule::getCreateTime));
      if (CollUtil.isNotEmpty(scheduleList)) {
         BigDecimal remain = addDTO.getTransationAmount();
         for (ContractPaymentSchedule schedule : scheduleList) {
            BigDecimal lastRemain = remain;
            remain = remain.subtract(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount() :
                  schedule.getPlannedAmount().subtract(schedule.getActualAmount()));
            if (remain.compareTo(new BigDecimal("0")) >= 0) {
               schedule.setActualAmount(schedule.getPlannedAmount());
               schedule.setPaymentDate(addDTO.getConfirmTime());
               schedule.setPaymentStatus(2);
               contractPaymentScheduleMapper.updateById(schedule);
               //查询是否有当前逾期
               CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                     .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
               if (ObjUtil.isNotNull(currentOverdue)) {
                  //新增逾期历史
                  HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                  historyOverdue.setPaymentTime(addDTO.getConfirmTime());
                  historyOverdue.setCompId(schedule.getCompId());
                  historyOverdueMapper.insert(historyOverdue);
                  //删除当前逾期
                  currentOverdueMapper.deleteById(currentOverdue);
               }
            } else {
               schedule.setActualAmount(StrUtil.equals(schedule.getPaymentStatus() + "", "0") ? schedule.getPlannedAmount().add(remain) :
                     schedule.getActualAmount().add(lastRemain));
               schedule.setPaymentDate(addDTO.getConfirmTime());
               schedule.setPaymentStatus(1);
               contractPaymentScheduleMapper.updateById(schedule);
               //查询是否有当前逾期
               CurrentOverdue currentOverdue = currentOverdueMapper.selectOne(Wrappers.<CurrentOverdue>lambdaQuery().eq(CurrentOverdue::getScheduleId, schedule.getId())
                     .eq(CurrentOverdue::getContractId, schedule.getContractId()).last("limit 1"));
               if (ObjUtil.isNotNull(currentOverdue)) {
                  //新增逾期历史
                  HistoryOverdue historyOverdue = BeanUtil.copyProperties(currentOverdue, HistoryOverdue.class, "id");
                  historyOverdue.setReceivableAmount(lastRemain);
                  historyOverdue.setPaymentTime(addDTO.getConfirmTime());
                  historyOverdue.setCompId(schedule.getCompId());
                  historyOverdueMapper.insert(historyOverdue);
                  //更新当前逾期
                  currentOverdue.setReceivableAmount(schedule.getPlannedAmount().subtract(schedule.getActualAmount()));
                  currentOverdueMapper.updateById(currentOverdue);
               }
               break;
            }
         }
      }
   }
   private void savePaymentConfirm(PaymentConfirmAddDTO addDTO,Contract contract,BusinessCustomer customer) {
      PaymentConfirm lastConfirm = baseMapper.selectOne(Wrappers.<PaymentConfirm>lambdaQuery().eq(PaymentConfirm::getContractId, contract.getId())
            .orderByDesc(PaymentConfirm::getCreateTime).last("limit 1"));
      BigDecimal lastTotal = new BigDecimal("0");
      if (ObjUtil.isNotNull(lastConfirm)) {
         lastTotal = lastConfirm.getTotalAmount();
      }
      BigDecimal newtotal = addDTO.getTransationAmount().add(lastTotal);
      PaymentConfirm entity = new PaymentConfirm();
      entity.setContractId(contract.getId());
      entity.setContractName(contract.getContractName());
      entity.setContractNo(addDTO.getContractNo());
      if (ObjUtil.isNotNull(lastConfirm)) {
         entity.setScheduleId(lastConfirm.getScheduleId());
         entity.setScheduleName(lastConfirm.getScheduleName());
      }
      entity.setBusGuestId(customer.getId());
      entity.setBusGuestName(customer.getCompanyName());
      entity.setBusinessType("客户付款");
      if (newtotal.compareTo(new BigDecimal("0")) > 0) {
         entity.setTransationAmount(addDTO.getTransationAmount());
         entity.setAdvanceAmount(newtotal);
         entity.setTotalAmount(newtotal);
         entity.setConfirmTime(new Date());
         baseMapper.insert(entity);
      } else if (newtotal.compareTo(new BigDecimal("0")) == 0) {
         entity.setTransationAmount(addDTO.getTransationAmount());
         entity.setTotalAmount(newtotal);
         entity.setConfirmTime(new Date());
         baseMapper.insert(entity);
      } else {
         entity.setTransationAmount(addDTO.getTransationAmount());
         entity.setReceivableAmount(newtotal.multiply(new BigDecimal("-1")));
         entity.setTotalAmount(newtotal);
         entity.setConfirmTime(new Date());
         baseMapper.insert(entity);
      }
   }
   private void savePaymentSlip(PaymentConfirmAddDTO addDTO,BusinessCustomer customer,Contract contract) {
      //新增付款单
      PaymentSlip slip = new PaymentSlip();
      slip.setBusGuestId(customer.getId());
      slip.setBusGuestName(customer.getCompanyName());
      slip.setPayeeCompId(SecurityUtils.getUser().getCompId());
      slip.setPaymentTime(addDTO.getConfirmTime());
      slip.setPaymentAmount(addDTO.getTransationAmount());
      slip.setPayType(addDTO.getPayType());
      slip.setContractId(contract.getId());
      paymentSlipMapper.insert(slip);
   }
   @Override
   public R syncPaymentRecepit(SyncPaymentRecepitDTO dto) {
      String accessToken = "";
      if (redisTemplate.hasKey("BIP_TOKEN")) {
         accessToken = (String) redisTemplate.opsForValue().get("BIP_TOKEN");
      } else {
         accessToken = getAccessToken(accessToken);
      }
      if (StrUtil.isEmpty(accessToken)) {
         return R.failed("获取token失败");
      }
      String[] bipCodeArr = StrUtil.isNotBlank(dto.getBipCode())?dto.getBipCode().split(","):codes.split(",");
      for (String bipCode : bipCodeArr) {
         //入参
         JSONObject params = new JSONObject();
         if (ObjUtil.isNotEmpty(dto.getPageSize())){
            params.put("pageSize",dto.getPageSize());
         }else {
            params.put("pageSize",999);
         }
         if (ObjUtil.isNotEmpty(dto.getPageNum())){
            params.put("pageNum",dto.getPageNum());
         }else {
            params.put("pageNum",1);
         }
         if (StrUtil.isNotBlank(dto.getStartDate())){
            params.put("begindate",dto.getStartDate());
         }else {
            params.put("begindate", DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1)));
         }
         if (StrUtil.isNotBlank(dto.getStartDate())){
            params.put("enddate", dto.getEndDate());
         }else {
            params.put("enddate", DateUtil.today());
         }
         params.put("dc_flag","1");//1 借 2 贷 只查收款
         //单据状态已审批
         params.put("accentity_code", bipCode);
         String finalAccessToken = accessToken;
         new Thread(() -> {
            try {
               Thread.sleep(500);
            } catch (InterruptedException e) {
               throw new RuntimeException(e);
            }
            log.info("银行流水查询 Request:{}", params.toJSONString());
            String result = HttpUtil.post(url + "/yonbip/ctm/cmp/bankReconciliationQuery?access_token=" + finalAccessToken, params.toJSONString());
            log.info("银行流水查询 Response:{}", result);
            //保存请求记录
            saveBipRequestRecord(params, "银行流水查询接口", result);
            JSONObject resultJson = JSONObject.parseObject(result);
            if (resultJson.containsKey("code") && resultJson.getString("code").equals("200")) {
               handleAndSave(bipCode, resultJson);
            }
         }).start();
      }
      return R.ok();
   }
   @Override
   public String getAccessToken(String accessToken) {
      long timestamp = System.currentTimeMillis();
      Map<String, Object> paramMap = new HashMap<>();
      paramMap.put("appKey", appKey);
      paramMap.put("timestamp", timestamp);
      String signature = null;
      try {
         signature = SignHelper.sign(paramMap, appSecret);
      } catch (NoSuchAlgorithmException e) {
         throw new RuntimeException(e);
      } catch (UnsupportedEncodingException e) {
         throw new RuntimeException(e);
      } catch (InvalidKeyException e) {
         throw new RuntimeException(e);
      }
      String getTokenResult = HttpUtil.get(url + "/open-auth/selfAppAuth/getAccessToken?appKey=" + appKey + "&timestamp=" + timestamp
            + "&signature=" + signature);
      log.info("Get access_token Response:{}", getTokenResult);
      JSONObject tokenJson = JSONObject.parseObject(getTokenResult);
      if (!tokenJson.containsKey("code") || !tokenJson.getString("code").equals("00000")) {
         log.error("Get access_token ERROR");
         return "";
      }
      if (ObjUtil.isNull(tokenJson.get("data")) || ObjUtil.isNull(JSONObject.parseObject(tokenJson.getString("data")))) {
         log.error("access_token value exception");
         return "";
      }
      accessToken = JSONObject.parseObject(tokenJson.getString("data")).getString("access_token");
      log.info("access_token value:{}", accessToken);
      redisTemplate.opsForValue().set("BIP_TOKEN", accessToken, JSONObject.parseObject(tokenJson.getString("data")).getIntValue("expire") - 10, TimeUnit.SECONDS);
      return accessToken;
   }
   @Override
   public void saveBipRequestRecord(JSONObject params, String methodName, String result) {
      BipRequestRecord record = new BipRequestRecord();
      record.setInterfaceName(methodName);
      record.setRequestParams(params.toJSONString());
      record.setResponseParams(result);
      record.setResponseCode(JSONObject.parseObject(result).getString("code"));
      bipRequestRecordMapper.insert(record);
   }
   private void handleAndSave(String bipCode, JSONObject resultJson) {
      R<SysDept> r = remoteDeptService.selectDeptByBipCode(bipCode);
      if (!r.isOk()) {
         log.error("bipcode查询单位失败");
         return;
      }
      SysDept dept = r.getData();
      JSONObject dataJson = resultJson.getJSONObject("data");
      if (ObjUtil.isNull(dataJson)) {
         log.error("返回结果中data解析失败");
         return;
      }
      JSONArray recordList = dataJson.getJSONArray("recordList");
      if (CollUtil.isEmpty(recordList)) {
         log.error("返回结果中recordList为空");
         return;
      }
      log.info("==================开始处理银行流水信息===================");
      recordList.stream().forEach(obj -> {
         JSONObject record = (JSONObject) obj;
         BusinessCustomer customer = businessCustomerService.getOne(Wrappers.<BusinessCustomer>lambdaQuery()
               .eq(BusinessCustomer::getCompanyName, record.getString("to_acct_name"))
               .eq(BusinessCustomer::getCompId,dept.getDeptId())
         );
         //保存付款单
         Boolean codeFlag = saveBankStatement(customer, record,dept);
         if (!codeFlag) {
            log.error("付款单id:{},付款单已存在");
         }
      });
      log.info("==================结束处理银行流水信息===================");
   }
   private Boolean saveBankStatement(BusinessCustomer customer, JSONObject record,SysDept dept) {
      BankStatement bankStatement = new BankStatement();
      bankStatement.setBankSeqNo(record.getString("bank_seq_no"));
      bankStatement.setReceiveBankAcc(record.getString("bank_seq_no"));
      bankStatement.setReceiveBankAccAcc(record.getString("bankaccount_account"));
      bankStatement.setReceiveBankAccName(record.getString("bankaccount_acctName"));
      bankStatement.setPayBankNo(record.getString("to_acct_no"));
      bankStatement.setPayBankAccName(record.getString("to_acct_name"));
      bankStatement.setTranDate(DateUtil.parseDateTime(record.getString("tran_date")));
      bankStatement.setTranAmount(record.getBigDecimal("tran_amt"));
      bankStatement.setDcFlag(record.getString("dc_flag"));
      bankStatement.setDataId(record.getLong("id"));
      bankStatement.setDataJson(record.toJSONString());
      if (ObjUtil.isNotNull(customer)) {
         bankStatement.setBusGuestId(customer.getId());
      }
      BankStatement statement = bankStatementMapper.selectOne(Wrappers.<BankStatement>lambdaQuery().eq(BankStatement::getDataId,record.getLong("id")));
      if (ObjUtil.isNotNull(statement)){
         return false;
      }
      bankStatement.setRemark(record.getString("remark"));
      bankStatement.setCompId(dept.getDeptId());
      bankStatementMapper.insert(bankStatement);
      return true;
   }
   @Override
   public R queryAllBusinessType() {
      return R.ok(baseMapper.selectList(Wrappers.<PaymentConfirm>lambdaQuery().select(PaymentConfirm::getBusinessType).isNotNull(PaymentConfirm::getBusinessType)
            .groupBy(PaymentConfirm::getBusinessType)).stream().map(PaymentConfirm::getBusinessType).collect(Collectors.toList()));
   }
   @Override
   public R queryAging() {
      List<AgingCompanyVo> companys = contractPaymentScheduleMapper.selectAgingCompany(null, DataScope.of("comp_id"));
      if (CollUtil.isEmpty(companys)) {
         return R.failed("暂无账龄");
      }
      List<AgingAnalysisVo> result = new ArrayList<>();
      AgingQueryDTO queryDTO = new AgingQueryDTO();
      List<AgingVo> agingVoList = contractPaymentScheduleMapper.selectAgingTotal(null);
      companys.stream().forEach(company -> {
         BusinessCustomer businessCustomer = businessCustomerService.getById(company.getCompanyId());
         AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
         agingAnalysisVo.setCompanyName(businessCustomer.getCompanyName());
         queryDTO.setCompanyId(company.getCompanyId());
         List<AgingVo> companyAgingVo = contractPaymentScheduleMapper.selectAgingTotal(queryDTO);
         //补全数据
         if (CollUtil.isEmpty(companyAgingVo)) {
            companyAgingVo = new ArrayList<>();
            AgingVo agingVo1 = new AgingVo(1L,"0-30天", new BigDecimal("0"), null);
            AgingVo agingVo2 = new AgingVo(2L,"31-60天", new BigDecimal("0"), null);
            AgingVo agingVo3 = new AgingVo(3L,"61-90天", new BigDecimal("0"), null);
            AgingVo agingVo4 = new AgingVo(4L,"91-180天", new BigDecimal("0"), null);
            AgingVo agingVo5 = new AgingVo(5L,"181-365天", new BigDecimal("0"), null);
            AgingVo agingVo6 = new AgingVo(6L,"1年以上", new BigDecimal("0"), null);
            companyAgingVo.add(agingVo1);
            companyAgingVo.add(agingVo2);
            companyAgingVo.add(agingVo3);
            companyAgingVo.add(agingVo4);
            companyAgingVo.add(agingVo5);
            companyAgingVo.add(agingVo6);
         } else {
            List<String> overdueRanges = companyAgingVo.stream().map(AgingVo::getOverdueRange).collect(Collectors.toList());
            if (!CollUtil.contains(overdueRanges, "0-30天")) {
               AgingVo agingVo1 = new AgingVo(1L,"0-30天", new BigDecimal("0"), null);
               companyAgingVo.add(agingVo1);
            }
            if (!CollUtil.contains(overdueRanges, "31-60天")) {
               AgingVo agingVo2 = new AgingVo(2L,"31-60天", new BigDecimal("0"), null);
               companyAgingVo.add(agingVo2);
            }
            if (!CollUtil.contains(overdueRanges, "61-90天")) {
               AgingVo agingVo3 = new AgingVo(3L,"61-90天", new BigDecimal("0"), null);
               companyAgingVo.add(agingVo3);
            }
            if (!CollUtil.contains(overdueRanges, "91-180天")) {
               AgingVo agingVo4 = new AgingVo(4L,"91-180天", new BigDecimal("0"), null);
               companyAgingVo.add(agingVo4);
            }
            if (!CollUtil.contains(overdueRanges, "181-365天")) {
               AgingVo agingVo5 = new AgingVo(5L,"181-365天", new BigDecimal("0"), null);
               companyAgingVo.add(agingVo5);
            }
            if (!CollUtil.contains(overdueRanges, "1年以上")) {
               AgingVo agingVo6 = new AgingVo(6L,"1年以上", new BigDecimal("0"), null);
               companyAgingVo.add(agingVo6);
            }
         }
         agingAnalysisVo.setAmount(companyAgingVo.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
         List<AgingVo> finalCompanyAgingVo = companyAgingVo;
         agingAnalysisVo.setPercent(IntStream.range(0, agingVoList.size())
               .mapToObj(i -> {
                  BigDecimal part = finalCompanyAgingVo.get(i).getTotalAmount();
                  BigDecimal total = agingVoList.get(i).getTotalAmount();
                  if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
                     return null;
                  }
                  return part.divide(total, 4, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100"))
                        .setScale(2, RoundingMode.HALF_UP);
               })
               .collect(Collectors.toList()));
         result.add(agingAnalysisVo);
      });
      //合计
      AgingAnalysisVo agingAnalysisVo = new AgingAnalysisVo();
      agingAnalysisVo.setCompanyName("合计");
      agingAnalysisVo.setAmount(agingVoList.stream().map(AgingVo::getTotalAmount).collect(Collectors.toList()));
      List<BigDecimal> percent = IntStream.range(0, agingAnalysisVo.getAmount().size())
            .mapToObj(i -> {
               if (agingAnalysisVo.getAmount().get(i) == null || agingAnalysisVo.getAmount().get(i).compareTo(BigDecimal.ZERO) == 0) {
                  return null;
               } else {
                  return new BigDecimal("100");
               }
            })
            .collect(Collectors.toList());
      agingAnalysisVo.setPercent(percent);
      result.add(agingAnalysisVo);
      return R.ok(result);
   }
}