package com.sunxung.factoring.service.financing.review.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunxung.factoring.component.enums.FinancingCurrentStageEnum;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ServiceException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.dict.impl.IncomeExpenditureTypeDict;
import com.sunxung.factoring.entity.ResponseJson;
import com.sunxung.factoring.entity.ValidatorEntity;
import com.sunxung.factoring.entity.creditresolution.CreditResolution;
import com.sunxung.factoring.entity.entprise.Enterprise;
import com.sunxung.factoring.entity.entprise.EnterpriseEntry;
import com.sunxung.factoring.entity.financing.apply.CAcceptanceGoodsInfo;
import com.sunxung.factoring.entity.financing.apply.CFinancingBasicInfo;
import com.sunxung.factoring.entity.financing.apply.CFinancingGoodsInfo;
import com.sunxung.factoring.entity.financing.review.*;
import com.sunxung.factoring.entity.project.ProjectInformation;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.mapper.financing.review.ReviewQuotaDisburseMapper;
import com.sunxung.factoring.service.creditresolution.ICreditResolutionService;
import com.sunxung.factoring.service.entprise.IEnterpriseService;
import com.sunxung.factoring.service.financing.apply.ICAcceptanceGoodsInfoService;
import com.sunxung.factoring.service.financing.apply.ICFinancingBasicInfoService;
import com.sunxung.factoring.service.financing.apply.ICFinancingGoodsInfoService;
import com.sunxung.factoring.service.financing.review.*;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.project.IProjectInformationService;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.FileStorageService;
import com.sunxung.factoring.service.sys.SerialNumberGenerator;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description : 额度支用控制层实现类
 * @Author : L.Jia
 * @Date: 2024-01-02 09:32
 */
@Service
public class ReviewQuotaDisburseServiceImpl extends ServiceImpl<ReviewQuotaDisburseMapper, ReviewQuotaDisburse>
        implements ReviewQuotaDisburseService {

    @Autowired
    private DictionaryService dictService;
    @Autowired
    private ReviewQuotaDisburseMapper quotaDisburseMapper;
    @Autowired
    private ReviewFinancingInfoService reviewFinancingInfoService;
    @Autowired
    private ReviewIncomeExpenditurePlanService reviewIncomeExpenditurePlanService;
    @Autowired
    private ReviewMasterContractService reviewMasterContractService;
    @Autowired
    private ReviewMasterContractDebtorService reviewMasterContractDebtorService;
    @Autowired
    private ReviewBasicContractService reviewBasicContractService;
    @Autowired
    private ReviewBasicContractChangeContentService reviewBasicContractChangeContentService;
    @Autowired
    private ReviewTransferReceivableService reviewTransferReceivableService;
    @Autowired
    private ReviewQuotaMortgageRelService reviewQuotaMortgageRelService;
    @Autowired
    private SerialNumberGenerator serialNumberGenerator;
    @Autowired
    private FileStorageService fileStorageService;
    @Autowired
    private ReviewRltRepayService reviewRltRepayService;
    @Autowired
    private IEnterpriseService enterpriseService;
    @Autowired
    private IReviewGuaranteeFileService reviewGuaranteeSecondFileService;
    @Autowired
    private IReviewGuaranteeFileHisService reviewGuaranteeSecondFileHistoryService;
    @Autowired
    private IReviewRltRepayEstateService reviewRltRepayEstateService;
    @Autowired
    private IReviewRltRepayEstateHistoryService reviewRltRepayEstateHistoryService;
    @Autowired
    private IReviewRltRepayLandService reviewRltRepayLandService;
    @Autowired
    private IReviewRltRepayLandHistoryService reviewRltRepayLandHistoryService;
    @Autowired
    private IReviewRltRepayVehicleService reviewRltRepayVehicleService;
    @Autowired
    private IReviewRltRepayVehicleHistoryService reviewRltRepayVehicleHistoryService;
    @Autowired
    private IReviewRltRepayEquityAssetsService reviewRltRepayEquityAssetsService;
    @Autowired
    private IReviewRltRepayEquityAssetsHistoryService reviewRltRepayEquityAssetsHistoryService;
    @Autowired
    private IReviewRltRepayOtherAssetsService reviewRltRepayOtherAssetsService;
    @Autowired
    private IReviewRltRepayOtherAssetsHistoryService reviewRltRepayOtherAssetsHistoryService;
    @Autowired
    private ReviewMortgageBasicInfoService reviewMortgageBasicInfoService;
    @Autowired
    private IReviewMortgageBasicInfoHisService reviewMortgageBasicInfoHisService;
    @Autowired
    private FlowableService flowableService;
    @Autowired
    private BusinessAssigneeService assigneeService;
    @Autowired
    private ICFinancingBasicInfoService financingBasicInfoService;
    @Autowired
    private ICFinancingGoodsInfoService financingGoodsInfoService;
    @Autowired
    private ICAcceptanceGoodsInfoService acceptanceGoodsInfoService;
    @Autowired
    private IReviewQuotaDisburseHisService reviewQuotaDisburseHisService;
    @Autowired
    private IReviewFinancingInfoHisService reviewFinancingInfoHisService;
    @Autowired
    private IReviewIncomeExpenditurePlanHisService reviewIncomeExpenditurePlanHisService;
    @Autowired
    private IReviewMasterContractHisService reviewMasterContractHisService;
    @Autowired
    private IReviewMasterContractDebtorHisService reviewMasterContractDebtorHisService;
    @Autowired
    private IReviewTransferReceivableHisService reviewTransferReceivableHisService;
    @Autowired
    private IReviewBasicContractHisService reviewBasicContractHisService;
    @Autowired
    private IReviewBasicContractChangeContentHisService reviewBasicContractChangeContentHisService;
    @Autowired
    private IReviewRltRepayHisService reviewRltRepayHisService;
    @Autowired
    private IReviewQuotaMortgageRelHisService reviewQuotaMortgageRelHisService;
    @Autowired
    private ReviewMortgageCollateralInfoService reviewMortgageCollateralInfoService;
    @Autowired
    private IReviewMortgageCollateralInfoHisService reviewMortgageCollateralInfoHisService;
    @Autowired
    private ReviewMortgagePledgeInfoService reviewMortgagePledgeInfoService;
    @Autowired
    private IReviewMortgagePledgeInfoHisService reviewMortgagePledgeInfoHisService;
    @Autowired
    private ICreditResolutionService creditResolutionService;
    @Autowired
    private IProjectInformationService projectInformationService;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${sop.addBusinessUrl}")
    private String addBusiness;

    @Override
    public List<ReviewIncomeExpenditurePlan> generateIncomeExpenditurePlan(ReviewFinancingInfo reviewFinancingInfo) {
        if (reviewFinancingInfo == null || reviewFinancingInfo.getRepaymentMethod() == null) {
            throw new BusinessException(CodeUtil.FAIL, "融资信息或回款方式不能为空");
        }
        Dictionary dict = dictService.getByCode(reviewFinancingInfo.getPayBackMethod());

        //回款方式为前收息或者后收息
        List<ReviewIncomeExpenditurePlan> planList = new ArrayList<>();
        preOrAfterInterest(reviewFinancingInfo, planList, dict);

        planList.sort(Comparator.comparing(ReviewIncomeExpenditurePlan::getIncomeExpenditureDate));
        return planList;
    }

    @Override
    public String calculateIrr(ReviewQuotaDisburse quota) {
        String irrStr = "0%";
        if (null != quota && null != quota.getIncomeExpenditurePlanList()
                && quota.getIncomeExpenditurePlanList().size() > 0) {
            List<BigDecimal> netCash = new ArrayList<BigDecimal>();
            Map<Date, BigDecimal> map = new HashMap<>();
            List<ReviewIncomeExpenditurePlan> planList = quota.getIncomeExpenditurePlanList();
            // 根据日期分组：
            Map<Date, List<ReviewIncomeExpenditurePlan>> map1 = planList.stream()
                    .filter((t) -> t.getIncomeExpenditureDate() != null)
                    .collect(Collectors.groupingBy(ReviewIncomeExpenditurePlan::getIncomeExpenditureDate));
            // 计算同一日期下的现金流量总和
            map1.forEach((x, y) -> {
                BigDecimal total = new BigDecimal(0);
                for (ReviewIncomeExpenditurePlan plan : y) {
                    if (null != plan.getFinalCashFlow()) {
                        total = total.add(plan.getFinalCashFlow());
                    }
                }
                map.put(x, total);
            });
            // 对map进行排序
            Map<Date, BigDecimal> result = map.entrySet().stream().sorted(Map.Entry.comparingByKey())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue,
                            LinkedHashMap::new));
            // 获取最大日期和最小的日期
            Date firstDate = null;
            Date endDate = null;
            for (Map.Entry<Date, BigDecimal> entry : result.entrySet()) {
                if (null != entry.getKey()) {
                    firstDate = entry.getKey();
                    break;
                }
            }
            for (Map.Entry<Date, BigDecimal> entry : result.entrySet()) {
                if (null != entry.getKey()) {
                    endDate = entry.getKey();
                }
            }
            // 把两个日期之间的所有日期的金额设置为0，放到Map中
            Map<Date, BigDecimal> allMap = new LinkedHashMap<>();
            if (null != firstDate && null != endDate) {
                List<Date> list = com.sunxung.factoring.component.util.DateUtil.getBetweenDates(com.sunxung.factoring.component.util.DateUtil.formateYMD(firstDate),
                        com.sunxung.factoring.component.util.DateUtil.formateYMD(endDate));
                for (Date date : list) {
                    allMap.put(date, new BigDecimal("0"));
                }
            }
            for (Map.Entry<Date, BigDecimal> entry : allMap.entrySet()) {
                BigDecimal amount = result.get(entry.getKey());
                if (amount == null) {
                    amount = entry.getValue();
                }
                netCash.add(amount);
            }
            double irr = new IrrUtil(netCash, 1).calculateIrr();
            if (Double.isNaN(irr)) {
                // throw new ValidatorException(CodeUtil.FAIL, "现金流量不符合IRR的计算公式");
            }
            if (!Double.isNaN(irr) && !Double.isInfinite(irr)) {
                irr = new BigDecimal(irr).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();// 保留四位小数
                irrStr = PercentageUtil.convertPercentage(irr);
                if (irrStr.length() >= 6) {
                    char a = irrStr.charAt(5);
                    if (a == '.') {
                        irrStr = irrStr.substring(0, 8) + "%";
                    }
                }
            }
        }
        return irrStr;
    }

    @Override
    public List<Dictionary> findArlpType(String code) {
        return dictService.findByParentCodeAndCode("certType", code);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editReviewQuotaDisburse(ReviewQuotaDisburse quotaDisburse) throws Exception {
        if (null != quotaDisburse) {
            // 验证额度支用数据的合法性
            if (ConstantConversionUtil.APPROVAL_RESULT_PASS.equals(quotaDisburse.getApprovalConclusion())) {
                checkQuotaDisburseLegality(quotaDisburse);
            }
            //IRR处理
            if (quotaDisburse.getPlanIrrStr() != null) {
                Number number = PercentageUtil.convertDouble(quotaDisburse.getPlanIrrStr());
                quotaDisburse.setPlanIrr(new BigDecimal(number.toString()));
            }
            CFinancingBasicInfo financingBasicInfo = financingBasicInfoService.getById(quotaDisburse.getFinancingBasicInfoId());
            if (null == quotaDisburse.getId()) {
                //新增
                add(quotaDisburse, financingBasicInfo);
            } else {
                update(quotaDisburse, financingBasicInfo);
            }
            //修改主合同名称
            doUpdateMasterContractName(quotaDisburse);
            // 提交
            if (quotaDisburse.isVisible()) {
                //添加三方企业工商信息
                addBusinessInfo(quotaDisburse);
                Map<String, Object> procVariables = new HashMap<>();
                Long assigneeId = assigneeService.getIdByBusiness(quotaDisburse.getFinancingBasicInfoId(), ConstantUtil.FINANCING_APPLY,
                        ConstantUtil.ASSIGNEE_RISK_MANAGER);
                procVariables.put(ConstantUtil.REVIEW_QUOTA_DISBURSE_APPROVAL_ASSIGNEE, assigneeId);

                Map<String, Object> msgVariables = new HashMap<>();
                msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, financingBasicInfo.getBusinessNumber());
                msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT, "业务编号为“" + financingBasicInfo.getBusinessNumber()
                        + "”的项目已inOut“"
                        + ConstantConversionUtil.flowBusinessKeyNames.get(quotaDisburse.getClass().getSimpleName())
                        + "—formBusiness”阶段，");
                Long historyId = addHistory(quotaDisburse);
                String conclusion = ConstantConversionUtil.processApprovalResult.get(quotaDisburse.getApprovalConclusion()).equals("驳回") ?
                        "退回" : ConstantConversionUtil.processApprovalResult.get(quotaDisburse.getApprovalConclusion());
                Boolean result = flowableService.completeMyTask(quotaDisburse.getTaskId(), financingBasicInfo, procVariables,
                        conclusion, historyId, msgVariables, ConstantUtil.FINANCING_APPLY);
                if (result == null || !result) {
                    throw new ValidatorException(CodeUtil.FAIL, "额度支用提交时出错啦！");
                }
                if (ConstantConversionUtil.APPROVAL_RESULT_PASS.equals(quotaDisburse.getApprovalConclusion())) {
                    //修改融资申请当前阶段
                    financingBasicInfo.setCurrentStage(FinancingCurrentStageEnum.REVIEW_QUOTA_DISBURSE_APPROVAL.getCode());
                    if (quotaDisburse.getReviewFinancingInfo() != null && quotaDisburse.getReviewFinancingInfo().getFinancingAmount() != null) {
                        financingBasicInfo.setFinancingAmount(quotaDisburse.getReviewFinancingInfo().getFinancingAmount());
                    }
                    financingBasicInfoService.updateById(financingBasicInfo);
                } else if (ConstantConversionUtil.APPROVAL_RESULT_BACK.equals(quotaDisburse.getApprovalConclusion())) {
                    financingBasicInfo.setCurrentStage("");
                    financingBasicInfoService.updateById(financingBasicInfo);
                    //退回时，释放点占用的验收单货物
                    releaseAcceptanceGoodsInfo(financingBasicInfo);
                }
            }
        }
    }

    /**
     * 添加企业工商信息
     *
     * @param quotaDisburse
     */
    void addBusinessInfo(ReviewQuotaDisburse quotaDisburse) {
        Set<String> enterpriseCodes = new HashSet();
        if (quotaDisburse.getRltRepayList() != null) {
            List<String> guaranteeEnterpriseCodeList = quotaDisburse.getRltRepayList().stream()
                    .filter(s -> ConstantConversionUtil.IDENTITY_TYPE2.equals(s.getArlpIdType())).map(ReviewRltRepay::getArlpCertNum).collect(Collectors.toList());
            enterpriseCodes.addAll(guaranteeEnterpriseCodeList);
        }
        if (quotaDisburse.getMortgageBasicInfoList() != null) {
            List<String> mortgageEnterpriseCodeList = quotaDisburse.getMortgageBasicInfoList().stream()
                    .filter(s -> ConstantConversionUtil.IDENTITY_TYPE2.equals(s.getMortgagorIdType())).map(ReviewMortgageBasicInfo::getMortgagorCertNum).collect(Collectors.toList());
            enterpriseCodes.addAll(mortgageEnterpriseCodeList);
        }
        if (enterpriseCodes.size() > 0) {
            enterpriseCodes.forEach(code -> {
                Enterprise enterprise = enterpriseService.getOne(new QueryWrapper<Enterprise>().eq("social_credit_code", code));
                if (enterprise == null) {
//                    enterpriseEntryService.addEnterpriseBycode(code);
                    List<Enterprise> enterpriseList = enterpriseService.getBusinessByKeyWord(code);
                    if (CollectionUtil.isEmpty(enterpriseList)) {
                        throw new ValidatorException(CodeUtil.FAIL, "添加企业出错");
                    } else if (enterpriseList.size() > 1) {
                        throw new ValidatorException(CodeUtil.FAIL, "添加企业出错");
                    } else {
                        enterprise = enterpriseList.get(0);
                        enterpriseService.save(enterprise);
                        //给sop 推数据   更新企业信息
                        EnterpriseEntry enterpriseEntry = new EnterpriseEntry();
                        enterpriseEntry.setFlag("0");
                        enterpriseEntry.setKeyWord(enterprise.getCorporateName());
                        Dictionary dictionary = new Dictionary();
                        dictionary.setId(197L);
                        enterpriseEntry.setInterfaceType(dictionary);
                        List list = new ArrayList<>();
                        list.add(18L);
                        list.add(25L);
                        enterpriseEntry.setInterfaceIdList(list);
                        ResponseJson entRj;
                        try {
                            entRj = restTemplate.postForObject(addBusiness, enterpriseEntry, ResponseJson.class);
                        } catch (Exception e) {
                            throw new ServiceException(CodeUtil.FAIL, "网络异常，请稍后重试！");
                        }
                        JSONObject jsonObject = new JSONObject(entRj.getData());
                        Boolean authStatus = jsonObject.getBool("authStatus");
                        String shortAuthUrl = jsonObject.getStr("shortAuthUrl");
                        String authUrl = jsonObject.getStr("authUrl");
                        Integer certificateSignStatus = jsonObject.getInt("certificateSignStatus");
                        String certificateShortSignUrl = jsonObject.getStr("certificateShortSignUrl");
                        String certificateSignUrl = jsonObject.getStr("certificateSignUrl");
                        Integer autoSignStatus = jsonObject.getInt("autoSignStatus");
                        String shortAutoSignUrl = jsonObject.getStr("shortAutoSignUrl");
                        String autoSignUrl = jsonObject.getStr("autoSignUrl");
                        String fddCustomerId = jsonObject.getStr("fddCustomerId");
                        String certificateContractId = jsonObject.getStr("certificateContractId");
                        String certificateTransactionId = jsonObject.getStr("certificateTransactionId");
                        enterprise.setCertificateTransactionId(certificateTransactionId);
                        enterprise.setAuthStatus(authStatus);
                        enterprise.setShortAuthUrl(shortAuthUrl);
                        enterprise.setCertificateSignStatus(certificateSignStatus);
                        enterprise.setCertificateShortSignUrl(certificateShortSignUrl);
                        enterprise.setAuthUrl(authUrl);
                        enterprise.setCertificateSignUrl(certificateSignUrl);
                        enterprise.setAutoSignStatus(autoSignStatus);
                        enterprise.setAutoSignUrl(autoSignUrl);
                        enterprise.setShortAutoSignUrl(shortAutoSignUrl);
                        enterprise.setFddCustomerId(fddCustomerId);
                        enterprise.setCertificateContractId(certificateContractId);
                        enterpriseService.updateById(enterprise);
                    }
                }
            });
        }
    }

    /**
     * 释放占用的验收单货物
     *
     * @param financingBasicInfo
     */
    private void releaseAcceptanceGoodsInfo(CFinancingBasicInfo financingBasicInfo) {
        List<CFinancingGoodsInfo> financingGoodsInfoList = financingGoodsInfoService.list(new QueryWrapper<CFinancingGoodsInfo>()
                .eq("c_financing_basic_info_id", financingBasicInfo.getId()));
        if (CollectionUtil.isNotEmpty(financingGoodsInfoList)) {
            List<CAcceptanceGoodsInfo> goodsInfoList = financingGoodsInfoList.stream().filter(goods -> goods.getAcceptanceGoodsInfoId() != null)
                    .map(goods -> acceptanceGoodsInfoService.getById(goods.getAcceptanceGoodsInfoId())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(goodsInfoList)) {
                for (CAcceptanceGoodsInfo acceptanceGoodsInfo : goodsInfoList) {
                    acceptanceGoodsInfoService.lambdaUpdate().eq(CAcceptanceGoodsInfo::getId, acceptanceGoodsInfo.getId())
                            .set(CAcceptanceGoodsInfo::getFinancing, false).update();
                }
            }
        }
    }

    /**
     * 保存历史信息
     *
     * @param quotaDisburse
     * @return
     */
    private Long addHistory(ReviewQuotaDisburse quotaDisburse) {

        //保存主表历史信息
        ReviewQuotaDisburseHis reviewQuotaDisburseHis = new ReviewQuotaDisburseHis();
        BeanUtils.copyProperties(quotaDisburse, reviewQuotaDisburseHis, "id");
        reviewQuotaDisburseHis.setReviewQuotaDisburseId(quotaDisburse.getId());
        reviewQuotaDisburseHisService.save(reviewQuotaDisburseHis);
        // 融资信息
        if (ConstantConversionUtil.APPROVAL_RESULT_PASS.equals(quotaDisburse.getApprovalConclusion())) {
            ReviewFinancingInfo financingInfo = reviewFinancingInfoService.getOne(new QueryWrapper<ReviewFinancingInfo>().eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (financingInfo != null) {
                ReviewFinancingInfoHis reviewFinancingInfoHis = new ReviewFinancingInfoHis();
                BeanUtils.copyProperties(financingInfo, reviewFinancingInfoHis, "id");
                reviewFinancingInfoHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                reviewFinancingInfoHisService.save(reviewFinancingInfoHis);
            }
            // 填充收支计划信息
            List<ReviewIncomeExpenditurePlan> list = reviewIncomeExpenditurePlanService.list(new QueryWrapper<ReviewIncomeExpenditurePlan>().eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (list != null && list.size() > 0) {
                for (ReviewIncomeExpenditurePlan reviewIncomeExpenditurePlan : list) {
                    ReviewIncomeExpenditurePlanHis reviewIncomeExpenditurePlanHis = new ReviewIncomeExpenditurePlanHis();
                    BeanUtils.copyProperties(reviewIncomeExpenditurePlan, reviewIncomeExpenditurePlanHis, "id");
                    reviewIncomeExpenditurePlanHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                    reviewIncomeExpenditurePlanHisService.save(reviewIncomeExpenditurePlanHis);
                }
            }
            // 填充主合同信息
            ReviewMasterContract masterContract = reviewMasterContractService.getOne(new QueryWrapper<ReviewMasterContract>()
                    .eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (null != masterContract) {
                ReviewMasterContractHis reviewMasterContractHis = new ReviewMasterContractHis();
                BeanUtils.copyProperties(masterContract, reviewMasterContractHis, "id");
                reviewMasterContractHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                reviewMasterContractHisService.save(reviewMasterContractHis);
                List<ReviewMasterContractDebtor> reviewMasterContractDebtorList = reviewMasterContractDebtorService.list(new QueryWrapper<ReviewMasterContractDebtor>().eq("review_master_contract_id", masterContract.getId()));
                if (null != reviewMasterContractDebtorList && reviewMasterContractDebtorList.size() > 0) {
                    for (ReviewMasterContractDebtor reviewMasterContractDebtor : reviewMasterContractDebtorList) {
                        ReviewMasterContractDebtorHis debtorHis = new ReviewMasterContractDebtorHis();
                        BeanUtils.copyProperties(reviewMasterContractDebtor, debtorHis, "id");
                        debtorHis.setReviewMasterContractHisId(reviewMasterContractHis.getId());
                        reviewMasterContractDebtorHisService.save(debtorHis);
                    }
                }
            }

            // 填充应收转让信息
            ReviewTransferReceivable transferReceivable = reviewTransferReceivableService.getOne(new QueryWrapper<ReviewTransferReceivable>()
                    .eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (null != transferReceivable) {
                ReviewTransferReceivableHis transferReceivableHis = new ReviewTransferReceivableHis();
                BeanUtils.copyProperties(transferReceivable, transferReceivableHis, "id");
                transferReceivableHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                reviewTransferReceivableHisService.save(transferReceivableHis);
            }

            // 填充基础交易合同信息
            List<ReviewBasicContract> reviewBasicContracts = reviewBasicContractService.list(new QueryWrapper<ReviewBasicContract>()
                    .eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (null != reviewBasicContracts && reviewBasicContracts.size() > 0) {
                for (ReviewBasicContract reviewBasicContract : reviewBasicContracts) {
                    ReviewBasicContractHis reviewBasicContractHis = new ReviewBasicContractHis();
                    BeanUtils.copyProperties(reviewBasicContract, reviewBasicContractHis, "id");
                    reviewBasicContractHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                    reviewBasicContractHisService.save(reviewBasicContractHis);

                    List<ReviewBasicContractChangeContent> reviewBasicContractChangeContentList = reviewBasicContractChangeContentService.list(new QueryWrapper<ReviewBasicContractChangeContent>()
                            .eq("review_basic_contract_id", reviewBasicContract.getId()));
                    if (reviewBasicContractChangeContentList != null && reviewBasicContractChangeContentList.size() > 0) {
                        for (ReviewBasicContractChangeContent reviewBasicContractChangeContent : reviewBasicContractChangeContentList) {
                            ReviewBasicContractChangeContentHis contractChangeContentHis = new ReviewBasicContractChangeContentHis();
                            BeanUtils.copyProperties(reviewBasicContractChangeContent, contractChangeContentHis, "id");
                            contractChangeContentHis.setReviewBasicContractHisId(reviewBasicContractHis.getId());
                            reviewBasicContractChangeContentHisService.save(contractChangeContentHis);
                        }
                    }
                }
            }
//        // 填充授信信息
//        ReviewCreditInfo creditInfo = reviewCreditInfoService.getReviewCreditInfoForView(entityId);
//        if (null != creditInfo) {
//            creditInfo.setReviewQuotaDisburse(quotaDisburse);
//            reviewCreditInfoService.addReviewCreditInfoHistory(creditInfo);
//        }
            // 2021.7.18新增 填充相关还款责任人信息
            List<ReviewRltRepay> reviewRltRepayList = reviewRltRepayService.list(new QueryWrapper<ReviewRltRepay>().eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (null != reviewRltRepayList && reviewRltRepayList.size() > 0) {
                for (ReviewRltRepay reviewRltRepay : reviewRltRepayList) {
                    ReviewRltRepayHis reviewRltRepayHis = new ReviewRltRepayHis();
                    BeanUtils.copyProperties(reviewRltRepay, reviewRltRepayHis, "id");
                    reviewRltRepayHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                    reviewRltRepayHisService.save(reviewRltRepayHis);
                    //保存附件
                    List<ReviewGuaranteeFile> reviewGuaranteeFiles = reviewGuaranteeSecondFileService.lambdaQuery().eq(ReviewGuaranteeFile::getGuaranteeId, reviewRltRepay.getId())
                            .eq(ReviewGuaranteeFile::getGuaranteeFileType, ConstantConversionUtil.GUARANTEEINFO_FILE).list();
                    if (CollectionUtil.isNotEmpty(reviewGuaranteeFiles)) {
                        reviewGuaranteeFiles.forEach(reviewGuaranteeSecondFile -> {
                            ReviewGuaranteeFileHis reviewGuaranteeFileHis = new ReviewGuaranteeFileHis();
                            reviewGuaranteeFileHis.setFileId(reviewGuaranteeSecondFile.getFileId());
                            reviewGuaranteeFileHis.setGuaranteeFileType(reviewGuaranteeSecondFile.getGuaranteeFileType());
                            reviewGuaranteeFileHis.setGuaranteeId(reviewRltRepayHis.getId());
                            reviewGuaranteeSecondFileHistoryService.save(reviewGuaranteeFileHis);
                        });
                    }
                    // 新增房产信息
                    List<ReviewRltRepayEstate> reviewRltRepayEstates = reviewRltRepayEstateService.lambdaQuery().eq(ReviewRltRepayEstate::getReviewRltRepayId, reviewRltRepay.getId()).list();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayEstates)) {
                        reviewRltRepayEstates.forEach(reviewRltRepayEstate -> {
                            ReviewRltRepayEstateHistory reviewRltRepayEstateHistory = new ReviewRltRepayEstateHistory();
                            BeanUtils.copyProperties(reviewRltRepayEstate, reviewRltRepayEstateHistory, "id");
                            reviewRltRepayEstateHistory.setReviewRltRepayId(reviewRltRepayHis.getId());
                            reviewRltRepayEstateHistoryService.save(reviewRltRepayEstateHistory);
                        });
                    }
                    // 新增土地信息
                    List<ReviewRltRepayLand> reviewRltRepayLands = reviewRltRepayLandService.lambdaQuery().eq(ReviewRltRepayLand::getReviewRltRepayId, reviewRltRepay.getId()).list();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayLands)) {
                        reviewRltRepayLands.forEach(reviewRltRepayLand -> {
                            ReviewRltRepayLandHistory reviewRltRepayLandHistory = new ReviewRltRepayLandHistory();
                            BeanUtils.copyProperties(reviewRltRepayLand, reviewRltRepayLandHistory, "id");
                            reviewRltRepayLandHistory.setReviewRltRepayId(reviewRltRepayHis.getId());
                            reviewRltRepayLandHistoryService.save(reviewRltRepayLandHistory);
                        });
                    }
                    // 新增车辆信息
                    List<ReviewRltRepayVehicle> reviewRltRepayVehicles = reviewRltRepayVehicleService.lambdaQuery().eq(ReviewRltRepayVehicle::getReviewRltRepayId, reviewRltRepay.getId()).list();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayVehicles)) {
                        reviewRltRepayVehicles.forEach(reviewRltRepayVehicle -> {
                            ReviewRltRepayVehicleHistory reviewRltRepayVehicleHistory = new ReviewRltRepayVehicleHistory();
                            BeanUtils.copyProperties(reviewRltRepayVehicle, reviewRltRepayVehicleHistory, "id");
                            reviewRltRepayVehicleHistory.setReviewRltRepayId(reviewRltRepayHis.getId());
                            reviewRltRepayVehicleHistoryService.save(reviewRltRepayVehicleHistory);
                        });
                    }
                    // 新增股权资产信息
                    List<ReviewRltRepayEquityAssets> reviewRltRepayEquityAssets = reviewRltRepayEquityAssetsService.lambdaQuery().eq(ReviewRltRepayEquityAssets::getReviewRltRepayId, reviewRltRepay.getId()).list();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayEquityAssets)) {
                        reviewRltRepayEquityAssets.forEach(reviewRltRepayEquityAsset -> {
                            ReviewRltRepayEquityAssetsHistory reviewRltRepayEquityAssetsHistory = new ReviewRltRepayEquityAssetsHistory();
                            BeanUtils.copyProperties(reviewRltRepayEquityAsset, reviewRltRepayEquityAssetsHistory, "id");
                            reviewRltRepayEquityAssetsHistory.setReviewRltRepayId(reviewRltRepayHis.getId());
                            reviewRltRepayEquityAssetsHistoryService.save(reviewRltRepayEquityAssetsHistory);
                        });
                    }
                    // 新增其他资产信息
                    List<ReviewRltRepayOtherAssets> reviewRltRepayOtherAssets = reviewRltRepayOtherAssetsService.lambdaQuery().eq(ReviewRltRepayOtherAssets::getReviewRltRepayId, reviewRltRepay.getId()).list();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayOtherAssets)) {
                        reviewRltRepayOtherAssets.forEach(reviewRltRepayOtherAsset -> {
                            ReviewRltRepayOtherAssetsHistory reviewRltRepayOtherAssetsHistory = new ReviewRltRepayOtherAssetsHistory();
                            BeanUtils.copyProperties(reviewRltRepayOtherAsset, reviewRltRepayOtherAssetsHistory, "id");
                            reviewRltRepayOtherAssetsHistory.setReviewRltRepayId(reviewRltRepayHis.getId());
                            reviewRltRepayOtherAssetsHistoryService.save(reviewRltRepayOtherAssetsHistory);
                        });
                    }
                }
            }
            //新增 填充抵质押信息
            List<ReviewQuotaMortgageRel> quotaMortgageRelList = reviewQuotaMortgageRelService.list(new QueryWrapper<ReviewQuotaMortgageRel>().eq("review_quota_disburse_id", quotaDisburse.getId()));
            if (quotaMortgageRelList != null && !quotaMortgageRelList.isEmpty()) {
                for (ReviewQuotaMortgageRel quotaMortgageRel : quotaMortgageRelList) {
                    ReviewMortgageBasicInfo mortgageBasicInfo = reviewMortgageBasicInfoService.getById(quotaMortgageRel.getReviewMortgageBasicId());
                    Long mortgageBasicInfoId = mortgageBasicInfo.getId();
                    if (mortgageBasicInfo != null && mortgageBasicInfo.getId() != null) {
                        ReviewMortgageBasicInfoHis reviewMortgageBasicInfoHis = new ReviewMortgageBasicInfoHis();
                        BeanUtils.copyProperties(mortgageBasicInfo, reviewMortgageBasicInfoHis, "id");
                        reviewMortgageBasicInfoHisService.save(reviewMortgageBasicInfoHis);

                        ReviewQuotaMortgageRelHis reviewQuotaMortgageRelHis = new ReviewQuotaMortgageRelHis();
                        reviewQuotaMortgageRelHis.setReviewQuotaDisburseHisId(reviewQuotaDisburseHis.getId());
                        reviewQuotaMortgageRelHis.setReviewMortgageBasicHisId(reviewMortgageBasicInfoHis.getId());
                        reviewQuotaMortgageRelHisService.save(reviewQuotaMortgageRelHis);

                        //获取抵押物信息
                        List<ReviewMortgageCollateralInfo> collateralInfoList = reviewMortgageCollateralInfoService.list(new QueryWrapper<ReviewMortgageCollateralInfo>()
                                .eq("review_mortgage_basic_id", mortgageBasicInfoId));
                        if (collateralInfoList != null && collateralInfoList.size() > 0) {
                            for (ReviewMortgageCollateralInfo reviewMortgageCollateralInfo : collateralInfoList) {
                                ReviewMortgageCollateralInfoHis reviewMortgageCollateralInfoHis = new ReviewMortgageCollateralInfoHis();
                                BeanUtils.copyProperties(reviewMortgageCollateralInfo, reviewMortgageCollateralInfoHis, "id");
                                reviewMortgageCollateralInfoHis.setReviewMortgageBasicHisId(reviewMortgageBasicInfoHis.getId());
                                reviewMortgageCollateralInfoHisService.save(reviewMortgageCollateralInfoHis);
                                //保存附件
                                List<ReviewGuaranteeFile> reviewGuaranteeFiles = reviewGuaranteeSecondFileService.lambdaQuery().eq(ReviewGuaranteeFile::getGuaranteeId, reviewMortgageCollateralInfo.getId())
                                        .eq(ReviewGuaranteeFile::getGuaranteeFileType, ConstantConversionUtil.CHATTELMORTGAGE_FILE).list();
                                if (CollectionUtil.isNotEmpty(reviewGuaranteeFiles)) {
                                    reviewGuaranteeFiles.forEach(reviewGuaranteeSecondFile -> {
                                        ReviewGuaranteeFileHis reviewGuaranteeFileHis = new ReviewGuaranteeFileHis();
                                        reviewGuaranteeFileHis.setFileId(reviewGuaranteeSecondFile.getFileId());
                                        reviewGuaranteeFileHis.setGuaranteeFileType(reviewGuaranteeSecondFile.getGuaranteeFileType());
                                        reviewGuaranteeFileHis.setGuaranteeId(reviewMortgageCollateralInfoHis.getId());
                                        reviewGuaranteeSecondFileHistoryService.save(reviewGuaranteeFileHis);
                                    });
                                }
                            }
                        }
                        //获取质押物信息
                        List<ReviewMortgagePledgeInfo> pledgeInfoList = reviewMortgagePledgeInfoService.list(new QueryWrapper<ReviewMortgagePledgeInfo>()
                                .eq("review_mortgage_basic_id", mortgageBasicInfoId));
                        if (pledgeInfoList != null && pledgeInfoList.size() > 0) {
                            for (ReviewMortgagePledgeInfo reviewMortgagePledgeInfo : pledgeInfoList) {
                                ReviewMortgagePledgeInfoHis reviewMortgagePledgeInfoHis = new ReviewMortgagePledgeInfoHis();
                                BeanUtils.copyProperties(reviewMortgagePledgeInfo, reviewMortgagePledgeInfoHis, "id");
                                reviewMortgagePledgeInfoHis.setReviewMortgageBasicHisId(reviewMortgageBasicInfoHis.getId());
                                reviewMortgagePledgeInfoHisService.save(reviewMortgagePledgeInfoHis);
                                //保存附件
                                List<ReviewGuaranteeFile> reviewGuaranteeFiles = reviewGuaranteeSecondFileService.lambdaQuery().eq(ReviewGuaranteeFile::getGuaranteeId, reviewMortgagePledgeInfo.getId())
                                        .eq(ReviewGuaranteeFile::getGuaranteeFileType, ConstantConversionUtil.PLEDGEINFORMATION_FILE).list();
                                if (CollectionUtil.isNotEmpty(reviewGuaranteeFiles)) {
                                    reviewGuaranteeFiles.forEach(reviewGuaranteeSecondFile -> {
                                        ReviewGuaranteeFileHis reviewGuaranteeFileHis = new ReviewGuaranteeFileHis();
                                        reviewGuaranteeFileHis.setFileId(reviewGuaranteeSecondFile.getFileId());
                                        reviewGuaranteeFileHis.setGuaranteeFileType(reviewGuaranteeSecondFile.getGuaranteeFileType());
                                        reviewGuaranteeFileHis.setGuaranteeId(reviewMortgagePledgeInfoHis.getId());
                                        reviewGuaranteeSecondFileHistoryService.save(reviewGuaranteeFileHis);
                                    });
                                }
                            }
                        }
                    }
                    // 填充附件信息
                    List<ReviewGuaranteeFile> reviewGuaranteeFiles = reviewGuaranteeSecondFileService.lambdaQuery().eq(ReviewGuaranteeFile::getGuaranteeId, mortgageBasicInfoId)
                            .eq(ReviewGuaranteeFile::getGuaranteeFileType, ConstantConversionUtil.MORTGAGEINFORMATION_FILE).list();
                    if (CollectionUtil.isNotEmpty(reviewGuaranteeFiles)) {
                        reviewGuaranteeFiles.forEach(reviewGuaranteeSecondFile -> {
                            ReviewGuaranteeFileHis reviewGuaranteeFileHis = new ReviewGuaranteeFileHis();
                            reviewGuaranteeFileHis.setFileId(reviewGuaranteeSecondFile.getFileId());
                            reviewGuaranteeFileHis.setGuaranteeFileType(reviewGuaranteeSecondFile.getGuaranteeFileType());
                            reviewGuaranteeFileHis.setGuaranteeId(mortgageBasicInfo.getId());
                            reviewGuaranteeSecondFileHistoryService.save(reviewGuaranteeFileHis);
                        });
                    }
                }
            }
        }

        return reviewQuotaDisburseHis.getId();
    }

    /**
     * 修改合同名称
     *
     * @param quotaDisburse
     */
    private void doUpdateMasterContractName(ReviewQuotaDisburse quotaDisburse) {
        ReviewMasterContract masterContract = quotaDisburse.getReviewMasterContract();
        if (masterContract != null) {
            //贸理通默认池保理
            UpdateWrapper<ReviewMasterContract> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", masterContract.getId());
            updateWrapper.set("contract_name", "池保理业务合同");
            reviewMasterContractService.update(updateWrapper);
        }
    }

    /**
     * 验证额度支用数据合法性
     */
    public void checkQuotaDisburseLegality(ReviewQuotaDisburse quota) {
        boolean visible = quota.isVisible();
        ReviewFinancingInfo financingInfo = quota.getReviewFinancingInfo();
        BigDecimal zero = BigDecimal.ZERO;
        BigDecimal maxAmount = new BigDecimal("999999999999999.99");
        // 验证融资信息
        if (visible) {
            if (null != financingInfo) {
                // 授信金额
                BigDecimal financingAmount = financingInfo.getFinancingAmount() != null
                        ? financingInfo.getFinancingAmount()
                        : new BigDecimal(0);
                if (financingAmount.compareTo(zero) < 0 || financingAmount.compareTo(maxAmount) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【融资金额】必须在0～999999999999999.99之间");
                }
                // 最大比例
                BigDecimal maxRatio = new BigDecimal("100");
                // 融资利率
                BigDecimal rate = new BigDecimal(String.valueOf(financingInfo.getFinancingRate()));
                if (rate.compareTo(zero) < 0 || rate.compareTo(maxRatio) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【融资利率】必须满足：0%<=融资利率<=100%");
                }
                // 融资比例
                BigDecimal ratio = new BigDecimal(String.valueOf(financingInfo.getFinancingRatio()));
                if (ratio.compareTo(zero) < 0 || ratio.compareTo(maxRatio) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【融资比例】必须满足：0%<=融资比例<=100%");
                }
                // 对外综合报价
                BigDecimal quotation = new BigDecimal(String.valueOf(financingInfo.getComprehensiveQuotation()));
                if (quotation.compareTo(zero) < 0 || quotation.compareTo(new BigDecimal("1000")) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【对外综合报价】必须满足：0%<=对外综合报价<=1000%");
                }
                // 逾期利率
                BigDecimal overdue = new BigDecimal(String.valueOf(financingInfo.getOverdueInterestRate()));
                if (overdue.compareTo(zero) < 0 || overdue.compareTo(maxRatio) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【逾期利率】必须满足：0%<=对外综合报价<=100%");
                }
                // 管理费比例
                BigDecimal feeRatio = new BigDecimal(String.valueOf(financingInfo.getManagementFeeRatio()));
                if (feeRatio.compareTo(zero) < 0 || feeRatio.compareTo(maxRatio) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【管理费比例】必须满足：0%<=管理费比例<=100%");
                }
                // 保证金比例
                BigDecimal marginRatio = new BigDecimal(String.valueOf(financingInfo.getMarginRatio()));
                if (marginRatio.compareTo(zero) < 0 || marginRatio.compareTo(maxRatio) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【保证金比例】必须满足：0%<=保证金比例<=100%");
                }
                // 融资利息
                BigDecimal interest = financingInfo.getFinancingInterest() != null ? financingInfo.getFinancingInterest()
                        : new BigDecimal(0);
                if (interest.compareTo(zero) < 0 || interest.compareTo(maxAmount) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【融资利息】必须在0～999999999999999.99之间");
                }
                // 管理费金额
                BigDecimal feeAmount = financingInfo.getManagementFeeAmount() != null
                        ? financingInfo.getManagementFeeAmount()
                        : new BigDecimal(0);
                if (feeAmount.compareTo(zero) < 0 || feeAmount.compareTo(maxAmount) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【管理费金额】必须在0～999999999999999.99之间");
                }
                // 保证金金额
                BigDecimal marginAmount = financingInfo.getMarginAmount() != null ? financingInfo.getMarginAmount()
                        : new BigDecimal(0);
                if (marginAmount.compareTo(zero) < 0 || marginAmount.compareTo(maxAmount) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【保证金金额】必须在0～999999999999999.99之间");
                }
                // 其他费用金额
                BigDecimal otherAmount = financingInfo.getOtherFeeAmount() != null ? financingInfo.getOtherFeeAmount()
                        : new BigDecimal(0);
                if (otherAmount.compareTo(zero) < 0 || otherAmount.compareTo(maxAmount) > 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资信息中【其他费用金额】必须在0～999999999999999.99之间");
                }
            }
            // 验证收支计划合法性
            List<ReviewIncomeExpenditurePlan> planList = quota.getIncomeExpenditurePlanList();
            // 如果是提交验证收支计划不能为空

            if (planList == null || planList.size() == 0) {
                throw new ValidatorException(CodeUtil.FAIL, "收支计划信息不能为空");
            }

            boolean flag = false;

            int principalLoan = 0;
            // 验证数据的合法性
            if (null != planList && planList.size() > 0) {
                int recordNo = 0;
                for (ReviewIncomeExpenditurePlan plan : planList) {
                    recordNo++;
                    // 收款
                    BigDecimal receivables = plan.getReceivables();
                    if (null != receivables) {
                        if (receivables.compareTo(zero) <= 0 || receivables.compareTo(maxAmount) > 0) {
                            throw new ValidatorException(CodeUtil.FAIL,
                                    "收支计划中收支计划中【序号为" + recordNo + "的【收款】金额在必须大于0～999999999999999.99之间】");
                        }
                    }
                    // 放款
                    BigDecimal loan = plan.getLoan();
                    if (null != loan) {
                        if (loan.compareTo(zero) <= 0 || loan.compareTo(maxAmount) > 0) {
                            throw new ValidatorException(CodeUtil.FAIL,
                                    "收支计划中【序号为" + recordNo + "的【放款】金额必须在大于0～999999999999999.99之间】");
                        }
                    }
                    // 提交时，验证数据是否为空
                    if (null == plan.getIncomeExpenditureDate()) {
                        throw new ValidatorException(CodeUtil.FAIL, "收支计划中【序号为" + recordNo + "的“收支日期”不能为空】");
                    }
                    if (StringUtil.isBlank(plan.getIncomeExpenditureType())) {
                        throw new ValidatorException(CodeUtil.FAIL, "收支计划中【序号为" + recordNo + "的“类型”不能为空】");
                    }
                    String code = plan.getIncomeExpenditureType();
                    if (code.equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode())) {
                        flag = true;
                    }
                    // 本金类的、保证金
                    if (code.equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode())
                            || code.equals(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode())) {
                        if (null == plan.getLoan() && null == plan.getReceivables()) {
                            throw new ValidatorException(CodeUtil.FAIL, "收支计划中【序号为" + recordNo + "的记录中，至少要有一个收款或放款金额】");
                        }
                        if (null != plan.getReceivables()) {
                            if (StringUtil.isEmpty(plan.getReceivingSubject())) {
                                throw new ValidatorException(CodeUtil.FAIL, "收支计划中【序号为" + recordNo + "的记录中，收款主体不能为空】");
                            }
                        }
                    }
                    // 利息类的、管理费、其他费用
                    if (code.equals(IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode())
                            || code.equals(IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode())
                            || code.equals(IncomeExpenditureTypeDict.ChildEnum.OTHER_FEE.getCode())) {
                        if (null == plan.getReceivables()) {
                            throw new ValidatorException(CodeUtil.FAIL, "收支计划中【序号为" + recordNo + "的记录中“收款金额”不能为空】");
                        }
                        if (null != plan.getReceivables()) {
                            if (StringUtil.isEmpty(plan.getReceivingSubject())) {
                                throw new ValidatorException(CodeUtil.FAIL, "收支计划中【序号为" + recordNo + "的记录中“收款主体”不能为空】");
                            }
                        }
                    }
                    //验证账户上报方式如果是B类，相关还款责任人中不能为A类
                    if (quota.getReportMethod() != null && quota.getReportMethod().equals(0)) {
                        if (quota.getRltRepayList() != null) {
                            List<ReviewRltRepay> rltRepayList = quota.getRltRepayList();
                            for (ReviewRltRepay rltRepay : rltRepayList) {
                                if (rltRepay.getResponsibleReportMethod().equals(1)) {
                                    throw new ValidatorException(CodeUtil.FAIL, "账户上报方式为B类，相关还款责任人中的上报方式不能为A类");
                                }
                            }
                        }
                    }
                    //本金放款
                    if (code.equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode()) && loan != null) {
                        principalLoan++;
                    }
                    //2023.8.23 校验最后一笔本金收款的约定日期+7个自然日要小于支用到期日
                    ReviewIncomeExpenditurePlan reviewIncomeExpenditurePlan = planList.stream().filter(p -> p.getReceivables() != null && IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode().equals(p.getIncomeExpenditureType()))
                            .max(Comparator.comparing(ReviewIncomeExpenditurePlan::getIncomeExpenditureDate)).get();
                    if (reviewIncomeExpenditurePlan != null && quota.getReviewFinancingInfo() != null && quota.getReviewFinancingInfo().getDisburseExpiryDate() != null) {
                        Date maxDate = com.sunxung.factoring.component.util.DateUtil.addDay(reviewIncomeExpenditurePlan.getIncomeExpenditureDate(), 7);
                        Date disburseExpiryDate = quota.getReviewFinancingInfo().getDisburseExpiryDate();
                        if (maxDate.compareTo(disburseExpiryDate) > 0) {
                            throw new ValidatorException(CodeUtil.FAIL, "最后一笔本金收款的约定日期+7个自然日要小于支用到期日");
                        }
                    }

                }
            }
            //2023.3.9 add 验证还款方式不为手动生成时，收支计划只能有一笔本金放款计划
            String payBackMethod = financingInfo.getPayBackMethod();
            if (StringUtil.isBlank(payBackMethod)) {
                throw new ValidatorException(CodeUtil.FAIL, "融资信息->还款方式不能为空");
            }
            if (principalLoan != 1) {
                throw new ValidatorException(CodeUtil.FAIL, "还款方式不是手动生成时、收支计划中本金放款记录只能为一条");
            }
            if (!flag) {
                throw new ValidatorException(CodeUtil.FAIL, "收支计划中必须得有【本金】类型的计划");
            }
        }
    }

    /**
     * 新增额度支用信息
     */
    public ReviewQuotaDisburse add(ReviewQuotaDisburse reviewQuotaDisburse, CFinancingBasicInfo financingBasicInfo) throws IOException {

        if (reviewQuotaDisburse.isVisible()
                && ConstantConversionUtil.APPROVAL_RESULT_PASS.equals(reviewQuotaDisburse.getApprovalConclusion())) {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.ADD, reviewQuotaDisburse);
            int batch = quotaDisburseMapper.getMaxBatchByBusinessNo(reviewQuotaDisburse.getBusinessNumber());
            reviewQuotaDisburse.setQuotaDisburseBatch(batch + 1);
        } else {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.TEMP, reviewQuotaDisburse);
        }
        quotaDisburseMapper.insert(reviewQuotaDisburse);
        if (ConstantConversionUtil.APPROVAL_RESULT_PASS.equals(reviewQuotaDisburse.getApprovalConclusion())) {
            // 新增融资信息
            addFinancingInfo(reviewQuotaDisburse, financingBasicInfo);
            // 新增收支计划信息
            addIncomeExpenditurePlan(reviewQuotaDisburse);
            // 新增主合同信息
            addMasterContract(reviewQuotaDisburse);
            // 新增基础交易合同信息
            addBasicContract(reviewQuotaDisburse);
            // 新增应收账款转让信息
            addReviewTransferReceivable(reviewQuotaDisburse);
            // 新增相关还款责任人
            addReviewRltRepay(reviewQuotaDisburse);
            // 新增抵质押信息
            addMortgageInfo(reviewQuotaDisburse);
        }
        return reviewQuotaDisburse;
    }


    /**
     * 修改额度支用信息
     */
    @Transactional(rollbackFor = Exception.class)
    public ReviewQuotaDisburse update(ReviewQuotaDisburse reviewQuotaDisburse, CFinancingBasicInfo financingBasicInfo) throws IOException {
        if (reviewQuotaDisburse.isVisible()
                && ConstantConversionUtil.APPROVAL_RESULT_PASS.equals(reviewQuotaDisburse.getApprovalConclusion())) {
            ReviewQuotaDisburse hisQuotaDisburse = quotaDisburseMapper.selectById(reviewQuotaDisburse.getId());
//            if (null == hisQuotaDisburse || StringUtil.isEmpty(hisQuotaDisburse.getBusinessNumber())) {
//                throw new BusinessException(CodeUtil.FAIL, "修改额度支用时，业务编号不能为空");
//            }
//            String businessNo = hisQuotaDisburse.getBusinessNumber();
//            reviewQuotaDisburse.setBusinessNumber(businessNo);
            String businessNo = reviewQuotaDisburse.getBusinessNumber();
            //修复退回批次号改变的问题
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.UPDATE, reviewQuotaDisburse);
            if (hisQuotaDisburse.getQuotaDisburseBatch() == null) {
                int batch = quotaDisburseMapper.getMaxBatchByBusinessNo(businessNo);
                reviewQuotaDisburse.setQuotaDisburseBatch(batch + 1);
            } else {
                reviewQuotaDisburse.setQuotaDisburseBatch(hisQuotaDisburse.getQuotaDisburseBatch());
            }
        } else {
            ValidatorUtil.validator(ValidatorEntity.ValidatorType.TEMP, reviewQuotaDisburse);
        }
        quotaDisburseMapper.updateById(reviewQuotaDisburse);
        // 修改融资信息
        reviewFinancingInfoService.remove(new QueryWrapper<ReviewFinancingInfo>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        addFinancingInfo(reviewQuotaDisburse, financingBasicInfo);
        // 修改收支计划信息
        reviewIncomeExpenditurePlanService.remove(new QueryWrapper<ReviewIncomeExpenditurePlan>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        addIncomeExpenditurePlan(reviewQuotaDisburse);
        // 修改主合同信息
        reviewMasterContractService.remove(new QueryWrapper<ReviewMasterContract>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        addMasterContract(reviewQuotaDisburse);
        // 修改基础交易合同信息
        reviewBasicContractService.remove(new QueryWrapper<ReviewBasicContract>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        addBasicContract(reviewQuotaDisburse);
        // 修改应收账款转让信息
        reviewTransferReceivableService.remove(new QueryWrapper<ReviewTransferReceivable>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        addReviewTransferReceivable(reviewQuotaDisburse);
        //修改相关还款责任人信息
        List<ReviewRltRepay> oldRltRepas = reviewRltRepayService.list(new QueryWrapper<ReviewRltRepay>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        if (CollectionUtil.isNotEmpty(oldRltRepas)) {
            oldRltRepas.forEach(reviewRltRepay -> {
                // 删除房产信息
                reviewRltRepayEstateService.lambdaUpdate().eq(ReviewRltRepayEstate::getReviewRltRepayId, reviewRltRepay.getId()).remove();
                // 删除土地信息
                reviewRltRepayLandService.lambdaUpdate().eq(ReviewRltRepayLand::getReviewRltRepayId, reviewRltRepay.getId()).remove();
                // 删除车辆信息
                reviewRltRepayVehicleService.lambdaUpdate().eq(ReviewRltRepayVehicle::getReviewRltRepayId, reviewRltRepay.getId()).remove();
                // 删除股权资产信息
                reviewRltRepayEquityAssetsService.lambdaUpdate().eq(ReviewRltRepayEquityAssets::getReviewRltRepayId, reviewRltRepay.getId()).remove();
                // 删除其他资产信息
                reviewRltRepayOtherAssetsService.lambdaUpdate().eq(ReviewRltRepayOtherAssets::getReviewRltRepayId, reviewRltRepay.getId()).remove();
                // 删除附件
                reviewGuaranteeSecondFileService.lambdaUpdate().eq(ReviewGuaranteeFile::getGuaranteeId, reviewRltRepay.getId())
                        .eq(ReviewGuaranteeFile::getGuaranteeFileType, ConstantConversionUtil.MORTGAGEINFORMATION_FILE).remove();
            });
        }
        reviewRltRepayService.remove(new QueryWrapper<ReviewRltRepay>().eq("review_quota_disburse_id", reviewQuotaDisburse.getId()));
        addReviewRltRepay(reviewQuotaDisburse);
        //修改抵质押信息
        reviewMortgageBasicInfoService.deleteByQuotaDisburseId(reviewQuotaDisburse);
        addMortgageInfo(reviewQuotaDisburse);
        return reviewQuotaDisburse;
    }

    /**
     * 新增抵质押信息
     */
    private void addMortgageInfo(ReviewQuotaDisburse quotaDisburse) {
        if (null != quotaDisburse && null != quotaDisburse.getId()) {
            List<ReviewMortgageBasicInfo> list = quotaDisburse.getMortgageBasicInfoList();
            if (null != list && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    ReviewMortgageBasicInfo mortgageBasicInfo = list.get(i);
                    mortgageBasicInfo.setMortContrStatus(1); //默认设置合同状态为生效
                    if (mortgageBasicInfo.getGuarType() != null && ConstantUtil.COLLATERAL_TYPE.equals(mortgageBasicInfo.getGuarType())) {
                        // 合同类型为抵押
                        mortgageBasicInfo.setMortgageNo(createContractNo(quotaDisburse, i + 1, "C"));
                    } else if (mortgageBasicInfo.getGuarType() != null && ConstantUtil.PLEDGE_TYPE.equals(mortgageBasicInfo.getGuarType())) {
                        // 合同类型为质押
                        mortgageBasicInfo.setMortgageNo(createContractNo(quotaDisburse, i + 1, "P"));
                    }

                    reviewMortgageBasicInfoService.addMortgageInfo(mortgageBasicInfo, quotaDisburse);

//                    List<MultipartFile> multipartFiles = mortgageBasicInfo.getMultipartFiles();
                    List<Long> multipartFileIds = mortgageBasicInfo.getFileStorageListId();
                    if (CollectionUtil.isNotEmpty(multipartFileIds)) {
                        multipartFileIds.forEach(fileId -> {
                            ReviewGuaranteeFile reviewGuaranteeFile = new ReviewGuaranteeFile();
                            reviewGuaranteeFile.setFileId(fileId);
                            reviewGuaranteeFile.setGuaranteeFileType(ConstantConversionUtil.MORTGAGEINFORMATION_FILE);
                            reviewGuaranteeFile.setGuaranteeId(mortgageBasicInfo.getId());
                            reviewGuaranteeSecondFileService.save(reviewGuaranteeFile);
                        });
                    }
//                    if (CollectionUtil.isNotEmpty(multipartFiles)) {
//                        addSecondGuaranteeFile(mortgageBasicInfo.getId(), ConstantConversionUtil.MORTGAGEINFORMATION_FILE, multipartFiles);
//                    }
                }
            }
        }
    }

    /**
     * 新增相关还款责任人信息
     */
    private void addReviewRltRepay(ReviewQuotaDisburse quotaDisburse) {
        if (null != quotaDisburse && null != quotaDisburse.getId()) {
            List<ReviewRltRepay> list = quotaDisburse.getRltRepayList();
            if (null != list && list.size() > 0) {
                int i = 0;
                Dictionary arlpTypeDict = dictService.getByCode("arlpType_BZR");
                if (arlpTypeDict == null || arlpTypeDict.getId() == null) {
                    throw new ValidatorException(CodeUtil.FAIL, "相关还款责任人字典项不能为空");
                }
                for (ReviewRltRepay rltRepay : list) {
                    i = i + 1;
                    String number = createContractNo(quotaDisburse, i, "G");
                    rltRepay.setMaxGuarMcc(number);
                    Long guaranteeCardFrontFileStorageId = rltRepay.getGuaranteeCardFrontFileStorageId();
                    if (guaranteeCardFrontFileStorageId != null) {
                        rltRepay.setGuaranteeCardFrontFileStorageId(guaranteeCardFrontFileStorageId);
                    }

                    Long guaranteeCardReverseFileStorageId = rltRepay.getGuaranteeCardReverseFileStorageId();
                    if (guaranteeCardReverseFileStorageId != null) {
                        rltRepay.setGuaranteeCardReverseFileStorageId(guaranteeCardReverseFileStorageId);
                    }

                    Long spouseCardFrontFileStorageId = rltRepay.getSpouseCardFrontFileStorageId();
                    if (spouseCardFrontFileStorageId != null) {
                        rltRepay.setSpouseCardFrontFileStorageId(spouseCardFrontFileStorageId);
                    }

                    Long spouseCardReverseFileStorageId = rltRepay.getSpouseCardReverseFileStorageId();
                    if (spouseCardReverseFileStorageId != null) {
                        rltRepay.setSpouseCardReverseFileStorageId(spouseCardReverseFileStorageId);
                    }

                    rltRepay.setReviewQuotaDisburseId(quotaDisburse.getId());
                    String guaranteeObjectName = rltRepay.getGuaranteeObjectName();
                    if (guaranteeObjectName != null) {
                        Enterprise enterprise = enterpriseService.getOne(new QueryWrapper<Enterprise>().eq("corporate_name", guaranteeObjectName));
                        rltRepay.setGuaranteeObjectId(enterprise.getId());
                    }
                    reviewRltRepayService.save(rltRepay);
                    List<Long> fileStorageIds = rltRepay.getFileStorageIds();
                    //之前暂存的文件
                    if (CollectionUtil.isNotEmpty(fileStorageIds)) {
                        fileStorageIds.forEach(id -> {
                            ReviewGuaranteeFile reviewGuaranteeFile = new ReviewGuaranteeFile();
                            reviewGuaranteeFile.setFileId(id);
                            reviewGuaranteeFile.setGuaranteeFileType(ConstantConversionUtil.GUARANTEEINFO_FILE);
                            reviewGuaranteeFile.setGuaranteeId(rltRepay.getId());
                            reviewGuaranteeSecondFileService.save(reviewGuaranteeFile);
                        });
                    }

                    // 新增房产信息
                    List<ReviewRltRepayEstate> reviewRltRepayEstates = rltRepay.getReviewRltRepayEstates();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayEstates)) {
                        reviewRltRepayEstates.forEach(reviewRltRepayEstate -> {
                            if (StringUtil.isNotEmpty(reviewRltRepayEstate.getHouseAddressDoorNumber()) || StringUtil.isNotEmpty(reviewRltRepayEstate.getPurchaseContract())
                                    || StringUtil.isNotEmpty(reviewRltRepayEstate.getHousePropertyNo()) || reviewRltRepayEstate.getLoanBalance() != null) {
                                reviewRltRepayEstate.setReviewRltRepayId(rltRepay.getId());
                                reviewRltRepayEstateService.save(reviewRltRepayEstate);
                            }
                        });
                    }
                    // 新增土地信息
                    List<ReviewRltRepayLand> reviewRltRepayLands = rltRepay.getReviewRltRepayLands();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayLands)) {
                        reviewRltRepayLands.forEach(reviewRltRepayLand -> {
                            if (StringUtil.isNotEmpty(reviewRltRepayLand.getLocation()) || StringUtil.isNotEmpty(reviewRltRepayLand.getLandNo())
                                    || StringUtil.isNotEmpty(reviewRltRepayLand.getOriginalBookValue()) || StringUtil.isNotEmpty(reviewRltRepayLand.getArea())
                                    || StringUtil.isNotEmpty(reviewRltRepayLand.getLandNature()) || StringUtil.isNotEmpty(reviewRltRepayLand.getMortgageInstallment())
                                    || StringUtil.isNotEmpty(reviewRltRepayLand.getReamrk())) {
                                reviewRltRepayLand.setReviewRltRepayId(rltRepay.getId());
                                reviewRltRepayLandService.save(reviewRltRepayLand);
                            }
                        });
                    }
                    // 新增车辆信息
                    List<ReviewRltRepayVehicle> reviewRltRepayVehicles = rltRepay.getReviewRltRepayVehicles();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayVehicles)) {
                        reviewRltRepayVehicles.forEach(reviewRltRepayVehicle -> {
                            if (StringUtil.isNotEmpty(reviewRltRepayVehicle.getVehicleNameLicenseNo()) || reviewRltRepayVehicle.getPurchaseDate() != null
                                    || StringUtil.isNotEmpty(reviewRltRepayVehicle.getEngineNo()) || StringUtil.isNotEmpty(reviewRltRepayVehicle.getDrivingLicenseNo())
                                    || reviewRltRepayVehicle.getLoanBalance() != null) {
                                reviewRltRepayVehicle.setReviewRltRepayId(rltRepay.getId());
                                reviewRltRepayVehicleService.save(reviewRltRepayVehicle);
                            }
                        });
                    }
                    // 新增股权资产信息
                    List<ReviewRltRepayEquityAssets> reviewRltRepayEquityAssets = rltRepay.getReviewRltRepayEquityAssets();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayEquityAssets)) {
                        reviewRltRepayEquityAssets.forEach(reviewRltRepayEquityAsset -> {
                            if (StringUtil.isNotEmpty(reviewRltRepayEquityAsset.getCompanyName()) || reviewRltRepayEquityAsset.getRegisteredCapital() != null
                                    || reviewRltRepayEquityAsset.getInvestmentDate() != null || reviewRltRepayEquityAsset.getRatio() != null
                                    || reviewRltRepayEquityAsset.getInvestmentAmount() != null || StringUtil.isNotEmpty(reviewRltRepayEquityAsset.getPosition())
                                    || StringUtil.isNotEmpty(reviewRltRepayEquityAsset.getReport())) {
                                if (reviewRltRepayEquityAsset.getRatio() != null) {
                                    reviewRltRepayEquityAsset.setRatio(reviewRltRepayEquityAsset.getRatio().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));
                                }
                                reviewRltRepayEquityAsset.setReviewRltRepayId(rltRepay.getId());
                                reviewRltRepayEquityAssetsService.save(reviewRltRepayEquityAsset);
                            }
                        });
                    }
                    // 新增其他资产信息
                    List<ReviewRltRepayOtherAssets> reviewRltRepayOtherAssets = rltRepay.getReviewRltRepayOtherAssets();
                    if (CollectionUtil.isNotEmpty(reviewRltRepayOtherAssets)) {
                        reviewRltRepayOtherAssets.forEach(reviewRltRepayOtherAsset -> {
                            if (StringUtil.isNotEmpty(reviewRltRepayOtherAsset.getOtherAssets())) {
                                reviewRltRepayOtherAsset.setReviewRltRepayId(rltRepay.getId());
                                reviewRltRepayOtherAssetsService.save(reviewRltRepayOtherAsset);
                            }
                        });
                    }
                }
            }
        }
    }

    /**
     * 生成保证合同标识码
     */
    private String createContractNo(ReviewQuotaDisburse quotaDisburse, int seq, String mark) {
        // 获取合同编号
        String masterContractNo = "";
        String contractNo = null;
        if (null != quotaDisburse && quotaDisburse.isVisible()) {
            ReviewMasterContract masterContract = quotaDisburse.getReviewMasterContract();
            if (null != masterContract && StringUtil.isNotEmpty(masterContract.getContractNo())) {
                masterContractNo = masterContract.getContractNo();
            }
            if (StringUtil.isNotEmpty(masterContractNo)) {
                // 设置三方协议编号
                String quotaBatchStr;
                // 判断是新池还是已有池
                ReviewQuotaDisburse oldQuotaDisburse = quotaDisburseMapper.selectOne(new QueryWrapper<ReviewQuotaDisburse>()
                        .eq("business_number", quotaDisburse.getBusinessNumber())
                        .ne("id", quotaDisburse.getId())
                        .last("limit 1"));
                if (null == oldQuotaDisburse) {
                    //新池
                    quotaBatchStr = "01";
                } else {
                    int batch = this.count(new QueryWrapper<ReviewQuotaDisburse>().eq("business_number", quotaDisburse.getBusinessNumber())
                            .ne("id", quotaDisburse.getId())
                            .eq("visible", true));
                    quotaBatchStr = StringUtil.formatNumber(batch + 1);
                }
                contractNo = masterContractNo + "-" + quotaBatchStr + "-" + mark + seq;
            }
        }
        return contractNo;
    }

    /**
     * 担保类文件上传
     *
     * @param guaranteeId
     * @param guaranteeFileType
     * @param multipartFiles
     */
    private void addSecondGuaranteeFile(Long guaranteeId, String guaranteeFileType, List<MultipartFile> multipartFiles) {
        multipartFiles.forEach(multipartFile -> {
            try {
                FileStorage fileStorage = fileStorageService.addFileStorage(multipartFile, FileModuleDict.ChildEnum.REVIEW_QUOTA_DISBURSE);
                if (null != fileStorage) {
                    ReviewGuaranteeFile reviewGuaranteeFile = new ReviewGuaranteeFile();
                    reviewGuaranteeFile.setFileId(fileStorage.getId());
                    reviewGuaranteeFile.setGuaranteeFileType(guaranteeFileType);
                    reviewGuaranteeFile.setGuaranteeId(guaranteeId);
                    reviewGuaranteeSecondFileService.save(reviewGuaranteeFile);
                }
            } catch (IOException e) {
                log.error("额度支用上传担保类附件出错：" + e.getMessage());
                throw new BusinessException(CodeUtil.FAIL, e.getMessage());
            }
        });
    }

    /**
     * 新增应收账款转让信息
     */
    private void addReviewTransferReceivable(ReviewQuotaDisburse quotaDisburse) {
        if (null != quotaDisburse && null != quotaDisburse.getId()) {
            if (null != quotaDisburse.getReviewTransferReceivable()) {
                ReviewTransferReceivable receivable = quotaDisburse.getReviewTransferReceivable();
                receivable.setReviewQuotaDisburseId(quotaDisburse.getId());
                // 生产编号
                createConfirmationNo(quotaDisburse, true, receivable);
                //确权方式
                if (receivable.getConfirm() && CollectionUtil.isNotEmpty(receivable.getConfirmMethodList())) {
                    receivable.setConfirmMethod(StringUtils.join(receivable.getConfirmMethodList(), ConstantConversionUtil.MULTIPLE_SELECTION_SEPARATOR));
                }
                reviewTransferReceivableService.save(receivable);
            }
        }
    }

    /**
     * 生成确认书编号、通知书编号
     *
     * @param quotaDisburse 额度支用的实体类
     * @param b             是否有应收账款转让信息。并且点提交时，才生产确认书编号、通知书编号
     */
    public void createConfirmationNo(ReviewQuotaDisburse quotaDisburse, boolean b, ReviewTransferReceivable transfer) {
        // 获取合同编号
        String masterContractNo = "";
        ReviewMasterContract masterContract = quotaDisburse.getReviewMasterContract();
        if (null != masterContract && StringUtil.isNotEmpty(masterContract.getContractNo())) {
            masterContractNo = masterContract.getContractNo();
        }
        // 确认书编号
        String confirmationNo = null;
        // 通知书编号
        String noticeNo = null;
        if (StringUtil.isNotEmpty(masterContractNo) && quotaDisburse.isVisible() && b) {
            // 设置：确认书编号、转让通知书，注：通知书编号规则，若存在多个债务人，需要加后缀-01，-02，其中数字表示第几个债务人
            String batchStr;
            int batch = quotaDisburseMapper.getMaxBatchByBusinessNo(quotaDisburse.getBusinessNumber());
            batchStr = StringUtil.formatNumber(batch);
            confirmationNo = masterContractNo + "-" + batchStr + "-" + 1;
            noticeNo = masterContractNo + "-" + batchStr + "-" + 3;
        }
        transfer.setConfirmationNo(confirmationNo);
        transfer.setNoticeNo(noticeNo);
    }

    /**
     * 新增基础交易合同信息
     */
    private void addBasicContract(ReviewQuotaDisburse quotaDisburse) {
        if (null != quotaDisburse && null != quotaDisburse.getId()) {
            List<ReviewBasicContract> list = quotaDisburse.getReviewBasicContractList();
            if (null != list && list.size() > 0) {
                int i = 0;
                for (ReviewBasicContract contract : list) {
                    i = i + 1;
                    String number = createTripartiteAgreementNo(quotaDisburse, i);
                    contract.setTripartiteAgreementNo(number);
                    contract.setReviewQuotaDisburseId(quotaDisburse.getId());
                    reviewBasicContractService.addReviewBasicContract(contract, quotaDisburse);
                }
            }
        }
    }

    /**
     * 生成三方协议编号
     */
    public String createTripartiteAgreementNo(ReviewQuotaDisburse quotaDisburse, int seq) {
        // 获取合同编号
        String masterContractNo = "";
        String contractNo = null;
        if (null != quotaDisburse && quotaDisburse.isVisible()) {
            ReviewMasterContract masterContract = quotaDisburse.getReviewMasterContract();
            if (null != masterContract && StringUtil.isNotEmpty(masterContract.getContractNo())) {
                masterContractNo = masterContract.getContractNo();
            }
            if (StringUtil.isNotEmpty(masterContractNo)) {
                // 设置三方协议编号
                String quotaBatchStr;
                int batch = quotaDisburseMapper.getMaxBatchByBusinessNo(quotaDisburse.getBusinessNumber());
                quotaBatchStr = StringUtil.formatNumber(batch);
                contractNo = masterContractNo + "-" + quotaBatchStr + "-" + "TP" + seq;
            }
        }
        return contractNo;
    }

    /**
     * 新增主合同信息
     */
    private void addMasterContract(ReviewQuotaDisburse quotaDisburse) {
        if (null != quotaDisburse && null != quotaDisburse.getId() && null != quotaDisburse.getReviewMasterContract()) {
            ReviewMasterContract masterContract = quotaDisburse.getReviewMasterContract();
            masterContract.setReviewQuotaDisburseId(quotaDisburse.getId());
            // 合同编号
            String contractNo = "";
            // 池保理合同编号
            String poolFactoringFinancingConfirmNo = "";
            // 国内保理-生成合同编号
            // 判断是新池还是已有池
            ReviewQuotaDisburse oldQuotaDisburse = quotaDisburseMapper.selectOne(new QueryWrapper<ReviewQuotaDisburse>()
                    .eq("business_number", quotaDisburse.getBusinessNumber())
                    .ne("id", quotaDisburse.getId())
                    .last("limit 1"));

            if (null != oldQuotaDisburse) {
                // 已有池保理合同：不用生成新的保理合同编号
                ReviewMasterContract alreadyMastContract = reviewMasterContractService.getOne(new QueryWrapper<ReviewMasterContract>()
                        .eq("review_quota_disburse_id", oldQuotaDisburse.getId())
                        .orderByDesc("id").last("limit 1"));
                if (null != alreadyMastContract) {
                    contractNo = alreadyMastContract.getContractNo();
                }
            } else {
                if (quotaDisburse.isVisible()) {
                    //生成新的保理合同编号
                    contractNo = serialNumberGenerator.nextValue(ConstantUtil.REVIEW_MASTER_CONTRACT_DOMESTIC_CODE);
                }
            }
            // 设置池保理融资确认书编号
            if (quotaDisburse.isVisible()) {
                String batchStr;
                // 新池：parentId为空
                int batch = quotaDisburseMapper.getMaxBatchByBusinessNo(quotaDisburse.getBusinessNumber());
                batchStr = StringUtil.formatNumber(batch);
                poolFactoringFinancingConfirmNo = contractNo + "-" + batchStr + "-" + 2;
            }
            masterContract.setPoolFactoringFinancingConfirmNo(poolFactoringFinancingConfirmNo);
            masterContract.setContractNo(contractNo);
            reviewMasterContractService.addMasterContract(masterContract, quotaDisburse.isVisible());
        }
    }

    /**
     * 新增收支计划信息
     */
    private void addIncomeExpenditurePlan(ReviewQuotaDisburse reviewQuotaDisburse) {
        // 验证收支计划：
        validatorIncomeExpenditurePlan(reviewQuotaDisburse);
        if (null != reviewQuotaDisburse && null != reviewQuotaDisburse.getIncomeExpenditurePlanList()) {
            List<ReviewIncomeExpenditurePlan> list = reviewQuotaDisburse.getIncomeExpenditurePlanList();
            int principalNo = 0;
            int marginNo = 0;
            if (null != list && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    ReviewIncomeExpenditurePlan plan = list.get(i);
                    // 设置“本金”和“保证金”类型的放款序号
                    if (StringUtil.isNotBlank(plan.getIncomeExpenditureType()) && null != plan.getLoan() && plan.getLoan().compareTo(new BigDecimal(0)) >= 0) {
                        if (plan.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode())) {
                            principalNo = principalNo + 1;
                            plan.setRecordNo(principalNo);
                        } else if (plan.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode())) {
                            marginNo = marginNo + 1;
                            plan.setRecordNo(marginNo);
                        }
                    }
                    plan.setReviewQuotaDisburseId(reviewQuotaDisburse.getId());
                    ValidatorUtil.validator(ValidatorEntity.ValidatorType.ADD, plan);
                    reviewIncomeExpenditurePlanService.save(plan);
                }
            }
        }
    }

    /**
     * 验证收支计划
     */
    public void validatorIncomeExpenditurePlan(ReviewQuotaDisburse reviewQuotaDisburse) {
        if (null != reviewQuotaDisburse && reviewQuotaDisburse.isVisible()) {
            List<ReviewIncomeExpenditurePlan> list = reviewQuotaDisburse.getIncomeExpenditurePlanList();
            if (null != list && list.size() > 0) {
                // 本金：收款、放款
                BigDecimal principal_receivableTotal;
                BigDecimal principal_loanTotal;
                // 利息：收款、放款
                BigDecimal interest_receivableTotal;
                BigDecimal interest_loanTotal;
                // 保证金：收款、放款
                BigDecimal margin_receivableTotal;
                BigDecimal margin_loanTotal;
                // 管理费:收款、放款
                BigDecimal management_receivableTotal;
                BigDecimal management_loanTotal;
                principal_receivableTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode()))
                        .filter((e) -> e.getReceivables() != null).map(ReviewIncomeExpenditurePlan::getReceivables)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 本金：放款
                principal_loanTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode()))
                        .filter((e) -> e.getLoan() != null).map(ReviewIncomeExpenditurePlan::getLoan)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 利息：收款
                interest_receivableTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode()))
                        .filter((e) -> e.getReceivables() != null).map(ReviewIncomeExpenditurePlan::getReceivables)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 利息：放款
                interest_loanTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode()))
                        .filter((e) -> e.getLoan() != null).map(ReviewIncomeExpenditurePlan::getLoan)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 保证金：收款
                margin_receivableTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode()))
                        .filter((e) -> e.getReceivables() != null).map(ReviewIncomeExpenditurePlan::getReceivables)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 保证金：放款
                margin_loanTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode()))
                        .filter((e) -> e.getLoan() != null).map(ReviewIncomeExpenditurePlan::getLoan)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 管理费：收款
                management_receivableTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode()))
                        .filter((e) -> e.getReceivables() != null).map(ReviewIncomeExpenditurePlan::getReceivables)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 管理费：放款
                management_loanTotal = list.stream()
                        .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                        .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode()))
                        .filter((e) -> e.getLoan() != null).map(ReviewIncomeExpenditurePlan::getLoan)
                        .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                // 【保证金】收款+放款=0，如果不等于0，则无法提交成功
                if (principal_receivableTotal.compareTo(principal_loanTotal) != 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "收支计划中【本金】的收款和放款必须相等");
                }
                // 【本金】 收款+放款=0，如果不等于0，则无法提交成功；
                if (margin_receivableTotal.compareTo(margin_loanTotal) != 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "收支计划中【保证金】的收款和放款必须相等");
                }
                // 【利息】收款+放款≧0，如果<0，则无法提交成功；
                if (interest_receivableTotal.compareTo(interest_loanTotal) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "收支计划中【利息】的收款加放款大于等于0");
                }
                // 【管理费】：收款+放款≧0，如果<0，则无法提交成功
                if (management_receivableTotal.compareTo(management_loanTotal) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "收支计划中【管理费】的收款加放款大于等于0");
                }
            }
        }
    }

    /**
     * 新增融资信息
     */
    private void addFinancingInfo(ReviewQuotaDisburse reviewQuotaDisburse, CFinancingBasicInfo financingBasicInfo) {
        if (null != reviewQuotaDisburse && null != reviewQuotaDisburse.getReviewFinancingInfo()) {
            ReviewFinancingInfo financingInfo = reviewQuotaDisburse.getReviewFinancingInfo();
            BigDecimal zero = BigDecimal.ZERO;
            // 最大比例
            BigDecimal maxRatio = new BigDecimal("1");
            //融资利率
            if (financingInfo.getFinancingRate() != null) {
                financingInfo.setFinancingRate(financingInfo.getFinancingRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));

            }
            //逾期利息
            if (financingInfo.getOverdueInterestRate() != null) {
                financingInfo.setOverdueInterestRate(financingInfo.getOverdueInterestRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));
            }
            // 融资比例：保留四位小数,直接删除多余的小数位数,整数部分最多是3位
            if (financingInfo.getFinancingRatio() != null) {
                BigDecimal financingRatio = financingInfo.getFinancingRatio().divide(new BigDecimal("100")).setScale(4, BigDecimal.ROUND_DOWN);
                financingInfo.setFinancingRatio(financingRatio);
            }
            // 设置融资金额=收支计划中放款类型的本金加和
            BigDecimal financingAmount = calculateFinancingAmount(reviewQuotaDisburse);
            financingInfo.setFinancingAmount(financingAmount);
            // 融资比例=融资金额/选择的应收账款净额加和
            BigDecimal netAmountTotal = reviewQuotaDisburse.getAccountsReceivableNetAmountTotal();
            if (null != financingAmount && null != netAmountTotal) {
                financingInfo.setFinancingRatio(financingAmount.divide(netAmountTotal, 4, RoundingMode.HALF_UP));
            }
            // 管理费率(年化)
            if (financingInfo.getManagementFeeRatio() != null) {
                BigDecimal manageFee = financingInfo.getManagementFeeRatio().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
                financingInfo.setManagementFeeRatio(manageFee);
            }
            // 保证金比例=收支计划中收款类型的保证金加和/融资金额
            BigDecimal margin = calculationMargin(reviewQuotaDisburse);
            if (null != financingAmount && null != margin && financingAmount.compareTo(BigDecimal.ZERO) != 0) {
                financingInfo.setMarginRatio(margin.divide(financingAmount, 4, RoundingMode.HALF_UP));
            }
            //对外综合报价
            if (financingInfo.getComprehensiveQuotation() != null) {
                financingInfo.setComprehensiveQuotation(financingInfo.getComprehensiveQuotation().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));
            }
            // 验证融资信息
            if (reviewQuotaDisburse.isVisible()) {
                ValidatorUtil.validator(ValidatorEntity.ValidatorType.ADD, financingInfo);
            } else {
                ValidatorUtil.validator(ValidatorEntity.ValidatorType.TEMP, financingInfo);
            }
            // 验证融资信息
            validatorFinancingInfoData(reviewQuotaDisburse, financingBasicInfo);

            // 管理费金额
            BigDecimal managementFeeAmount = financingInfo.getManagementFeeAmount() != null
                    ? financingInfo.getManagementFeeAmount() : BigDecimal.ZERO;
            financingInfo.setManagementFeeAmount(managementFeeAmount);
            // 保证金金额
            BigDecimal marginAmount = financingInfo.getMarginAmount() != null
                    ? financingInfo.getMarginAmount() : BigDecimal.ZERO;
            financingInfo.setMarginAmount(marginAmount);
            // 其他费用金额
            BigDecimal otherFeeAmount = financingInfo.getOtherFeeAmount() != null ? financingInfo.getOtherFeeAmount()
                    : BigDecimal.ZERO;
            financingInfo.setOtherFeeAmount(otherFeeAmount);
            //转让通知方式
            if (CollectionUtil.isNotEmpty(financingInfo.getTransferNoticeMethodList())) {
                financingInfo.setTransferNoticeMethod(StringUtils.join(financingInfo.getTransferNoticeMethodList(), ConstantConversionUtil.MULTIPLE_SELECTION_SEPARATOR));
            }
            //服务范围
            if (CollectionUtil.isNotEmpty(financingInfo.getServiceScopeList())) {
                financingInfo.setServiceScope(StringUtils.join(financingInfo.getServiceScopeList(), ConstantConversionUtil.MULTIPLE_SELECTION_SEPARATOR));
            }
            financingInfo.setReviewQuotaDisburseId(reviewQuotaDisburse.getId());
            reviewFinancingInfoService.save(financingInfo);
        }
    }

    /**
     * 计算融资金额
     *
     * @param disburse
     * @return
     */
    public BigDecimal calculateFinancingAmount(ReviewQuotaDisburse disburse) {
        BigDecimal financingAmount = BigDecimal.ZERO;
        if (null != disburse && null != disburse.getIncomeExpenditurePlanList()
                && disburse.getIncomeExpenditurePlanList().size() > 0) {
            List<ReviewIncomeExpenditurePlan> list = disburse.getIncomeExpenditurePlanList();
            financingAmount = list.stream()
                    .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                    .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode()))
                    .filter((e) -> e.getLoan() != null).map(ReviewIncomeExpenditurePlan::getLoan)
                    .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        }
        return financingAmount;
    }

    /**
     * 计算保证金金额
     *
     * @param quotaDisburse
     * @return
     */
    public BigDecimal calculationMargin(ReviewQuotaDisburse quotaDisburse) {
        BigDecimal margin = BigDecimal.ZERO;
        if (null != quotaDisburse && null != quotaDisburse.getIncomeExpenditurePlanList()
                && quotaDisburse.getIncomeExpenditurePlanList().size() > 0) {
            List<ReviewIncomeExpenditurePlan> list = quotaDisburse.getIncomeExpenditurePlanList();
            margin = list.stream()
                    .filter((e) -> StringUtil.isNotBlank(e.getIncomeExpenditureType()))
                    .filter((e) -> e.getIncomeExpenditureType().equals(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode()))
                    .filter((e) -> e.getReceivables() != null).map(ReviewIncomeExpenditurePlan::getReceivables)
                    .reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        }
        return margin;
    }

    /**
     * 验证融资信息
     */
    public void validatorFinancingInfoData(ReviewQuotaDisburse reviewQuotaDisburse, CFinancingBasicInfo financingBasicInfo) {
        if (null != reviewQuotaDisburse && reviewQuotaDisburse.isVisible()) {
            // 授信信息中的综合报价
            double creditInfoComprehensiveQuotation = 0;
            // 授信信息中的逾期IRR
            double creditInfoPlanIrr = 0;
            // 授信信息中的融资利率(年化)
            double creditInfoFinancingRateStart = 0;
            double creditInfoFinancingRateEnd = 0;
            // 授信信息中的管理费率(年化)
            double creditInfoManagementFeeStart = 0;
            double creditInfoManagementFeeEnd = 0;
            // 授信信息中的保证金比例(年化)
            double creditInfoMarginRatioStart = 0;
            double creditInfoMarginRatioEnd = 0;
            // 授信信息中的融资比例
            double creditInfoFinancingRatioStart = 0;
            double creditInfoFinancingRatioEnd = 0;

            //从授信决议里取
            ProjectInformation projectInformation = projectInformationService.getOne(new QueryWrapper<ProjectInformation>()
                    .eq("business_number", financingBasicInfo.getBusinessNumber()));
            if (projectInformation == null) {
                throw new BusinessException(CodeUtil.FAIL, "根据业务编号获取不到对应项目信息");
            }
            CreditResolution creditResolution = creditResolutionService.getByProjectInformationId(projectInformation.getId());
            if (creditResolution != null) {
                // 获取到：对外综合报价信息
                creditInfoComprehensiveQuotation = creditResolution.getComprehensiveQuotation();
                // 获取到:逾期IRR
                creditInfoPlanIrr = creditResolution.getPlanIrr();
                // 获取到：融资利率(年化)
                creditInfoFinancingRateStart = creditResolution.getFinancingRateLow();
                creditInfoFinancingRateEnd = creditResolution.getFinancingRateHigh();
                // 获取到：融资比例
                ReviewFinancingInfo reviewFinancingInfo = reviewQuotaDisburse.getReviewFinancingInfo();
                if (reviewFinancingInfo.getOccupation() == 0) {
                    //不占用公司资金
                    creditInfoFinancingRatioStart = creditResolution.getProposedFinancingRatioTwoLow();
                    creditInfoFinancingRatioEnd = creditResolution.getProposedFinancingRatioTwoHigh();
                } else if (reviewFinancingInfo.getOccupation() == 1) {
                    //占用公司资金
                    creditInfoFinancingRatioStart = creditResolution.getFinancingRatioLow();
                    creditInfoFinancingRatioEnd = creditResolution.getFinancingRatioHigh();
                }
                // 获取到：管理费率(年化)
                creditInfoManagementFeeStart = creditResolution.getManagementRateLow();
                creditInfoManagementFeeEnd = creditResolution.getManagementRateHigh();
                // 获取到：保证金比例
                creditInfoMarginRatioStart = creditResolution.getMarginRatioLow();
                creditInfoMarginRatioEnd = creditResolution.getMarginRatioHigh();
            }

            // 验证融资金额
            if (null != reviewQuotaDisburse.getReviewFinancingInfo()) {
                ReviewFinancingInfo reviewFinancingInfo = reviewQuotaDisburse.getReviewFinancingInfo();
                BigDecimal financingAmount = reviewFinancingInfo.getFinancingAmount();
                if (null == financingAmount || financingAmount.compareTo(BigDecimal.ZERO) == 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "【融资金额】不能为空,且大于0");
                }
                // 应收账款净额总计
                BigDecimal netAmountTotal = reviewQuotaDisburse.getAccountsReceivableNetAmountTotal();
                if (netAmountTotal.compareTo(financingAmount) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "融资金额必须满足:【底层资产的应收账款净额总计】>=【融资金额】");
                }
                // 验证融资利率(年化)
                BigDecimal financingRate = reviewFinancingInfo.getFinancingRate();
                if (financingRate.compareTo(new BigDecimal(creditInfoFinancingRateEnd)) > 0
                        || financingRate.compareTo(new BigDecimal(creditInfoFinancingRateStart)) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "【融资利率(年化)】必须在授信决议中的【融资利率(年化)】之间");
                }
                // 验证管理费率(年化)
                BigDecimal managementFeeRatio = reviewFinancingInfo.getManagementFeeRatio();
                if (managementFeeRatio.compareTo(new BigDecimal(creditInfoManagementFeeEnd)) > 0
                        || managementFeeRatio.compareTo(new BigDecimal(creditInfoManagementFeeStart)) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "【管理费比例】必须在授信决议中的【管理费比例】之间");
                }
                // 验证保证金比例
                BigDecimal marginRatio = reviewFinancingInfo.getMarginRatio();
                if (marginRatio.compareTo(new BigDecimal(creditInfoMarginRatioEnd)) > 0
                        || marginRatio.compareTo(new BigDecimal(creditInfoMarginRatioStart)) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "【保证金比例】必须在授信决议中的【保证金比例】之间");
                }
                // 验证融资比例
                BigDecimal financingRatio = reviewFinancingInfo.getFinancingRatio();
                if (financingRatio.compareTo(new BigDecimal(creditInfoFinancingRatioEnd)) > 0
                        || financingRatio.compareTo(new BigDecimal(creditInfoFinancingRatioStart)) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "【融资比例】必须在授信决议中的【融资比例】之间");
                }
                // 验证对外综合报价
                BigDecimal comprehensiveQuotation = reviewFinancingInfo.getComprehensiveQuotation();
                if (comprehensiveQuotation.compareTo(new BigDecimal(creditInfoComprehensiveQuotation)) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "对外综合报价必须满足:【对外综合报价】≧授信决议中的【对外综合报价低限】");
                }
                // 验证预期IRR
                BigDecimal planIrr = reviewQuotaDisburse.getPlanIrr();
                if (planIrr.compareTo(new BigDecimal(creditInfoPlanIrr)) < 0) {
                    throw new ValidatorException(CodeUtil.FAIL, "【预期IRR】≧授信信息中的【预期IRR低限】");
                }
            }
        }
    }

    /**
     * 回款方式为前收息、后收息、管理费前收利息后收的收支计划
     *
     * @param reviewFinancingInfo 融资信息
     * @param planList            收支计划
     * @return
     */
    public List<ReviewIncomeExpenditurePlan> preOrAfterInterest(ReviewFinancingInfo reviewFinancingInfo, List<ReviewIncomeExpenditurePlan> planList,
                                                                Dictionary dict) {
        Integer interestCalculate = reviewFinancingInfo.getInterestCalculate();
        if (interestCalculate == null) {
            throw new BusinessException(CodeUtil.FAIL, "利息是否计算投放日不能为空");
        }
        DateTime endDate = null;
        if (interestCalculate.equals(1)) {
            endDate = DateUtil.offsetDay(reviewFinancingInfo.getStartingDate(), reviewFinancingInfo.getFinancingPeriod() - 1);
        } else if (interestCalculate.equals(0)) {
            endDate = DateUtil.offsetDay(reviewFinancingInfo.getStartingDate(), reviewFinancingInfo.getFinancingPeriod());
        }

        //本金
        if (reviewFinancingInfo.getFinancingAmount() != null) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setLoan(reviewFinancingInfo.getFinancingAmount());
            plan.setIncomeExpenditureDate(reviewFinancingInfo.getStartingDate());
            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getFinancingAmount().negate());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }

        //保证金
        if (reviewFinancingInfo.getMarginAmount() != null && reviewFinancingInfo.getMarginAmount().compareTo(BigDecimal.ZERO) > 0) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setReceivables(reviewFinancingInfo.getMarginAmount());
            plan.setIncomeExpenditureDate(reviewFinancingInfo.getStartingDate());
            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getMarginAmount());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }

        //利息
        if (reviewFinancingInfo.getFinancingInterest() != null && reviewFinancingInfo.getFinancingInterest().compareTo(BigDecimal.ZERO) > 0) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setReceivables(reviewFinancingInfo.getFinancingInterest());
            if (dict.getCode().equals("paymentMethodForInterestManagementFee_A")) {
                //如果是前收息
                plan.setIncomeExpenditureDate(reviewFinancingInfo.getStartingDate());
            } else if (dict.getCode().equals("paymentMethodForInterestManagementFee_B")
                    || dict.getCode().equals("paymentMethodForInterestManagementFee_C")) {
                //如果是后收息或者是管理费前收利息后收
                plan.setIncomeExpenditureDate(endDate);
            }
            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getFinancingInterest());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }

        //管理费
        if (reviewFinancingInfo.getManagementFeeAmount() != null && reviewFinancingInfo.getManagementFeeAmount().compareTo(BigDecimal.ZERO) > 0) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setReceivables(reviewFinancingInfo.getManagementFeeAmount());
            if (dict.getCode().equals("paymentMethodForInterestManagementFee_A") || dict.getCode().equals("paymentMethodForInterestManagementFee_C")) {
                //如果是前收息或者是管理费前收利息后收
                plan.setIncomeExpenditureDate(reviewFinancingInfo.getStartingDate());
            } else if (dict.getCode().equals("paymentMethodForInterestManagementFee_B")) {
                //如果是后收息
                plan.setIncomeExpenditureDate(endDate);
            }

            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getManagementFeeAmount());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }


        //其它费用
        if (reviewFinancingInfo.getOtherFeeAmount() != null && reviewFinancingInfo.getOtherFeeAmount().compareTo(BigDecimal.ZERO) > 0) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setReceivables(reviewFinancingInfo.getOtherFeeAmount());
            plan.setIncomeExpenditureDate(reviewFinancingInfo.getStartingDate());
            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.OTHER_FEE.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getOtherFeeAmount());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }

        //回款本金
        if (reviewFinancingInfo.getFinancingPeriod() != null) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setReceivables(reviewFinancingInfo.getFinancingAmount());
            plan.setIncomeExpenditureDate(endDate);
            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getFinancingAmount());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }

        //退回保证金
        if (reviewFinancingInfo.getMarginAmount() != null && reviewFinancingInfo.getMarginAmount().compareTo(BigDecimal.ZERO) > 0) {
            ReviewIncomeExpenditurePlan plan = new ReviewIncomeExpenditurePlan();
            plan.setLoan(reviewFinancingInfo.getMarginAmount());
            plan.setIncomeExpenditureDate(endDate);
            plan.setIncomeExpenditureType(IncomeExpenditureTypeDict.ChildEnum.MARGIN.getCode());
            plan.setFinalCashFlow(reviewFinancingInfo.getMarginAmount().negate());
            //收款主体默认为债权人
            plan.setReceivingSubject(ConstantUtil.CREDITOR);
            planList.add(plan);
        }
        return planList;
    }
}
