package com.sunxung.factoring.service.ledger.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.CodeUtil;
import com.sunxung.factoring.component.util.ConstantConversionUtil;
import com.sunxung.factoring.dict.impl.CashFlowOutTypeDict;
import com.sunxung.factoring.dict.impl.IncomeExpenditureTypeDict;
import com.sunxung.factoring.dict.impl.LedgerStatusDict;
import com.sunxung.factoring.dict.impl.PaymentCollectionPlanStatusDict;
import com.sunxung.factoring.entity.GridPage;
import com.sunxung.factoring.entity.ResponseJson;
import com.sunxung.factoring.entity.cashflowmanage.CashFlowManageBasicInfo;
import com.sunxung.factoring.entity.cashflowmanage.sop.BankAccountInfo;
import com.sunxung.factoring.entity.cashflowmanage.sop.BillingNonbusinessManageFactoringentry;
import com.sunxung.factoring.entity.cashflowmanage.sop.BillingRecordBasic;
import com.sunxung.factoring.entity.customerinformation.SupplierBankCardInfo;
import com.sunxung.factoring.entity.entprise.Enterprise;
import com.sunxung.factoring.entity.financing.apply.CFinancingAccountsReceivableInfo;
import com.sunxung.factoring.entity.financing.apply.CFinancingApplicantInfo;
import com.sunxung.factoring.entity.financing.apply.CFinancingBasicInfo;
import com.sunxung.factoring.entity.ledger.CashFlowManageBasicPayCollPlanRef;
import com.sunxung.factoring.entity.ledger.LedgerAccountBasicInfo;
import com.sunxung.factoring.entity.ledger.LedgerFundGoodsAssign;
import com.sunxung.factoring.entity.ledger.LedgerPlanFactoringAssign;
import com.sunxung.factoring.entity.ledger.vo.*;
import com.sunxung.factoring.entity.project.ProjectCoreEnterprise;
import com.sunxung.factoring.entity.project.ProjectInformation;
import com.sunxung.factoring.entity.purchcontractmanagement.PurchContractBasicInfo;
import com.sunxung.factoring.entity.purchcontractmanagement.PurchContractManagement;
import com.sunxung.factoring.entity.purchcontractmanagement.PurchContractSettlePayment;
import com.sunxung.factoring.entity.salescontractmanagement.CSalesContractBasicInfo;
import com.sunxung.factoring.entity.salescontractmanagement.SalesContractApproval;
import com.sunxung.factoring.entity.salescontractmanagement.SalesContractRetentionInfo;
import com.sunxung.factoring.entity.settlement.SettlementBasicInfo;
import com.sunxung.factoring.entity.settlement.SettlementGoodsInfo;
import com.sunxung.factoring.entity.supplier.SupplierInfo;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.User;
import com.sunxung.factoring.entity.sys.UserDO;
import com.sunxung.factoring.entity.tradingPlatform.Platform;
import com.sunxung.factoring.entity.underlying.sop.PayCollPlanFactoringAmountAllocation;
import com.sunxung.factoring.entity.underlying.sop.PaymentCollectionPlanFactoring;
import com.sunxung.factoring.mapper.ledger.LedgerManagementMapper;
import com.sunxung.factoring.service.async.AsyncService;
import com.sunxung.factoring.service.cashflowmanage.CashFlowManageBasicInfoService;
import com.sunxung.factoring.service.customerinformation.SupplierBankCardInfoService;
import com.sunxung.factoring.service.entprise.IEnterpriseService;
import com.sunxung.factoring.service.financing.apply.ICFinancingAccountsReceivableInfoService;
import com.sunxung.factoring.service.financing.apply.ICFinancingApplicantInfoService;
import com.sunxung.factoring.service.financing.apply.ICFinancingBasicInfoService;
import com.sunxung.factoring.service.financing.apply.ICFinancingGoodsInfoService;
import com.sunxung.factoring.service.ledger.*;
import com.sunxung.factoring.service.project.IProjectCoreEnterpriseService;
import com.sunxung.factoring.service.project.IProjectInformationService;
import com.sunxung.factoring.service.purchcontractmanagement.PurchContractBasicInfoService;
import com.sunxung.factoring.service.purchcontractmanagement.PurchContractService;
import com.sunxung.factoring.service.purchcontractmanagement.PurchContractSettlePaymentService;
import com.sunxung.factoring.service.refundsManagement.IRefundManagementService;
import com.sunxung.factoring.service.salescontractmanagement.SalesContractApprovalService;
import com.sunxung.factoring.service.salescontractmanagement.SalesContractRetentionInfoService;
import com.sunxung.factoring.service.salescontractmanagement.SalesContractService;
import com.sunxung.factoring.service.settlement.SettlementBasicInfoService;
import com.sunxung.factoring.service.settlement.SettlementGoodsInfoService;
import com.sunxung.factoring.service.supplier.ISupplierInfoService;
import com.sunxung.factoring.service.sys.CUserService;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.UserService;
import com.sunxung.factoring.service.tradingPlatform.PlatformService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

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

/**
 * 分账管理service实现类
 *
 * @author LiuJia
 * @date 2021.11.11
 */
@Service
@PropertySource("classpath:config.properties")
public class LedgerManagementServiceImpl implements LedgerManagementService {

    @Autowired
    private LedgerAccountBasicInfoService ledgerAccountBasicInfoService;

    @Autowired
    private LedgerFundGoodsAssignService ledgerFundGoodsAssignService;

    @Autowired
    private SupplierBankCardInfoService supplierBankCardInfoService;

    @Autowired
    private DictionaryService dictService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LedgerManagementMapper ledgerManagementMapper;

    @Autowired
    private SettlementGoodsInfoService settlementGoodsInfoService;

    @Autowired
    private SettlementBasicInfoService settlementBasicInfoService;

    @Autowired
    private LedgerPlanFactoringAssignService planFactoringAssignService;

    @Autowired
    private CashFlowManageBasicInfoService cashFlowManageBasicInfoService;

    @Autowired
    private ICFinancingBasicInfoService financingBasicInfoService;

    @Autowired
    private ICFinancingGoodsInfoService financingGoodsInfoService;

    @Autowired
    private ICFinancingApplicantInfoService financingApplicantInfoService;

    @Autowired
    private ICFinancingAccountsReceivableInfoService financingAccountsReceivableInfoService;

    @Autowired
    private SalesContractService salesContractService;

    @Autowired
    private SalesContractApprovalService salesContractApprovalService;

    @Autowired
    private SalesContractRetentionInfoService salesContractRetentionInfoService;

    @Autowired
    private PurchContractService purchContractManagementService;

    @Autowired
    private PurchContractBasicInfoService purchContractBasicInfoService;

    @Autowired
    private PurchContractSettlePaymentService purchContractSettlePaymentService;

    @Autowired
    private ICashFlowManageBasicPayCollPlanRefService CashFlowManageBasicPayCollPlanRefService;

    @Autowired
    private IProjectInformationService projectInformationService;

    @Autowired
    private IProjectCoreEnterpriseService projectCoreEnterpriseService;

    @Autowired
    private AsyncService asyncService;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private PlatformService platformService;

    @Autowired
    private ISupplierInfoService supplierInfoService;

    @Autowired
    private CUserService cUserService;

    @Autowired
    private UserService userService;

    @Value("${config.ledger.findPayCollPlanFactoringList.url}")
    private String payCollPlanFactoringListUrl;

    @Value("${config.ledger.findUnCompletePayCollPlanFactoringList.url}")
    private String unCompletePayCollPlanFactoringList;

    @Value("${config.ledger.findAllPayCollPlanFactoringList.url}")
    private String allPayCollPlanFactoringList;

    @Value("${config.ledger.findPrepaymentInterestCal.url}")
    private String findPrepaymentInterestCalUrl;

    @Value("${config.ledger.findGoodsAssignInfoByReceivableId.url}")
    private String findGoodsAssignInfoUrl;

    @Value("${config.planInfo.add.url}")
    private String planInfoAddUrl;

    @Value("${config.billingRecordBasic.add.url}")
    private String billingRecordBasicAddUrl;

    @Value("${config.startOaPaymentProcessUrl.url}")
    private String startOaPaymentProcessUrl;

    @Value("${config.ledger.findPlanFactoringId.url}")
    private String findPlanFactoringIdUrl;

    @Autowired
    private IRefundManagementService refundManagementService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(LedgerAccountInfoVo ledgerAccountInfoVo) {
        if (ledgerAccountInfoVo == null || ledgerAccountInfoVo.getLedgerAccountBasicInfo() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "分账信息不能为空");
        }

        Boolean submit = ledgerAccountInfoVo.getSubmit();
        if (submit == null) {
            throw new ValidatorException(CodeUtil.FAIL, "暂存或提交标识不能为空");
        }

        //数据合法性校验
        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountInfoVo.getLedgerAccountBasicInfo();
        if (submit) {
            validatorData(ledgerAccountInfoVo);
            //修改分账管理状态为已完成
            ledgerAccountBasicInfo.setLedgerStatus(LedgerStatusDict.ChildEnum.COMPLETE.getCode());
        }
        ledgerAccountBasicInfoService.updateById(ledgerAccountBasicInfo);

        //保存货款分配信息(先删后增，因为可能暂存过)
        List<LedgerFundGoodsAssign> ledgerFundGoodsAssignList = ledgerFundGoodsAssignService.findByBasicId(ledgerAccountBasicInfo.getId());
        if (CollectionUtil.isNotEmpty(ledgerFundGoodsAssignList)) {
            ledgerFundGoodsAssignService.remove(new QueryWrapper<LedgerFundGoodsAssign>().eq("ledger_account_basic_info_id", ledgerAccountBasicInfo.getId()));
        }
        List<LedgerPlanFactoringAssign> planFactoringAssignList = planFactoringAssignService.findByBasicInfoId(ledgerAccountBasicInfo.getId());
        if (CollectionUtil.isNotEmpty(planFactoringAssignList)) {
            planFactoringAssignService.remove(new QueryWrapper<LedgerPlanFactoringAssign>().eq("ledger_account_basic_info_id", ledgerAccountBasicInfo.getId()));
        }

        List<LedgerFundGoodsAssign> goodsAssignList = ledgerAccountInfoVo.getGoodsAssignList();
        if (goodsAssignList != null && goodsAssignList.size() > 0) {
            for (LedgerFundGoodsAssign ledgerFundGoodsAssign : goodsAssignList) {
                ledgerFundGoodsAssign.setLedgerAccountBasicInfoId(ledgerAccountBasicInfo.getId());
                ledgerFundGoodsAssign.setGoodsAssignId(ledgerFundGoodsAssign.getId());
                ledgerFundGoodsAssign.setId(null);
                ledgerFundGoodsAssign.setSubmit(submit);
                ledgerFundGoodsAssignService.save(ledgerFundGoodsAssign);

                List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList = ledgerFundGoodsAssign.getLedgerPlanFactoringAssignList();
                if (CollectionUtil.isNotEmpty(ledgerPlanFactoringAssignList)) {
                    for (LedgerPlanFactoringAssign planFactoringAssign : ledgerPlanFactoringAssignList) {
                        planFactoringAssign.setLedgerAccountBasicInfoId(ledgerAccountBasicInfo.getId());
                        planFactoringAssign.setLedgerFundGoodsAssignId(ledgerFundGoodsAssign.getId());
                        planFactoringAssignService.save(planFactoringAssign);
                    }
                }
            }
        }

        supplierBankCardInfoService.remove(new QueryWrapper<SupplierBankCardInfo>().eq("ledger_account_basic_info_id", ledgerAccountBasicInfo.getId()));
        List<SupplierBankCardInfo> supplierBankCardInfoList = ledgerAccountInfoVo.getSupplierBankCardInfoList();
        if (supplierBankCardInfoList != null && supplierBankCardInfoList.size() > 0) {
            for (SupplierBankCardInfo supplierBankCardInfo : supplierBankCardInfoList) {
                supplierBankCardInfo.setLedgerAccountBasicInfoId(ledgerAccountBasicInfo.getId());
                supplierBankCardInfoService.save(supplierBankCardInfo);
            }
        }

        //完成后添加现金流数据
        //修改现金流入账信息状态为已分配
        if (submit) {
            CashFlowManageBasicInfo cashFlowManageBasicInfo = cashFlowManageBasicInfoService.getById(ledgerAccountBasicInfo.getCashFlowManageBasicInfoId());
            cashFlowManageBasicInfo.setCashStatus(2);
            cashFlowManageBasicInfoService.updateById(cashFlowManageBasicInfo);

            //调用sop变更收放款计划接口
            planFactoringAssignList = planFactoringAssignService.findByBasicInfoId(ledgerAccountBasicInfo.getId());
            if (CollectionUtil.isNotEmpty(planFactoringAssignList)) {
                ResponseEntity<String> responseEntity = restTemplate.postForEntity(planInfoAddUrl, planFactoringAssignList, String.class);
                ResponseJson responseJson = JSONUtil.toBean(responseEntity.getBody(), ResponseJson.class);
                if (responseEntity.getStatusCode().value() != HttpStatus.OK.value() || !responseJson.isSuccess()) {
                    throw new BusinessException(CodeUtil.FAIL, "分账失败--变更sop收放款计划失败：" + responseJson.getMsg());
                }
            }

            //添加现金流出账数据
            List<LedgerFundGoodsAssign> fundGoodsAssignList = ledgerFundGoodsAssignService.findByBasicId(ledgerAccountBasicInfo.getId());
            if (fundGoodsAssignList != null && fundGoodsAssignList.size() > 0) {
                for (LedgerFundGoodsAssign ledgerFundGoodsAssign : fundGoodsAssignList) {
                    //融资本金
                    BigDecimal financingPrincipal = ledgerFundGoodsAssign.getFinancingPrincipal();

                    //融资逾期利息
                    BigDecimal financingOverdueInterest = ledgerFundGoodsAssign.getFinancingOverdueInterest();

                    //融资管理费
                    BigDecimal financingManagementFee = ledgerFundGoodsAssign.getFinancingManagementFee();

                    //融资利息
                    BigDecimal financingInterest = ledgerFundGoodsAssign.getFinancingInterest();

                    //本金、利息、管理费、逾期利息合成保理融资款项
                    BigDecimal financingAmount = financingPrincipal.add(financingOverdueInterest).add(financingManagementFee).add(financingInterest);
                    if (financingAmount.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.FINANCING_AMOUNT.getCode(),
                                ledgerFundGoodsAssign, financingAmount);
                    }
                    //实退金额
                    BigDecimal discountAmount = ledgerFundGoodsAssign.getDiscountAmount();
                    if (discountAmount.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.DISCOUNT.getCode(),
                                ledgerFundGoodsAssign, discountAmount);
                    }
                    // 平台利润
                    BigDecimal platformProfit = ledgerFundGoodsAssign.getPlatformProfit();
                    if (platformProfit.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.PROFIT.getCode(),
                                ledgerFundGoodsAssign, platformProfit);
                    }
                    //贸理通4.0add
                    //履约保证金(计提金额)
                    BigDecimal accrualAmount = ledgerFundGoodsAssign.getAccrualAmount();
                    if (accrualAmount.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.PERFORMANCE_BOND.getCode(),
                                ledgerFundGoodsAssign, accrualAmount);
                    }

                    //质保金
                    BigDecimal guarantee = ledgerFundGoodsAssign.getGuarantee();
                    if (guarantee.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.RETENTION_MONEY.getCode(),
                                ledgerFundGoodsAssign, guarantee);
                    }

                    //应退利息
                    BigDecimal refundInterest = ledgerFundGoodsAssign.getRefundInterest();
                    if (guarantee.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.REFUND_INTEREST.getCode(),
                                ledgerFundGoodsAssign, refundInterest);
                    }

                    //应退管理费
                    BigDecimal refundManagementFee = ledgerFundGoodsAssign.getRefundManagementFee();
                    if (guarantee.compareTo(BigDecimal.ZERO) == 1) {
                        addCashFlowManageBasicInfo(ledgerAccountBasicInfo, CashFlowOutTypeDict.ChildEnum.REFUND_MANAGEMENT_FEE.getCode(),
                                ledgerFundGoodsAssign, refundManagementFee);
                    }

                    //往退款中添加数据
                    refundManagementService.add(ledgerFundGoodsAssign);
                    //同步sop发送通知消息
                    // asyncService.sendMsg(fundGoodsAssignList);
                }
            }
        }
    }

    /**
     * 生成现金流出账数据
     *
     * @param ledgerAccountBasicInfo
     * @param cashTypeCode
     * @param ledgerFundGoodsAssign
     * @param amount
     */
    private void addCashFlowManageBasicInfo(LedgerAccountBasicInfo ledgerAccountBasicInfo, String cashTypeCode, LedgerFundGoodsAssign ledgerFundGoodsAssign,
                                            BigDecimal amount) {
        CashFlowManageBasicInfo cashFlowManageBasicInfo = new CashFlowManageBasicInfo();

        //根据业务编号和供应商Id获取对应的采购合同编号
        PurchContractManagement purchContractManagement = purchContractManagementService.getOne(new QueryWrapper<PurchContractManagement>()
                .eq("business_number", ledgerFundGoodsAssign.getBusinessNumber()));
        if (purchContractManagement == null || purchContractManagement.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "采购合同管理不能为空");
        }
        PurchContractBasicInfo purchContractBasicInfo = purchContractBasicInfoService.getOne(new QueryWrapper<PurchContractBasicInfo>()
                .eq("c_purch_contract_management_id", purchContractManagement.getId()));

        cashFlowManageBasicInfo.setBusinessNumber(ledgerFundGoodsAssign.getBusinessNumber());
        cashFlowManageBasicInfo.setContractNumber(purchContractBasicInfo.getContractNumber());
        //出账默认为2
        cashFlowManageBasicInfo.setEntryOutType("2");
        //类型为保理融资款时添加贸易平台Id,为其它类型时、添加供应商Id
        Dictionary profitDict = dictService.getByCode(CashFlowOutTypeDict.ChildEnum.PROFIT.getCode());
        if (profitDict == null || profitDict.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "款项类型-平台利润字典项不能为空!");
        }

        Dictionary financingAmountDict = dictService.getByCode(CashFlowOutTypeDict.ChildEnum.FINANCING_AMOUNT.getCode());
        if (financingAmountDict == null || financingAmountDict.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "款项类型-保理融资款项不能为空!");
        }

        if (cashTypeCode.equals(financingAmountDict.getCode())) {
            //获取贸易平台ID
            Platform platform = platformService.getById(purchContractBasicInfo.getTradingPlatformId());
            if (platform != null) {
                cashFlowManageBasicInfo.setTradingPlatformId(platform.getId());
            }
        } else {
            cashFlowManageBasicInfo.setSupplierId(ledgerFundGoodsAssign.getSupplierId());
        }
        //获取核心企业信息
        ProjectInformation projectInformation = projectInformationService.getOne(new QueryWrapper<ProjectInformation>().eq("business_number", ledgerFundGoodsAssign.getBusinessNumber()));
        if (projectInformation != null) {
            cashFlowManageBasicInfo.setBusinessName(projectInformation.getProjectName());
            ProjectCoreEnterprise projectCoreEnterprise = projectCoreEnterpriseService.getOne(new QueryWrapper<ProjectCoreEnterprise>().eq("c_project_information_id", projectInformation.getId()));
            if (projectCoreEnterprise != null) {
                cashFlowManageBasicInfo.setEnterpriseCustomerInfoId(projectCoreEnterprise.getcEnterpriseId());
            }
        }
        cashFlowManageBasicInfo.setCashType(cashTypeCode);
        cashFlowManageBasicInfo.setCurrency(dictService.getByCode("CNY").getId());
        cashFlowManageBasicInfo.setAmount(amount);
        //状态为待处理
        if (profitDict.getCode().equals(cashTypeCode)) {
            cashFlowManageBasicInfo.setCashStatus(4);
        } else {
            cashFlowManageBasicInfo.setCashStatus(3);
        }

        cashFlowManageBasicInfo.setCashDate(new Date());
        cashFlowManageBasicInfo.setLedgerAccountBasicInfoId(ledgerAccountBasicInfo.getId());
        cashFlowManageBasicInfo.setLedgerFundGoodsAssignId(ledgerFundGoodsAssign.getId());
        cashFlowManageBasicInfoService.save(cashFlowManageBasicInfo);

        if (cashTypeCode.equals(financingAmountDict.getCode())) {
            //类型为保理融资款项时,同步sop现金流保理入账信息
            List<LedgerPlanFactoringAssign> planFactoringAssignList = planFactoringAssignService.findByFundGoodsAssignId(ledgerFundGoodsAssign.getId());
            if (planFactoringAssignList != null && planFactoringAssignList.size() > 0) {
                if (cashTypeCode.equals(financingAmountDict.getCode())) {
                    planFactoringAssignList = planFactoringAssignList.stream().filter(p -> p.getActualDate() != null && DateUtil.compare(p.getActualDate(), ledgerAccountBasicInfo.getLedgerDate()) == 0)
                            .filter(p -> p.getActualAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                }
                //向sop同步现金流入账数据
                BillingNonbusinessManageFactoringentry nonbusinessManageFactoringentry = addCashFlowOutInfoToSop(ledgerAccountBasicInfo, planFactoringAssignList,
                        ledgerFundGoodsAssign, cashFlowManageBasicInfo);
                if (nonbusinessManageFactoringentry != null) {
                    cashFlowManageBasicInfo.setBillingFactoringEntryId(nonbusinessManageFactoringentry.getId());
                    cashFlowManageBasicInfoService.updateById(cashFlowManageBasicInfo);
                }
                //发起OA申请
                startOaPayment(amount, purchContractBasicInfo.getTradingPlatformId(), projectInformation.getcSupplierInfoId(), ledgerFundGoodsAssign.getSupplierId());
            }
        }
        if (cashTypeCode.equals(CashFlowOutTypeDict.ChildEnum.REFUND_MANAGEMENT_FEE.getCode())) {
            List<LedgerPlanFactoringAssign> planFactoringAssignList = planFactoringAssignService.findByFundGoodsAssignId(ledgerFundGoodsAssign.getId());
            for (LedgerPlanFactoringAssign planFactoringAssign : planFactoringAssignList) {
                if (planFactoringAssign.getPlanAmount().compareTo(BigDecimal.ZERO) < 0 && "management_fee".equals(planFactoringAssign.getAmountType())) {
                    PaymentCollectionPlanFactoring factoring = getPlanFactoringByFactoringAssignId(planFactoringAssign);
                    //退款关联关系表添加数据
                    CashFlowManageBasicPayCollPlanRef ref = new CashFlowManageBasicPayCollPlanRef();
                    ref.setPayCollPlanFactoringId(factoring.getId());
                    ref.setCashFlowManageBasicInfoId(cashFlowManageBasicInfo.getId());
                    CashFlowManageBasicPayCollPlanRefService.save(ref);
                }
            }
        }
        if (cashTypeCode.equals(CashFlowOutTypeDict.ChildEnum.REFUND_INTEREST.getCode())) {
            List<LedgerPlanFactoringAssign> planFactoringAssignList = planFactoringAssignService.findByFundGoodsAssignId(ledgerFundGoodsAssign.getId());
            for (LedgerPlanFactoringAssign planFactoringAssign : planFactoringAssignList) {
                if (planFactoringAssign.getPlanAmount().compareTo(BigDecimal.ZERO) < 0 && "interest".equals(planFactoringAssign.getAmountType())) {
                    PaymentCollectionPlanFactoring factoring = getPlanFactoringByFactoringAssignId(planFactoringAssign);
                    //退款关联关系表添加数据
                    CashFlowManageBasicPayCollPlanRef ref = new CashFlowManageBasicPayCollPlanRef();
                    ref.setPayCollPlanFactoringId(factoring.getId());
                    ref.setCashFlowManageBasicInfoId(cashFlowManageBasicInfo.getId());
                    CashFlowManageBasicPayCollPlanRefService.save(ref);
                }
            }
        }
    }

    /**
     * 开启OA归还保理融资款流程
     *
     * @param amount
     * @param tradingPlatformId
     * @param supplierInfoId
     */
    private void startOaPayment(BigDecimal amount, Long tradingPlatformId, Long supplierInfoId, Long supplierId) {
        OaOtherPaymentTradeVo oaOtherPaymentTradeVo = new OaOtherPaymentTradeVo();
        User user = null;
        if (supplierInfoId != null) {
            SupplierInfo supplierInfo = supplierInfoService.getById(supplierInfoId);
            if (supplierInfo != null) {
                UserDO userDO = cUserService.getById(supplierInfo.getSysUserId());
                if (userDO != null) {
                    user = userService.get(userDO.getProjectManager());
                }
            }
        }
        if (user == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到项目对应的业务经理");
        }
        Enterprise enterprise = enterpriseService.getById(supplierId);
        if (enterprise != null) {
            oaOtherPaymentTradeVo.setSupplierName(enterprise.getCorporateName());
        }
        oaOtherPaymentTradeVo.setSysUserStr(user.getLoginName());
        oaOtherPaymentTradeVo.setPaymentAmount(amount);
        List<Long> orgIds = userService.getOrgIdByUserId(user.getId());
        if (CollectionUtil.isEmpty(orgIds)) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到业务经理所属的部门");
        }
        Platform platform = platformService.getById(tradingPlatformId);
        if (platform == null) {
            throw new BusinessException(CodeUtil.FAIL, "获取不到项目对应的贸易平台");
        }
        oaOtherPaymentTradeVo.setOaCompanyEntityStr(platform.getPlatformName());
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(startOaPaymentProcessUrl, oaOtherPaymentTradeVo, String.class);
        ResponseJson responseJson = JSONUtil.toBean(responseEntity.getBody(), ResponseJson.class);
        if (responseEntity.getStatusCode().value() != HttpStatus.OK.value() || !responseJson.isSuccess()) {
            throw new BusinessException(CodeUtil.FAIL, "开启OA申请-归还保理融资款失败：" + responseJson.getMsg().toString());
        }
    }

    /**
     * 根据计划分配表查询sop对应的收放款计划
     *
     * @param planFactoringAssign
     * @return
     */
    private PaymentCollectionPlanFactoring getPlanFactoringByFactoringAssignId(LedgerPlanFactoringAssign planFactoringAssign) {
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(findPlanFactoringIdUrl + "?ledgerPlanFactoringAssignId="
                + planFactoringAssign.getId(), String.class);
        ResponseJson responseJson = JSONUtil.toBean(responseEntity.getBody(), ResponseJson.class);
        if (responseEntity.getStatusCode().value() != HttpStatus.OK.value() || !responseJson.isSuccess()) {
            throw new BusinessException(CodeUtil.FAIL, "根据分账分配Id获取不到对应的收放款计划：" + responseJson.getMsg().toString());
        }
        return JSONUtil.toBean((JSONObject) responseJson.getData(), PaymentCollectionPlanFactoring.class);
    }

    /**
     * 向sop同步现金流入账数据
     *
     * @param ledgerAccountBasicInfo  现金流管理基础信息
     * @param planFactoringAssignList 关联的出账信息
     */
    private BillingNonbusinessManageFactoringentry addCashFlowOutInfoToSop(LedgerAccountBasicInfo ledgerAccountBasicInfo, List<LedgerPlanFactoringAssign> planFactoringAssignList,
                                                                           LedgerFundGoodsAssign ledgerFundGoodsAssign, CashFlowManageBasicInfo cashFlowManageBasicInfo1) {
        //组装数据
        BillingRecordBasic billingRecordBasic = new BillingRecordBasic();
        BillingNonbusinessManageFactoringentry nobusinessManage = new BillingNonbusinessManageFactoringentry();

        if (ledgerAccountBasicInfo != null) {
            //根据业务编号和供应商Id获取对应的采购合同编号
            PurchContractManagement purchContractManagement = purchContractManagementService.getOne(new QueryWrapper<PurchContractManagement>()
                    .eq("business_number", ledgerFundGoodsAssign.getBusinessNumber()));
            if (purchContractManagement == null || purchContractManagement.getId() == null) {
                throw new BusinessException(CodeUtil.FAIL, "采购合同管理不能为空");
            }
            PurchContractBasicInfo purchContractBasicInfo = purchContractBasicInfoService.getOne(new QueryWrapper<PurchContractBasicInfo>()
                    .eq("c_purch_contract_management_id", purchContractManagement.getId()));

            if (purchContractBasicInfo != null) {
                Platform platform = platformService.getById(purchContractBasicInfo.getTradingPlatformId());
                if (platform != null) {
                    nobusinessManage.setFirstLevelProject(platform.getPlatformName());
                    nobusinessManage.setPlatformSocialCreditCode(platform.getSocialCreditCode());
                }
            }

            if (ledgerFundGoodsAssign.getSupplierId() != null) {
                Enterprise enterprise = enterpriseService.getById(ledgerFundGoodsAssign.getSupplierId());
                if (enterprise != null) {
                    nobusinessManage.setSupplierSocialCreditCode(enterprise.getSocialCreditCode());
                }
            }

            BigDecimal actualAmountTotal = planFactoringAssignList.stream().filter(p -> p.getActualAmount() != null)
                    .map(LedgerPlanFactoringAssign::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            nobusinessManage.setAmountMoney(actualAmountTotal);

            Dictionary currencyDict = dictService.getByCode("CNY");
            if (currencyDict == null) {
                throw new BusinessException(CodeUtil.FAIL, "币种字典项不能为空!");
            }
            nobusinessManage.setCurrency(currencyDict);
        }

        nobusinessManage.setBillDate(ledgerAccountBasicInfo.getLedgerDate());
        BankAccountInfo bankAccountInfo = new BankAccountInfo();
        //贸理通临时同步数据账号
        bankAccountInfo.setBankCardNo("888888");
        nobusinessManage.setBankAccountInfo(bankAccountInfo);

        billingRecordBasic.setNobusinessManage(nobusinessManage);


        List<PaymentCollectionPlanFactoring> planFactoringList = new ArrayList<>();

        for (LedgerPlanFactoringAssign planFactoringAssign : planFactoringAssignList) {
            PaymentCollectionPlanFactoring planFactoring = new PaymentCollectionPlanFactoring();
            if (planFactoringAssign.getPlanFactoringId() == null) {
                PaymentCollectionPlanFactoring factoring = getPlanFactoringByFactoringAssignId(planFactoringAssign);
                planFactoring.setId(factoring.getId());
            } else {
                planFactoring.setId(planFactoringAssign.getPlanFactoringId());
            }
            List<PayCollPlanFactoringAmountAllocation> amountAllocationList = new ArrayList<>();
            PayCollPlanFactoringAmountAllocation amountAllocation = new PayCollPlanFactoringAmountAllocation();
            amountAllocation.setActualAmount(planFactoringAssign.getActualAmount());
            amountAllocationList.add(amountAllocation);
            planFactoring.setAmountAllocationList(amountAllocationList);
            planFactoringList.add(planFactoring);
        }
        billingRecordBasic.setPlanFactoringList(planFactoringList);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(billingRecordBasicAddUrl, billingRecordBasic, String.class);
        ResponseJson responseJson = JSONUtil.toBean(responseEntity.getBody(), ResponseJson.class);
        if (responseEntity.getStatusCode().value() != HttpStatus.OK.value() || !responseJson.isSuccess()) {
            throw new BusinessException(CodeUtil.FAIL, "数据同步到sop失败：" + responseJson.getMsg().toString());
        }
        return JSONUtil.toBean((JSONObject) responseJson.getData(), BillingNonbusinessManageFactoringentry.class);
    }


    /**
     * 分账数据提交校验
     *
     * @param ledgerAccountInfoVo
     */
    private void validatorData(LedgerAccountInfoVo ledgerAccountInfoVo) {
        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountInfoVo.getLedgerAccountBasicInfo();

        if (ledgerAccountBasicInfo != null) {
            //货物金额+贴现费用 = 入账金额
            BigDecimal ledgerAmount = ledgerAccountBasicInfo.getLedgerAmount() == null ? BigDecimal.ZERO : ledgerAccountBasicInfo.getLedgerAmount();
            BigDecimal goodsAssignAmount = ledgerAccountBasicInfo.getGoodsAmount() == null ? BigDecimal.ZERO : ledgerAccountBasicInfo.getGoodsAmount();
            BigDecimal discountChargeAmount = ledgerAccountBasicInfo.getDiscountCharge() == null ? BigDecimal.ZERO : ledgerAccountBasicInfo.getDiscountCharge();
            if (ledgerAmount.compareTo(goodsAssignAmount.add(discountChargeAmount)) != 0) {
                throw new ValidatorException(CodeUtil.FAIL, "货物金额+贴现费用不等于入账金额");
            }

            //货物金额 = 各货物金额之和
            List<LedgerFundGoodsAssign> goodsAssignList = ledgerAccountInfoVo.getGoodsAssignList();
            BigDecimal goodsAssignTotal = BigDecimal.ZERO;
            if (goodsAssignList != null && goodsAssignList.size() > 0) {
                for (LedgerFundGoodsAssign goodsAssign : goodsAssignList) {
                    if (goodsAssign.getFinancingPrincipal() == null || goodsAssign.getFinancingInterest() == null
                            || goodsAssign.getPlatformProfit() == null || goodsAssign.getDiscountAmount() == null) {
                        throw new ValidatorException(CodeUtil.FAIL, "需要一键计算出货物分配金额才能提交");
                    }
                }
                goodsAssignTotal = goodsAssignList.stream().filter(g -> g.getCurrentAssignAmount() != null)
                        .map(LedgerFundGoodsAssign::getCurrentAssignAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
            if (goodsAssignTotal.compareTo(goodsAssignAmount) != 0) {
                throw new ValidatorException(CodeUtil.FAIL, "货物金额必须等于各货物金额之和");
            }
        }
    }

    @Override
    public LedgerAccountInfoVo getById(Long id) {

        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountBasicInfoService.getDetail(id);
        if (ledgerAccountBasicInfo == null || ledgerAccountBasicInfo.getId() == null) {
            throw new ValidatorException(CodeUtil.FAIL, "分账基础信息不能为空");
        }

        LedgerAccountInfoVo ledgerAccountInfoVo = new LedgerAccountInfoVo();
        ledgerAccountInfoVo.setLedgerAccountBasicInfo(ledgerAccountBasicInfo);

        //货款分配
        List<LedgerFundGoodsAssign> goodsAssignList = ledgerFundGoodsAssignService.findByBasicId(ledgerAccountBasicInfo.getId());
        ledgerAccountInfoVo.setGoodsAssignList(goodsAssignList);

        //资金占用费
//        List<LedgerFundPossessionCost> fundPossessionCostList = ledgerFundPossessionCostService.findByBasicId(ledgerAccountBasicInfo.getId());
//        if (fundPossessionCostList != null && fundPossessionCostList.size() > 0) {
//            ledgerAccountInfoVo.setLedgerFundPossessionCostList(fundPossessionCostList);
//        }
        //关联的供应商账户
        List<SupplierBankCardInfo> supplierBankCardInfoList = supplierBankCardInfoService.list(new QueryWrapper<SupplierBankCardInfo>()
                .eq("ledger_account_basic_info_id", ledgerAccountBasicInfo.getId()));
        ledgerAccountInfoVo.setSupplierBankCardInfoList(supplierBankCardInfoList);
        return ledgerAccountInfoVo;
    }

    @Override
    public List<LedgerFundGoodsAssign> findFinancingGoodsList(LedgerPlanFactoringSearch search) {

        //选择对应业务编号下的所有已开过票的结算单信息
        if (search.getLabel() == null) {
            throw new BusinessException(CodeUtil.FAIL, "标签不能为空");
        }
        //选择对应业务编号下的所有已开过票的底层编号  底层货物计算是需要用到
        List<Long> sopAccountsReceivableIds = new ArrayList<>();
        if (search.getLabel().equals(0L)) {
            //下游回款、查询核心企业
            sopAccountsReceivableIds = ledgerManagementMapper.findAccountsReceivableIdsByEnterpriseId(search.getEnterpriseId());
        } else if (search.getLabel().equals(1L)) {
            //上游回购、查询供应商
            sopAccountsReceivableIds = ledgerManagementMapper.findAccountsReceivableIdsBySupplierId(search.getEnterpriseId());
        }
        if (sopAccountsReceivableIds != null && sopAccountsReceivableIds.size() > 0) {
            search.setSopAccountsReceivableIds(sopAccountsReceivableIds);
            search.setLevel("all");
            ResponseEntity<List> responseEntity = restTemplate.postForEntity(findGoodsAssignInfoUrl, search, List.class);
            if (responseEntity.getStatusCode() != HttpStatus.OK) {
                throw new BusinessException(CodeUtil.FAIL, "调用SOP接口获取货款分配信息失败");
            }
            if (responseEntity.getBody() != null) {
                List<Map<String, Object>> rows = responseEntity.getBody();
                //获取销售总价、采购总价、底层编号
                List<LedgerFundGoodsAssign> voList = new ArrayList<>();
                for (Map<String, Object> row : rows) {
                    LedgerFundGoodsAssign goodsAssignVo = BeanUtil.mapToBean(row, LedgerFundGoodsAssign.class, true);
                    voList.add(goodsAssignVo);
                }
                List<LedgerFundGoodsAssign> goodsAssignVoList = new ArrayList<>();
                for (LedgerFundGoodsAssign goodsAssignVo : voList) {
                    //该底层的实际放款金额
                    BigDecimal actualLoanAmount = BigDecimal.ZERO;
                    for (LedgerFundGoodsAssign ledgerFundGoodsAssign : voList) {
                        if (goodsAssignVo.getSopAccountsReceivableId().equals(ledgerFundGoodsAssign.getSopAccountsReceivableId())) {
                            actualLoanAmount = actualLoanAmount.add(ledgerFundGoodsAssign.getLoanAmount());
                        }
                    }
                    BigDecimal toAssignedAmount = BigDecimal.ZERO;
                    if (goodsAssignVo.getSopAccountsReceivableId() != null) {
                        CFinancingBasicInfo basicInfo = financingBasicInfoService.getOne(new QueryWrapper<CFinancingBasicInfo>()
                                .eq("sop_accounts_receivable_id", goodsAssignVo.getSopAccountsReceivableId()));
                        if (basicInfo != null) {
                            //     对于单笔底层多次放款，无法拆分 销售总价和采购总价 的情况，计算规则为：
                            //     单次放款的销售总价为：单次放款金额/该笔底层的实际放款金额  *  该笔底层的销售总价
                            //     单次放款的采购总价为：单次放款金额/该笔底层的实际放款金额  *  该笔底层的采购总价
                            goodsAssignVo.setBusinessNumber(basicInfo.getBusinessNumber());
                            BigDecimal salesTotalPriceSum = financingGoodsInfoService.sumSalesTotalPrice(basicInfo.getId());
                            salesTotalPriceSum = salesTotalPriceSum.multiply(goodsAssignVo.getLoanAmount()).divide(actualLoanAmount, 2, BigDecimal.ROUND_HALF_UP);
                            goodsAssignVo.setSalesTotalPrice(salesTotalPriceSum);

                            BigDecimal purchaseTotalPriceSum = financingGoodsInfoService.sumPurchaseTotalPrice(basicInfo.getId());
                            purchaseTotalPriceSum = purchaseTotalPriceSum.multiply(goodsAssignVo.getLoanAmount()).divide(actualLoanAmount, 2, BigDecimal.ROUND_HALF_UP);
                            goodsAssignVo.setPurchaseTotalPrice(purchaseTotalPriceSum);

                            // 计算待分配金额 = 贸理通底层对应的销售总价-已分账金额
                            //计算已分账金额
                            BigDecimal assignAmount = ledgerFundGoodsAssignService.calculateAssignAmount(goodsAssignVo.getSopAccountsReceivableId()
                                    , goodsAssignVo.getBillingFactoringBusinessLoanRecordId());
                            toAssignedAmount = salesTotalPriceSum.subtract(assignAmount);
                        }
                        goodsAssignVo.setToAssignedAmount(toAssignedAmount);
                        //根据供应商名称获取供应商Id
                        Enterprise enterprise = enterpriseService.getOne(new QueryWrapper<Enterprise>()
                                .eq("corporate_name", goodsAssignVo.getSupplierName()));
                        if (enterprise == null || enterprise.getId() == null) {
                            throw new BusinessException(CodeUtil.FAIL, "根据供应商名称获取不到对应供应商信息");
                        }
                        goodsAssignVo.setSupplierId(enterprise.getId());
                    }
                    goodsAssignVoList.add(goodsAssignVo);
                }
                return goodsAssignVoList;
            }
        }
        return null;
    }

    @Override
    public List<LedgerFundGoodsAssign> findAcceptanceGoodsList(LedgerPlanFactoringSearch search) {

        //选择对应业务编号下的所有已开过票的结算单信息
        if (search.getLabel() == null) {
            throw new BusinessException(CodeUtil.FAIL, "标签不能为空");
        }

        List<LedgerFundGoodsAssign> goodsAssignVoList = new ArrayList<>();
        if (search.getLabel().equals(0L)) {
            //下游回款、查询核心企业
            goodsAssignVoList = ledgerManagementMapper.findAcceptanceByEnterpriseId(search.getEnterpriseId());
        } else if (search.getLabel().equals(1L)) {
            //上游回购、查询供应商
            goodsAssignVoList = ledgerManagementMapper.findAcceptanceBySupplierId(search.getEnterpriseId());
        }

        //获取销售总价、待分配金额
        if (goodsAssignVoList != null && goodsAssignVoList.size() > 0) {
            for (LedgerFundGoodsAssign ledgerFundGoodsAssign : goodsAssignVoList) {
                List<SettlementGoodsInfo> settlementGoodsInfos = settlementGoodsInfoService
                        .list(new QueryWrapper<SettlementGoodsInfo>().eq("c_settlement_basic_info_id", ledgerFundGoodsAssign.getId()));
                BigDecimal salesTotalPriceSum = BigDecimal.ZERO;
                BigDecimal purchaseTotalPriceSum = BigDecimal.ZERO;
                if (settlementGoodsInfos != null && settlementGoodsInfos.size() > 0) {
                    salesTotalPriceSum = settlementGoodsInfos.stream().filter(s -> s.getSalesTotalPrice() != null)
                            .map(SettlementGoodsInfo::getSalesTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    purchaseTotalPriceSum = settlementGoodsInfos.stream().filter(s -> s.getPurchaseTotalPrice() != null)
                            .map(SettlementGoodsInfo::getPurchaseTotalPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                }
                ledgerFundGoodsAssign.setSalesTotalPrice(salesTotalPriceSum);
                ledgerFundGoodsAssign.setPurchaseTotalPrice(purchaseTotalPriceSum);
                // 计算待分配金额 = 结算单对应的销售总价-已分账金额
                //计算销售总价
                BigDecimal toAssignedAmount = BigDecimal.ZERO;
                if (ledgerFundGoodsAssign.getSettlementNumber() != null) {
                    SettlementBasicInfo settlementBasicInfo = settlementBasicInfoService.getOne(new QueryWrapper<SettlementBasicInfo>()
                            .eq("settlement_number", ledgerFundGoodsAssign.getSettlementNumber()));
                    if (settlementBasicInfo != null) {
                        BigDecimal salesTotalPrice = settlementGoodsInfoService.sumSalesTotalPrice(settlementBasicInfo.getId());
                        //计算已分账金额
                        BigDecimal assignAmount = ledgerFundGoodsAssignService.calculateAssignAmount(ledgerFundGoodsAssign.getSettlementNumber());
                        toAssignedAmount = salesTotalPrice.subtract(assignAmount);
                    }
                }
                ledgerFundGoodsAssign.setToAssignedAmount(toAssignedAmount);
            }
        }
        return goodsAssignVoList;
    }

    @Override
    public List<SupplierBankCardInfo> findSupplierBankInfoList(List<LedgerFundGoodsAssign> goodsAssignList) {

        if (CollectionUtil.isEmpty(goodsAssignList)) {
            throw new BusinessException(CodeUtil.FAIL, "货物信息不能为空");
        }

        List<SupplierBankCardInfo> supplierBankCardInfoList = new ArrayList<>();
        for (LedgerFundGoodsAssign goodsAssign : goodsAssignList) {
            if (goodsAssign.getSopAccountsReceivableId() != null) {
                //已融资货物
                CFinancingBasicInfo financingBasicInfo = financingBasicInfoService.getOne(new QueryWrapper<CFinancingBasicInfo>()
                        .eq("sop_accounts_receivable_id", goodsAssign.getSopAccountsReceivableId()));
                if (financingBasicInfo != null) {
                    CFinancingApplicantInfo financingApplicantInfo = financingApplicantInfoService.getOne(new QueryWrapper<CFinancingApplicantInfo>()
                            .eq("c_financing_basic_info_id", financingBasicInfo.getId()));
                    if (financingApplicantInfo != null) {
                        SupplierBankCardInfo supplierBankCardInfo = new SupplierBankCardInfo(financingApplicantInfo);
                        autoSupplierName(goodsAssign.getSupplierId(), supplierBankCardInfo);
                        supplierBankCardInfoList.add(supplierBankCardInfo);
                    }
                }
            } else {
                //已验收货物
                if (goodsAssign.getBusinessNumber() != null) {
                    PurchContractManagement purchContractManagement = purchContractManagementService.getOne(new QueryWrapper<PurchContractManagement>()
                            .eq("business_number", goodsAssign.getBusinessNumber()));
                    if (purchContractManagement == null || purchContractManagement.getId() == null) {
                        throw new BusinessException(CodeUtil.FAIL, "采购合同管理不能为空");
                    }
                    PurchContractBasicInfo purchContractBasicInfo = purchContractBasicInfoService.getOne(new QueryWrapper<PurchContractBasicInfo>()
                            .eq("c_purch_contract_management_id", purchContractManagement.getId()));
                    if (purchContractBasicInfo != null) {
                        PurchContractSettlePayment purchContractSettlePayment = purchContractSettlePaymentService.getOne(new QueryWrapper<PurchContractSettlePayment>()
                                .eq("c_purch_contract_basic_info_id", purchContractBasicInfo.getId()));
                        if (purchContractSettlePayment != null) {
                            SupplierBankCardInfo supplierBankCardInfo = new SupplierBankCardInfo(purchContractSettlePayment);
                            autoSupplierName(goodsAssign.getSupplierId(), supplierBankCardInfo);
                            supplierBankCardInfoList.add(supplierBankCardInfo);
                        }
                    }
                }
            }
        }
        //去重
        supplierBankCardInfoList = supplierBankCardInfoList.stream().distinct().collect(Collectors.toList());
        return supplierBankCardInfoList;
    }

    /**
     * 填充供应商
     *
     * @param supplierId
     * @param supplierBankCardInfo
     */
    private void autoSupplierName(Long supplierId, SupplierBankCardInfo supplierBankCardInfo) {
        if (supplierId != null) {
            supplierBankCardInfo.setSupplierId(supplierId);
            Enterprise enterprise = enterpriseService.getById(supplierId);
            if (enterprise != null) {
                supplierBankCardInfo.setSupplierName(enterprise.getCorporateName());
            }
        }
    }


    @Override
    public GridPage<PaymentCollectionPlanFactoring> findPayCollPlanFactoringList(LedgerPlanFactoringSearch search) {

        if (search.getSopAccountsReceivableId() == null || search.getBillingFactoringBusinessLoanRecordId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "参数不能为空");
        }

        ResponseEntity<GridPage> responseEntity = restTemplate.getForEntity(payCollPlanFactoringListUrl + "?rows=" + search.getRows() + "&page="
                + search.getPage() + "&accountsReceivableId=" + search.getSopAccountsReceivableId()
                + "&billingFactoringBusinessLoanRecordId=" + search.getBillingFactoringBusinessLoanRecordId(), GridPage.class);
        return responseEntity.getBody();
    }

    /**
     * 获取未完成的收放款计划
     *
     * @param sopAccountsReceivableId              sop应收账款Id
     * @param billingFactoringBusinessLoanRecordId sop放款记录Id
     * @return
     */
    public List<PaymentCollectionPlanFactoring> findUnCompletePayCollPlanFactoringList(Long sopAccountsReceivableId, Long billingFactoringBusinessLoanRecordId) {

        ResponseEntity<PaymentCollectionPlanFactoring[]> responseEntity = restTemplate
                .getForEntity(unCompletePayCollPlanFactoringList + "?accountsReceivableId=" + sopAccountsReceivableId
                        + "&billingFactoringBusinessLoanRecordId=" + billingFactoringBusinessLoanRecordId, PaymentCollectionPlanFactoring[].class);
        if (responseEntity.getBody() == null) {
            throw new BusinessException(CodeUtil.FAIL, "分配的货物有对应的在途业务：额度支用支用对应底层，但财务尚未确认付款未生成收放款计划");
        }
        return Arrays.asList(responseEntity.getBody());
    }

    /**
     * 获取所有的收放款计划
     *
     * @param sopAccountsReceivableId              sop应收账款Id
     * @param billingFactoringBusinessLoanRecordId sop放款记录Id
     * @return
     */
    public List<PaymentCollectionPlanFactoring> findAllPayCollPlanFactoringList(Long sopAccountsReceivableId, Long billingFactoringBusinessLoanRecordId) {

        ResponseEntity<PaymentCollectionPlanFactoring[]> responseEntity = restTemplate
                .getForEntity(allPayCollPlanFactoringList + "?accountsReceivableId=" + sopAccountsReceivableId
                        + "&billingFactoringBusinessLoanRecordId=" + billingFactoringBusinessLoanRecordId, PaymentCollectionPlanFactoring[].class);
        if (responseEntity.getBody() == null) {
            throw new BusinessException(CodeUtil.FAIL, "分配的货物有对应的在途业务：额度支用支用对应底层，但财务尚未确认付款未生成收放款计划");
        }
        return Arrays.asList(responseEntity.getBody());
    }

    /**
     * 获取利息计算方式、融资利率、利息是否计算投放日
     *
     * @param sopAccountsReceivableId sop应收账款Id
     * @return
     */
    private PrePaymentCalculateVo findPrepaymentInterestCal(Long sopAccountsReceivableId, Long billingFactoringBusinessLoanRecordId) {

        ResponseEntity<PrePaymentCalculateVo> responseEntity = restTemplate
                .getForEntity(findPrepaymentInterestCalUrl + "?accountsReceivableId=" + sopAccountsReceivableId
                        + "&billingFactoringBusinessLoanRecordId=" + billingFactoringBusinessLoanRecordId, PrePaymentCalculateVo.class);
        return responseEntity.getBody();
    }


    @Override
    public LedgerAccountInfoVo calculateAssign(LedgerAccountInfoVo ledgerAccountInfoVo) {

        List<LedgerFundGoodsAssign> ledgerFundGoodsAssignList = ledgerAccountInfoVo.getGoodsAssignList();
        if (ledgerFundGoodsAssignList == null || ledgerFundGoodsAssignList.isEmpty()) {
            throw new BusinessException(CodeUtil.FAIL, "货物列表不能为空");
        }
        //获取货物中的所有业务编号（去重）
        List<String> businessNumberList = ledgerFundGoodsAssignList.stream().filter(ledgerFundGoodsAssign -> ledgerFundGoodsAssign.getBusinessNumber() != null)
                .map(LedgerFundGoodsAssign::getBusinessNumber).distinct().collect(Collectors.toList());

        List<GoodsOccupyVo> goodsOccupyVos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(businessNumberList)) {
            for (String businessNumber : businessNumberList) {
                SalesContractApproval salesContractApproval = getSalesContractApproval(businessNumber);
                //业务下的履约保证金上限
                BigDecimal depositLimit = null;
                if (salesContractApproval.getPerformanceBondLimit() != null) {
                    depositLimit = new BigDecimal(salesContractApproval.getPerformanceBondLimit());
                }

                //业务下质保金上限和质保金比例
                SalesContractRetentionInfo salesContractRetentionInfo = salesContractRetentionInfoService.getOne(new QueryWrapper<SalesContractRetentionInfo>()
                        .eq("sales_contract_approval_id", salesContractApproval.getId()));
                //质保金上限
                BigDecimal retentionLimit = salesContractRetentionInfo.getRetentionLimit();

                List<LedgerFundGoodsAssign> goodsAssignList = ledgerFundGoodsAssignService.list(new QueryWrapper<LedgerFundGoodsAssign>()
                        .eq("business_number", businessNumber));
                //剩余可分配质保金
                BigDecimal occupyRetention = goodsAssignList.stream().filter(l -> l.getGuarantee() != null && l.getSubmit() != null && l.getSubmit())
                        .map(LedgerFundGoodsAssign::getGuarantee).reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal surplusRetentionAmount = null;
                if (retentionLimit != null) {
                    surplusRetentionAmount = retentionLimit.subtract(occupyRetention);
                }
                //质保金比例
                BigDecimal retentionPercent = salesContractRetentionInfo.getRetentionPercent();
                // 计算该业务已经占用的计提金
                BigDecimal occupyAmount = goodsAssignList.stream().filter(l -> l.getAccrualAmount() != null && l.getSubmit() != null && l.getSubmit())
                        .map(LedgerFundGoodsAssign::getAccrualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                //该业务剩余可用计提金额
                BigDecimal surplusAccrualAmount = depositLimit.subtract(occupyAmount);
                GoodsOccupyVo goodsOccupyVo = new GoodsOccupyVo(businessNumber, depositLimit, retentionLimit,
                        surplusRetentionAmount, retentionPercent, occupyAmount, surplusAccrualAmount);
                goodsOccupyVos.add(goodsOccupyVo);
            }
        }

        Dictionary principalDict = dictService.getByCode(IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode());
        if (principalDict == null || principalDict.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "本金字典项不能为空!");
        }
        Dictionary interestDict = dictService.getByCode(IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode());
        if (interestDict == null || interestDict.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "利息字典项不能为空!");
        }
        Dictionary managementFeeDict = dictService.getByCode(IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode());
        if (managementFeeDict == null || managementFeeDict.getId() == null) {
            throw new BusinessException(CodeUtil.FAIL, "管理费字典项不能为空!");
        }
        if (ledgerFundGoodsAssignList != null && ledgerFundGoodsAssignList.size() > 0) {
            for (LedgerFundGoodsAssign goodsAssignVo : ledgerFundGoodsAssignList) {
                //本次分配金额
                BigDecimal thisAssignAmount = goodsAssignVo.getCurrentAssignAmount() == null ? BigDecimal.ZERO
                        : goodsAssignVo.getCurrentAssignAmount();
                //待分配金额
                BigDecimal toAssignedAmount = goodsAssignVo.getToAssignedAmount() == null ? BigDecimal.ZERO
                        : goodsAssignVo.getToAssignedAmount();
                if (thisAssignAmount.compareTo(toAssignedAmount) == 1) {
                    throw new BusinessException(CodeUtil.FAIL, "本次分配金额不能大于待分配金额");
                }
                List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList = new ArrayList<>();
                if (StringUtils.isBlank(goodsAssignVo.getContractNo()) && goodsAssignVo.getQuotaDisburseBatch() == null) {
                    //说明选的是结算单货物
                    //该笔结算单已存在的货款分配
                    List<LedgerFundGoodsAssign> oldLedgerFundGoodsAssignLists = ledgerFundGoodsAssignService.list(
                            new QueryWrapper<LedgerFundGoodsAssign>().eq("settlement_number", goodsAssignVo.getSettlementNumber())
                                    .eq("is_submit", true));
                    //该次结算放款已有平台利润
                    BigDecimal existingProfit = BigDecimal.ZERO;
                    for (LedgerFundGoodsAssign oldLedgerFundGoodsAssignList : oldLedgerFundGoodsAssignLists) {
                        //同一笔结算单的同一笔放款计提上限是否已经达到
                        if (oldLedgerFundGoodsAssignList.getSettlementNumber().equals(goodsAssignVo.getSettlementNumber())) {
                            existingProfit = existingProfit.add(oldLedgerFundGoodsAssignList.getPlatformProfit());
                        }
                    }
                    //融资利息、融资本金置为0
                    goodsAssignVo.setFinancingPrincipal(BigDecimal.ZERO);
                    goodsAssignVo.setFinancingInterest(BigDecimal.ZERO);
                    //最大平台利润= 销售总价-采购总价
                    BigDecimal salesTotalPrice = goodsAssignVo.getSalesTotalPrice() == null ? BigDecimal.ZERO
                            : goodsAssignVo.getSalesTotalPrice();
                    BigDecimal purchaseTotalPrice = goodsAssignVo.getPurchaseTotalPrice() == null ? BigDecimal.ZERO
                            : goodsAssignVo.getPurchaseTotalPrice();
                    BigDecimal platformProfit = salesTotalPrice.subtract(purchaseTotalPrice);

                    //最大平台利润和已有平台利润比较
                    if (existingProfit.compareTo(platformProfit) == -1) {
                        platformProfit = platformProfit.subtract(existingProfit);
                    } else {
                        platformProfit = BigDecimal.ZERO;
                    }
                    //平台利润和分配金额比较
                    if (platformProfit.compareTo(thisAssignAmount) >= 0) {
                        platformProfit = thisAssignAmount;
                    }
                    goodsAssignVo.setPlatformProfit(platformProfit);
                    thisAssignAmount = thisAssignAmount.subtract(platformProfit);
                    //2024.3.16 新增质保金逻辑
                    //获取质保金上限
                    GoodsOccupyVo occupyVo = goodsOccupyVos.stream().filter(goodsOccupyVo -> goodsOccupyVo.getBusinessNumber().equals(goodsAssignVo.getBusinessNumber()))
                            .collect(Collectors.toList()).get(0);
                    BigDecimal retentionLimit = occupyVo.getRetentionLimit();
                    BigDecimal surplusRetentionAmount = occupyVo.getSurplusRetentionAmount();
                    BigDecimal retentionPercent = occupyVo.getRetentionPercent();
                    //质保金=销售总价*质保金比例
                    BigDecimal retentionAmount = goodsAssignVo.getSalesTotalPrice().multiply(retentionPercent)
                            .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                    BigDecimal currentAssignRetention = thisAssignAmount.compareTo(retentionAmount) <= 0 ? thisAssignAmount : retentionAmount;
                    if (retentionLimit != null && surplusRetentionAmount != null) {
                        if (currentAssignRetention.compareTo(surplusRetentionAmount) >= 0) {
                            currentAssignRetention = surplusRetentionAmount;
                        }
                    }
                    occupyVo.setSurplusRetentionAmount(surplusRetentionAmount.subtract(currentAssignRetention));
                    goodsAssignVo.setGuarantee(currentAssignRetention);
                    thisAssignAmount = thisAssignAmount.subtract(currentAssignRetention);
                    // 计提金额  结算货物 无计提金额
                    BigDecimal accrualAmount = BigDecimal.ZERO;
                    goodsAssignVo.setAccrualAmount(accrualAmount);
                    //实退金额= 本次分配金额-保理融资利息-保理融资本金-计提金额-平台利润
                    BigDecimal discountAmount = thisAssignAmount.subtract(accrualAmount);
                    goodsAssignVo.setDiscountAmount(discountAmount);
                    goodsAssignVo.setLedgerPlanFactoringAssignList(ledgerPlanFactoringAssignList);
                }
                if (StringUtils.isNotBlank(goodsAssignVo.getContractNo()) && goodsAssignVo.getQuotaDisburseBatch() != null) {
                    //说明选的是底层货物
                    BigDecimal financePrincipal = BigDecimal.ZERO;
                    BigDecimal financeInterest = BigDecimal.ZERO;
                    BigDecimal financingManagementFee = BigDecimal.ZERO;
                    BigDecimal financingOverdueInterest = BigDecimal.ZERO;
                    BigDecimal refundInterest = BigDecimal.ZERO;
                    BigDecimal refundManagement = BigDecimal.ZERO;

                    //本次分配金额
                    BigDecimal assignAmount = goodsAssignVo.getCurrentAssignAmount();
                    //待回款本金
                    BigDecimal returnedAmount = goodsAssignVo.getReturnedAmount() == null ? BigDecimal.ZERO : goodsAssignVo.getReturnedAmount();
                    if (returnedAmount.compareTo(BigDecimal.ZERO) > 0) {
                        if (goodsAssignVo.getSopAccountsReceivableId() == null || goodsAssignVo.getBillingFactoringBusinessLoanRecordId() == null) {
                            throw new BusinessException(CodeUtil.FAIL, "传参异常");
                        }
                        //查询所有未完成的收放款计划
                        List<PaymentCollectionPlanFactoring> planFactoringList = findUnCompletePayCollPlanFactoringList(goodsAssignVo.getSopAccountsReceivableId(),
                                goodsAssignVo.getBillingFactoringBusinessLoanRecordId());
                        planFactoringList.stream().filter(p -> p.getPlanDate() != null).forEach(p -> p.setPlanDate(DateUtil.beginOfDay(p.getPlanDate())));

                        //入账日期
                        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountInfoVo.getLedgerAccountBasicInfo();
                        Date ledgerDate = ledgerAccountBasicInfo.getLedgerDate();

                        //判断还款方式
                        Long sopAccountsReceivableId = goodsAssignVo.getSopAccountsReceivableId();
                        Long billingFactoringBusinessLoanRecordId = goodsAssignVo.getBillingFactoringBusinessLoanRecordId();
                        PrePaymentCalculateVo paymentCalculateVo = findPrepaymentInterestCal(sopAccountsReceivableId, billingFactoringBusinessLoanRecordId);
                        if (paymentCalculateVo.getPayBackMethod() == null || paymentCalculateVo.getPayBackMethod().getId() == null) {
                            throw new BusinessException(CodeUtil.FAIL, "无法获取到该业务的还款方式");
                        }
                        Dictionary payBackMethod = paymentCalculateVo.getPayBackMethod();

                        if (payBackMethod.getCode().equals("pre_interest")
                                || payBackMethod.getCode().equals("after_interest") || payBackMethod.getCode().equals("pre_management_after_interest")) {
                            //查询所有的收放款计划
                            List<PaymentCollectionPlanFactoring> allPlanFactoringList = findAllPayCollPlanFactoringList(sopAccountsReceivableId, billingFactoringBusinessLoanRecordId);
                            //获取所有的本金收款计划
                            List<PaymentCollectionPlanFactoring> principalFactoringList = getFactoringByAmountType(allPlanFactoringList, principalDict);
                            //检验本金是否存在
                            validatePlanFactoring(principalFactoringList);

                            //1.查看计划是否有逾期利息未分完的，存在先分逾期利息
                            if (goodsAssignVo.getHasAssignOverdueInterest()) {
                                List<PaymentCollectionPlanFactoring> overdueInterestList = planFactoringList.stream()
                                        .filter(f -> f.getAmountType().getCode().equals("overdue_interest") && f.getPlanDate().before(ledgerDate))
                                        .sorted(Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate)).collect(Collectors.toList());
                                if (overdueInterestList != null && overdueInterestList.size() > 0) {
                                    for (PaymentCollectionPlanFactoring factoring : overdueInterestList) {
                                        BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                        financingOverdueInterest = financingOverdueInterest.add(currentAssignAmount);
                                        assignAmount = assignAmount.subtract(currentAssignAmount);
                                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, currentAssignAmount, factoring, goodsAssignVo, 0));
                                        if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                            //说明钱已经分完了，结束分配
                                            break;
                                        }
                                    }
                                }
                            }

                            //2.查看计划是否有其他费用，存在分其它费用
                            List<PaymentCollectionPlanFactoring> otherFeeList = planFactoringList.stream().filter(f -> f.getAmountType().getCode().equals("other_fee")).collect(Collectors.toList());
                            if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                if (otherFeeList != null && otherFeeList.size() > 0) {
                                    for (PaymentCollectionPlanFactoring factoring : otherFeeList) {
                                        BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                        financeInterest = financeInterest.add(currentAssignAmount);
                                        assignAmount = assignAmount.subtract(currentAssignAmount);
                                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, currentAssignAmount, factoring, goodsAssignVo, 0));
                                        if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                            //说明钱已经分完了，结束分配
                                            break;
                                        }
                                    }
                                }
                            }
                            //3.获取所有已经收款的管理费之和
                            BigDecimal actualManagementTotal = getActualAmountTotal(allPlanFactoringList, managementFeeDict);
                            //4.获取所有的已经收款的利息之和
                            BigDecimal actualInterestTotal = getActualAmountTotal(allPlanFactoringList, interestDict);
                            //5.获取截至到分账日期的新的本金计划
                            List<PaymentCollectionPlanFactoring> newPrincipalFactoringList = getPrincipalFactoringByLedgerDate(principalFactoringList, ledgerDate, returnedAmount);
                            //6.计算截至到分账日期计划应收管理费总和
                            BigDecimal planManagementTotal = getAllocatedAmountByPlanFactoring(newPrincipalFactoringList, managementFeeDict,
                                    goodsAssignVo, paymentCalculateVo);
                            //7.计算截至到分账日期计划应收利息总和
                            BigDecimal planInterestTotal = getAllocatedAmountByPlanFactoring(newPrincipalFactoringList, interestDict,
                                    goodsAssignVo, paymentCalculateVo);
                            //剩余未分配管理费
                            BigDecimal unAssignManagement = BigDecimal.ZERO;
                            //剩余未分配利息
                            BigDecimal unAssignInterest = BigDecimal.ZERO;

                            //用已收利息之和减去计划应收、判断需不需要退还
                            refundInterest = actualInterestTotal.subtract(planInterestTotal);
                            //获取所有的利息收款计划
                            List<PaymentCollectionPlanFactoring> interestFactoringList = getFactoringByAmountType(allPlanFactoringList, interestDict);
                            if (refundInterest.compareTo(BigDecimal.ZERO) > 0) {
                                //说明利息分多了，需要将多的退掉
//                                ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, refundInterest.negate(), refundInterest.negate(),
//                                        IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                unAssignInterest = refundInterest.negate();
                                //删除未分配的利息
                                deleteUnAssignList(interestFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                                //将部分分配的利息计划金额改为实收金额
                                updatePartAssignList(interestFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                            } else if (refundInterest.compareTo(BigDecimal.ZERO) == 0) {
                                //删除未分配的利息
                                deleteUnAssignList(interestFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                                //将部分分配的利息计划金额改为实收金额
                                updatePartAssignList(interestFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                            } else if (refundInterest.compareTo(BigDecimal.ZERO) < 0) {
                                //说明利息还需要补
                                BigDecimal toAssignInterest = refundInterest.negate();
                                if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    if (assignAmount.compareTo(toAssignInterest) >= 0) {
                                        //说明本次分的钱可以把管理费分完，增加一条利息分配记录（应分=实分）
                                        if (goodsAssignVo.getHasAssignInterest()) {
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, toAssignInterest, toAssignInterest,
                                                    IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                            financeInterest = financeInterest.add(toAssignInterest);
                                            assignAmount = assignAmount.subtract(toAssignInterest);
                                        } else {
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, toAssignInterest, BigDecimal.ZERO,
                                                    IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                        }
                                    } else if (assignAmount.compareTo(toAssignInterest) < 0) {
                                        //说明本次分的钱把管理费分不完，增加一条利息分配记录（应分>实分）
                                        if (goodsAssignVo.getHasAssignInterest()) {
                                            //如果本次选择分利息
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, assignAmount, assignAmount,
                                                    IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                            financeInterest = financeInterest.add(assignAmount);
                                            assignAmount = BigDecimal.ZERO;
                                        } else {
                                            //如果选择不分利息
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, assignAmount, BigDecimal.ZERO,
                                                    IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                        }
                                        //剩余未分配利息
                                        unAssignInterest = toAssignInterest.subtract(assignAmount);

                                        // 获取最后一期利息收款计划
//                                        PaymentCollectionPlanFactoring interestFactoring = getLastPrincipalFactoring(planFactoringList, interestDict);
//                                        if (interestFactoring != null) {
//                                            List<PayCollPlanFactoringAmountAllocation> allocationList = interestFactoring.getAmountAllocationList();
//                                            BigDecimal allocationAmount = BigDecimal.ZERO;
//                                            if (CollectionUtil.isNotEmpty(allocationList)) {
//                                                allocationAmount = allocationList.stream().filter(a -> a.getActualAmount() != null)
//                                                        .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//                                            }
//                                            if (interestFactoring.getAmount().compareTo(allocationAmount) > 0) {
//                                                //说明是未完成的计划
//                                                interestFactoring.setAmount(unAssignInterest.add(interestFactoring.getAmount()));
//                                                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(interestFactoring.getPlanDate(), BigDecimal.ZERO,
//                                                        interestFactoring, goodsAssignVo, 0));
//                                            }
//                                        } else {
//                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, unAssignInterest, BigDecimal.ZERO,
//                                                    IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
//                                        }
                                    }

                                }
                            }

                            //用已收管理费之和减去计划应收、判断需不需要退还
                            refundManagement = actualManagementTotal.subtract(planManagementTotal);
                            //获取所有的管理费收款计划
                            List<PaymentCollectionPlanFactoring> managementFeeFactoringList = getFactoringByAmountType(allPlanFactoringList, managementFeeDict);
                            if (refundManagement.compareTo(BigDecimal.ZERO) > 0) {
                                //说明管理费分多了，需要将多的退掉
//                                ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, refundManagement.negate(), refundManagement.negate(),
//                                        IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                unAssignManagement = refundManagement.negate();
                                //删除未分配的管理费
                                deleteUnAssignList(managementFeeFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                                //将部分分配的管理费计划金额改为实收金额
                                updatePartAssignList(managementFeeFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                            } else if (refundManagement.compareTo(BigDecimal.ZERO) == 0) {
                                //说明管理费正好，只需要处理未完成的计划
                                //删除未分配的管理费
                                deleteUnAssignList(managementFeeFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                                //将部分分配的管理费计划金额改为实收金额
                                updatePartAssignList(managementFeeFactoringList, ledgerPlanFactoringAssignList, goodsAssignVo);
                            } else if (refundManagement.compareTo(BigDecimal.ZERO) < 0) {
                                //说明管理费还需要补
                                BigDecimal toAssignManagement = refundManagement.negate();
                                if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    if (assignAmount.compareTo(toAssignManagement) >= 0) {
                                        //说明本次分的钱可以把管理费分完，增加一条管理费分配记录
                                        if (goodsAssignVo.getHasAssignManagementFee()) {
                                            //如果本次选择分管理费
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, toAssignManagement, toAssignManagement,
                                                    IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                            financingManagementFee = financingManagementFee.add(toAssignManagement);
                                            assignAmount = assignAmount.subtract(toAssignManagement);
                                        } else {
                                            //如果本次选择不分管理费
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, toAssignManagement, BigDecimal.ZERO,
                                                    IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                        }
                                    } else if (assignAmount.compareTo(toAssignManagement) < 0) {
                                        //说明本次分的钱把管理费分不完，增加一条管理费分配记录
                                        if (goodsAssignVo.getHasAssignManagementFee()) {
                                            //如果本次选择分管理费
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, assignAmount, assignAmount,
                                                    IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                            financingManagementFee = financingManagementFee.add(assignAmount);
                                            assignAmount = BigDecimal.ZERO;
                                        } else {
                                            //如果本次选择不分管理费
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, assignAmount, BigDecimal.ZERO,
                                                    IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                        }
                                        //剩余未分配管理费
                                        unAssignManagement = toAssignManagement.subtract(assignAmount);
                                        // 获取最后一期管理费收款计划
//                                        PaymentCollectionPlanFactoring managementFactoring = getLastPrincipalFactoring(planFactoringList, managementFeeDict);
//                                        if (managementFactoring != null) {
//                                            List<PayCollPlanFactoringAmountAllocation> allocationList = managementFactoring.getAmountAllocationList();
//                                            BigDecimal allocationAmount = BigDecimal.ZERO;
//                                            if (CollectionUtil.isNotEmpty(allocationList)) {
//                                                allocationAmount = allocationList.stream().filter(a -> a.getActualAmount() != null)
//                                                        .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
//                                            }
//                                            if (managementFactoring.getAmount().compareTo(allocationAmount) > 0) {
//                                                //说明是未完成的计划
//                                                managementFactoring.setAmount(unAssignManagement.add(managementFactoring.getAmount()));
//                                                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(managementFactoring.getPlanDate(), BigDecimal.ZERO,
//                                                        managementFactoring, goodsAssignVo, 0));
//                                            }
//                                        } else {
//                                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, unAssignManagement, BigDecimal.ZERO,
//                                                    IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
//                                        }
                                    }
                                }
                            }
                            if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                //分配完还有钱去分配本金
                                if (CollectionUtil.isNotEmpty(principalFactoringList)) {
                                    //按计划日期升序排列
                                    Collections.sort(principalFactoringList, Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate));
                                    Boolean flag = false;
                                    for (PaymentCollectionPlanFactoring planFactoring : principalFactoringList) {
                                        if (!PaymentCollectionPlanStatusDict.ChildEnum.COMPLETED.getCode().equals(planFactoring.getStatus().getCode()) &&
                                                !PaymentCollectionPlanStatusDict.ChildEnum.OVERDUE_COMPLETED.getCode().equals(planFactoring.getStatus().getCode())) {
                                            if (flag) {
                                                //金额已分完了
                                                ledgerPlanFactoringAssignList.add(addPlanFactoringDeleteAssign(planFactoring, goodsAssignVo, 1));
                                                continue;
                                            }
                                            if (assignAmount.compareTo(planFactoring.getAmount()) >= 0) {
                                                //本金分配金额>计划金额、说明本金够分
                                                //修改一笔本金收款记录
                                                if (ledgerDate.before(planFactoring.getPlanDate())) {
                                                    //分账日期早于计划日期
                                                    planFactoring.setPlanDate(ledgerDate);
                                                }
                                                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, planFactoring.getAmount(),
                                                        planFactoring, goodsAssignVo, 1));
                                                assignAmount = assignAmount.subtract(planFactoring.getAmount());
                                                returnedAmount = returnedAmount.subtract(planFactoring.getAmount());
                                                financePrincipal = financePrincipal.add(planFactoring.getAmount());
                                            } else {
                                                //说明本金不够分了
                                                if (ledgerDate.before(planFactoring.getPlanDate())) {
                                                    //分账日期早于计划日期
                                                    planFactoring.setPlanDate(ledgerDate);
                                                }
                                                planFactoring.setAmount(assignAmount);
                                                planFactoring.setActualCashFlow(assignAmount);

                                                //修改一笔本金收款记录
                                                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, assignAmount,
                                                        planFactoring, goodsAssignVo, 1));
                                                financePrincipal = financePrincipal.add(assignAmount);
                                                Date lastPlanDate = goodsAssignVo.getLastPlanDate();
                                                //增加一笔剩余本金收款记录
                                                ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPlanDate, returnedAmount.subtract(assignAmount), BigDecimal.ZERO,
                                                        IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode(), goodsAssignVo, 1));
                                                returnedAmount = returnedAmount.subtract(assignAmount);
                                                assignAmount = BigDecimal.ZERO;
                                            }
                                        }
                                    }
                                }
                            }
                            if (returnedAmount.compareTo(BigDecimal.ZERO) == 0) {
                                //说明此分配本金已经分完了
                                if (unAssignInterest.compareTo(BigDecimal.ZERO) != 0) {
                                    //将之前未分配的利息分完
                                    ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, unAssignInterest, unAssignInterest,
                                            IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                }
                                if (unAssignManagement.compareTo(BigDecimal.ZERO) != 0) {
                                    //将之前未分配的管理费分完
                                    ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, unAssignManagement, unAssignManagement,
                                            IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                }
                            } else if (returnedAmount.compareTo(BigDecimal.ZERO) > 0) {
                                //说明此次本金未分完
                                Date lastPlanDate = goodsAssignVo.getLastPlanDate();
                                Boolean hasPrincipalAssign = false;
                                if (returnedAmount.compareTo(goodsAssignVo.getReturnedAmount()) < 0) {
                                    //说明分配过本金
                                    hasPrincipalAssign = true;
                                }
                                //增加一笔剩余利息计划
                                //计算剩余应收利息
                                BigDecimal calculateInterest = calculateAssignInterest(returnedAmount, ledgerDate, lastPlanDate,
                                        !hasPrincipalAssign, paymentCalculateVo, IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode());
                                BigDecimal surplusInterest = calculateInterest.add(unAssignInterest);
                                if (surplusInterest.compareTo(new BigDecimal("0.5")) <= 0 && surplusInterest.compareTo(new BigDecimal("-0.5")) >= 0) {
                                    //误差范围在+0.5之内的、直接忽略
                                    surplusInterest = BigDecimal.ZERO;
                                    refundInterest = BigDecimal.ZERO;
                                }
                                if (surplusInterest.compareTo(BigDecimal.ZERO) < 0) {
                                    refundInterest = surplusInterest.negate();
                                }
                                if (surplusInterest.compareTo(BigDecimal.ZERO) != 0) {
                                    PaymentCollectionPlanFactoring lastInterestFactoring = getLastPrincipalFactoring(allPlanFactoringList, interestDict, lastPlanDate);
                                    if (lastInterestFactoring == null) {
                                        ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPlanDate, surplusInterest, BigDecimal.ZERO,
                                                IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                                    } else {
                                        lastInterestFactoring.setAmount(surplusInterest);
                                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(lastInterestFactoring.getPlanDate(), BigDecimal.ZERO,
                                                lastInterestFactoring, goodsAssignVo, 0));
                                    }

                                }
                                //增加一笔剩余管理费计划
                                //计算剩余应收管理费
                                BigDecimal calculateManagementFee = calculateAssignInterest(returnedAmount, ledgerDate, lastPlanDate,
                                        !hasPrincipalAssign, paymentCalculateVo, IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode());
                                BigDecimal surplusManagement = calculateManagementFee.add(unAssignManagement);
                                if (surplusManagement.compareTo(new BigDecimal("0.5")) <= 0 && surplusManagement.compareTo(new BigDecimal("-0.5")) >= 0) {
                                    //误差范围在+0.5之内的、直接忽略
                                    surplusManagement = BigDecimal.ZERO;
                                    refundManagement = BigDecimal.ZERO;
                                }
                                if (surplusManagement.compareTo(BigDecimal.ZERO) < 0) {
                                    refundManagement = surplusManagement.negate();
                                }
                                if (surplusManagement.compareTo(BigDecimal.ZERO) != 0) {
                                    PaymentCollectionPlanFactoring lastManagementFactoring = getLastPrincipalFactoring(allPlanFactoringList, managementFeeDict, lastPlanDate);
                                    if (lastManagementFactoring == null) {
                                        ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPlanDate, surplusManagement, BigDecimal.ZERO,
                                                IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                                    } else {
                                        lastManagementFactoring.setAmount(surplusManagement);
                                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(lastManagementFactoring.getPlanDate(), BigDecimal.ZERO,
                                                lastManagementFactoring, goodsAssignVo, 0));
                                    }

                                }
                            }
                        } else if (payBackMethod.getCode().equals("manually_generated")) {
                            //还款方式为手动生成
                            //1.查询有没有分账当天及之前的还款计划、没有提示用户去修改计划、有的话只分配当天的计划
                            List<PaymentCollectionPlanFactoring> filterList = planFactoringList.stream().filter(p -> DateUtil.compare(p.getPlanDate(), new Date()) < 1)
                                    .collect(Collectors.toList());
                            if (filterList == null || filterList.isEmpty()) {
                                throw new BusinessException(CodeUtil.FAIL, "手动生成的收放款计划无入账日期的回款，请先前往sop手动修改计划");
                            } else {
                                //按照逾期利息->其它费用->管理费->利息->本金的顺序回款
                                List<PaymentCollectionPlanFactoring> overdueList = filterList.stream().filter(f -> f.getAmountType().getCode().equals("overdue_interest")).collect(Collectors.toList());
                                List<PaymentCollectionPlanFactoring> otherFeeList = filterList.stream().filter(f -> f.getAmountType().getCode().equals("other_fee")).collect(Collectors.toList());
                                List<PaymentCollectionPlanFactoring> managementFeeList = filterList.stream().filter(f -> f.getAmountType().getCode().equals("management_fee") && f.getAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                                List<PaymentCollectionPlanFactoring> interestList = filterList.stream().filter(f -> f.getAmountType().getCode().equals("interest") && f.getAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                                List<PaymentCollectionPlanFactoring> principalList = filterList.stream().filter(f -> f.getAmountType().getCode().equals("principal") && f.getAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());

                                if (overdueList != null && overdueList.size() > 0) {
                                    for (PaymentCollectionPlanFactoring factoring : overdueList) {
                                        BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                        financingOverdueInterest = financingOverdueInterest.add(currentAssignAmount);
                                        assignAmount = assignAmount.subtract(currentAssignAmount);
                                        if (currentAssignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                            ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, currentAssignAmount, factoring, goodsAssignVo, 0));
                                        }
                                        if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                            //说明钱已经分完了，结束分配
                                            break;
                                        }
                                    }
                                }

                                if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    if (otherFeeList != null && otherFeeList.size() > 0) {
                                        for (PaymentCollectionPlanFactoring factoring : otherFeeList) {
                                            BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                            financeInterest = financeInterest.add(currentAssignAmount);
                                            assignAmount = assignAmount.subtract(currentAssignAmount);
                                            if (currentAssignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, currentAssignAmount, factoring, goodsAssignVo, 0));
                                            }
                                            if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                                //说明钱已经分完了，结束分配
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    if (managementFeeList != null && managementFeeList.size() > 0) {
                                        for (PaymentCollectionPlanFactoring factoring : managementFeeList) {
                                            BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                            financingManagementFee = financingManagementFee.add(currentAssignAmount);
                                            assignAmount = assignAmount.subtract(currentAssignAmount);
                                            if (currentAssignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                                manuallyGeneratedAssign(factoring, currentAssignAmount, goodsAssignVo,
                                                        ledgerPlanFactoringAssignList, ledgerDate, 0, IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode());
                                            }
                                            if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                                //说明钱已经分完了，结束分配
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    //如果钱还有剩余继续分配利息费
                                    if (interestList != null && interestList.size() > 0) {
                                        for (PaymentCollectionPlanFactoring factoring : interestList) {
                                            BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                            financeInterest = financeInterest.add(currentAssignAmount);
                                            assignAmount = assignAmount.subtract(currentAssignAmount);
                                            if (currentAssignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                                manuallyGeneratedAssign(factoring, currentAssignAmount, goodsAssignVo,
                                                        ledgerPlanFactoringAssignList, ledgerDate, 0, IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode());
                                            }
                                            if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                                //说明钱已经分完了，结束分配
                                                break;
                                            }
                                        }
                                    }
                                }

                                if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    //如果钱还有剩余继续分配本金
                                    if (principalList != null && principalList.size() > 0) {
                                        for (PaymentCollectionPlanFactoring factoring : principalList) {
                                            BigDecimal currentAssignAmount = assignAmount(assignAmount, factoring);
                                            financePrincipal = financePrincipal.add(currentAssignAmount);
                                            assignAmount = assignAmount.subtract(currentAssignAmount);
                                            if (currentAssignAmount.compareTo(BigDecimal.ZERO) > 0) {
                                                manuallyGeneratedAssign(factoring, currentAssignAmount, goodsAssignVo,
                                                        ledgerPlanFactoringAssignList, ledgerDate, 1, IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode());
                                            }
                                            if (assignAmount.compareTo(BigDecimal.ZERO) == 0) {
                                                //说明钱已经分完了，结束分配
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    goodsAssignVo.setFinancingPrincipal(financePrincipal);
                    goodsAssignVo.setFinancingInterest(financeInterest);
                    goodsAssignVo.setFinancingManagementFee(financingManagementFee);
                    goodsAssignVo.setFinancingOverdueInterest(financingOverdueInterest);
                    goodsAssignVo.setRefundInterest(refundInterest.compareTo(BigDecimal.ZERO) > 0 ? refundInterest : BigDecimal.ZERO);
                    goodsAssignVo.setRefundManagementFee(refundManagement.compareTo(BigDecimal.ZERO) > 0 ? refundManagement : BigDecimal.ZERO);
                    goodsAssignVo.setLedgerPlanFactoringAssignList(ledgerPlanFactoringAssignList);

                    BigDecimal platformProfit = BigDecimal.ZERO;
                    BigDecimal discountAmount = BigDecimal.ZERO;
                    BigDecimal guarantee = BigDecimal.ZERO;

                    // 计提金额=贸理通底层对应的应收账款净额*5%   最大计提金额
                    BigDecimal accrualAmount = BigDecimal.ZERO;
                    if (goodsAssignVo.getSopAccountsReceivableId() != null) {
                        CFinancingBasicInfo financingBasicInfo = financingBasicInfoService.getOne(new QueryWrapper<CFinancingBasicInfo>()
                                .eq("sop_accounts_receivable_id", goodsAssignVo.getSopAccountsReceivableId()));
                        if (financingBasicInfo != null) {
                            List<CFinancingAccountsReceivableInfo> accountsReceivableList = financingAccountsReceivableInfoService.list(new QueryWrapper<CFinancingAccountsReceivableInfo>()
                                    .eq("c_financing_basic_info_id", financingBasicInfo.getId()));
                            if (CollectionUtil.isNotEmpty(accountsReceivableList)) {
                                //应收账款净额之和
                                BigDecimal netAmountTotal = accountsReceivableList.stream().filter(a -> a.getNetAccountsReceivableAmount() != null)
                                        .map(CFinancingAccountsReceivableInfo::getNetAccountsReceivableAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                                accrualAmount = netAmountTotal.multiply(new BigDecimal(5)).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                            }
                        }
                    }
                    //当前计提金额
                    BigDecimal currentAccrualAmount = BigDecimal.ZERO;
                    BigDecimal existingProfit = BigDecimal.ZERO;

                    List<LedgerFundGoodsAssign> oldLedgerFundGoodsAssignLists = ledgerFundGoodsAssignService.list(
                            new QueryWrapper<LedgerFundGoodsAssign>().eq("sop_accounts_receivable_id", goodsAssignVo.getSopAccountsReceivableId()));
                    //分配计提金额
                    if (goodsAssignVo.getAccrual() != null && goodsAssignVo.getAccrual()) {
                        GoodsOccupyVo occupyVo = goodsOccupyVos.stream().filter(goodsOccupyVo -> goodsOccupyVo.getBusinessNumber().equals(goodsAssignVo.getBusinessNumber()))
                                .collect(Collectors.toList()).get(0);
                        //业务剩余可用计提金额
                        BigDecimal surplusAccrualAmount = occupyVo.getSurplusAccrualAmount();
                        //该业务剩余可用计提金额  大于等于 底层对应的最大计提金额
                        if (surplusAccrualAmount.compareTo(accrualAmount) >= 0) {
                            currentAccrualAmount = accrualAmount;
                            //该业务剩余可用计提金额  小于 底层对应的最大计提金额
                        } else if (surplusAccrualAmount.compareTo(accrualAmount) < 0) {
                            currentAccrualAmount = surplusAccrualAmount;
                        }
                        //该笔业务已占用的计提金额
                        BigDecimal businessOccupied = occupyVo.getOccupyAmount();
                        //履约保证金上限
                        BigDecimal depositLimit = surplusAccrualAmount.add(businessOccupied);
                        //该笔底层已占计提金额
                        BigDecimal occupied = BigDecimal.ZERO;
                        if (CollectionUtil.isNotEmpty(oldLedgerFundGoodsAssignLists)) {
                            for (LedgerFundGoodsAssign ledgerFundGoodsAssign : oldLedgerFundGoodsAssignLists) {
                                if (ledgerFundGoodsAssign.getSubmit() != null && ledgerFundGoodsAssign.getSubmit()) {
                                    occupied = occupied.add(ledgerFundGoodsAssign.getAccrualAmount());
                                }
                            }

                        }
                        //一笔底层多次放款的活  按每次放款金额的比例拆分计提金额   该次底层防款最大计提上限
                        BigDecimal splitAccrualAmount = accrualAmount.multiply(goodsAssignVo.getLoanAmount());
                        //该笔底层已存在的货款分配
                        if (CollectionUtil.isNotEmpty(oldLedgerFundGoodsAssignLists)) {
                            for (LedgerFundGoodsAssign oldLedgerFundGoodsAssign : oldLedgerFundGoodsAssignLists) {
                                //同一笔底层的同一笔放款计提上限是否已经达到
                                if (oldLedgerFundGoodsAssign.getSubmit() != null && oldLedgerFundGoodsAssign.getSubmit()) {
                                    splitAccrualAmount = splitAccrualAmount.subtract(oldLedgerFundGoodsAssign.getAccrualAmount());
                                }
                            }
                        }
                        // 该次底层放款最大计提上限
                        if (splitAccrualAmount.compareTo(BigDecimal.ZERO) > -1) {
                            if (splitAccrualAmount.compareTo(currentAccrualAmount) == -1) {
                                currentAccrualAmount = splitAccrualAmount;
                            }
                        }

                        //和剩余分配金额比较
                        if (assignAmount.compareTo(currentAccrualAmount) == -1) {
                            currentAccrualAmount = assignAmount;
                        }

                        //判断预占用计提金额加上已占用计提金额是否大于底层计提上限  如果大于的话 减少该笔的计提金额到合理大小
                        occupied = occupied.add(currentAccrualAmount);
                        if (occupied.compareTo(accrualAmount) == 1) {
                            currentAccrualAmount = accrualAmount.subtract(occupied.subtract(currentAccrualAmount));
                        }
                        if (currentAccrualAmount.compareTo(surplusAccrualAmount) == 1) {
                            currentAccrualAmount = surplusAccrualAmount;
                        }

                        //判断业务预占用计提金额加上已占用计提金额是否大于业务计提上限  如果大于的话 减少该笔的计提金额到合理大小
                        businessOccupied = businessOccupied.add(currentAccrualAmount);
                        if (businessOccupied.compareTo(depositLimit) == 1) {
                            currentAccrualAmount = depositLimit.subtract(businessOccupied.subtract(currentAccrualAmount));
                        }

                        //设置合理计提金额
                        goodsAssignVo.setAccrualAmount(currentAccrualAmount);
                        assignAmount = assignAmount.subtract(currentAccrualAmount);
                    }

                    if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                        //分配金额还有剩余，计算平台利润和实退金额
                        //平台利润= 销售总价-采购总价
                        BigDecimal salesTotalPrice = goodsAssignVo.getSalesTotalPrice() == null ? BigDecimal.ZERO
                                : goodsAssignVo.getSalesTotalPrice();
                        BigDecimal purchaseTotalPrice = goodsAssignVo.getPurchaseTotalPrice() == null ? BigDecimal.ZERO
                                : goodsAssignVo.getPurchaseTotalPrice();
                        platformProfit = salesTotalPrice.subtract(purchaseTotalPrice);

                        if (CollectionUtil.isNotEmpty(oldLedgerFundGoodsAssignLists)) {
                            for (LedgerFundGoodsAssign oldLedgerFundGoodsAssign : oldLedgerFundGoodsAssignLists) {
                                //同一笔底层的同一笔放款计提上限是否已经达到
                                if (oldLedgerFundGoodsAssign.getSubmit() != null && oldLedgerFundGoodsAssign.getSubmit()) {
                                    existingProfit = existingProfit.add(oldLedgerFundGoodsAssign.getPlatformProfit());
                                }

                            }
                        }
                        //最大平台利润和已有平台利润比较
                        if (existingProfit.compareTo(platformProfit) == -1) {
                            platformProfit = platformProfit.subtract(existingProfit);
                        } else {
                            platformProfit = BigDecimal.ZERO;
                        }

                        if (assignAmount.compareTo(platformProfit) == -1) {
                            platformProfit = assignAmount;
                            assignAmount = BigDecimal.ZERO;
                        } else {
                            assignAmount = assignAmount.subtract(platformProfit);
                        }
                        //2023.3.18新增分配质保金
                        if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                            //获取质保金上限
                            GoodsOccupyVo occupyVo = goodsOccupyVos.stream().filter(goodsOccupyVo -> goodsOccupyVo.getBusinessNumber().equals(goodsAssignVo.getBusinessNumber()))
                                    .collect(Collectors.toList()).get(0);
                            BigDecimal retentionLimit = occupyVo.getRetentionLimit();
                            BigDecimal surplusRetentionAmount = occupyVo.getSurplusRetentionAmount();
                            BigDecimal retentionPercent = occupyVo.getRetentionPercent();
                            //质保金=销售总价*质保金比例
                            BigDecimal retentionAmount = goodsAssignVo.getSalesTotalPrice().multiply(retentionPercent)
                                    .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
                            guarantee = assignAmount.compareTo(retentionAmount) <= 0 ? assignAmount : retentionAmount;
                            if (retentionLimit != null && surplusRetentionAmount != null) {
                                if (guarantee.compareTo(surplusRetentionAmount) >= 0) {
                                    guarantee = surplusRetentionAmount;
                                }
                            }
                            assignAmount = assignAmount.subtract(guarantee);
                        }
                        if (assignAmount.compareTo(BigDecimal.ZERO) > 0) {
                            //实退金额 = 核心企业回款-保理融资本息-平台利润
                            discountAmount = assignAmount;
                        }
                    }
                    goodsAssignVo.setPlatformProfit(platformProfit);
                    goodsAssignVo.setGuarantee(guarantee);
                    goodsAssignVo.setDiscountAmount(discountAmount);
                }
            }
        }
        return ledgerAccountInfoVo;
    }

    /**
     * 收放款计划校验
     *
     * @param principalFactoringList
     */
    private void validatePlanFactoring(List<PaymentCollectionPlanFactoring> principalFactoringList) {
        //判断已经分配的本金计划有没有分配完成
        if (CollectionUtil.isNotEmpty(principalFactoringList)) {
            principalFactoringList.stream().forEach(p -> {
                List<PayCollPlanFactoringAmountAllocation> amountAllocationList = p.getAmountAllocationList();
                if (CollectionUtil.isNotEmpty(amountAllocationList)) {
                    BigDecimal collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                            .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    if (collAmountSum.compareTo(p.getAmount()) != 0) {
                        throw new BusinessException(CodeUtil.FAIL, "尚有本金计划未分配完成、请先去sop修改收放款计划或者分配完再来分账");
                    }
                }
            });
        }
    }

    /**
     * 获取销售合同审核信息
     *
     * @param businessNumber
     * @return
     */
    private SalesContractApproval getSalesContractApproval(String businessNumber) {
        CSalesContractBasicInfo salesContractBasicInfo = salesContractService.findByBusinessNumber(businessNumber);
        SalesContractApproval salesContractApproval = salesContractApprovalService.getOne(new QueryWrapper<SalesContractApproval>()
                .eq("c_sales_contract_basic_info_id", salesContractBasicInfo.getId())
                .eq("approval_conclusion", ConstantConversionUtil.APPROVAL_RESULT_PASS));
        return salesContractApproval;
    }

    /**
     * 手动生成分配
     *
     * @param factoring
     * @param currentAssignAmount
     * @param goodsAssignVo
     * @param ledgerPlanFactoringAssignList
     */
    private void manuallyGeneratedAssign(PaymentCollectionPlanFactoring factoring, BigDecimal currentAssignAmount,
                                         LedgerFundGoodsAssign goodsAssignVo, List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList,
                                         Date ledgerDate, Integer isPrincipal, String amountType) {
        //判断有没有分配过
        List<PayCollPlanFactoringAmountAllocation> amountAllocationList = factoring.getAmountAllocationList();
        if (CollectionUtil.isEmpty(amountAllocationList)) {
            //直接修改对应计划(需分配)
            ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, currentAssignAmount, factoring,
                    goodsAssignVo, isPrincipal));
        } else {
            //做过分配需要将计划进行拆分
            BigDecimal collAmountSum = BigDecimal.ZERO;
            if (amountAllocationList != null && amountAllocationList.size() > 0) {
                collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                        .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            }
            //将已分配的计划进行变更（不分配）
            BigDecimal planAmount = factoring.getAmount();
            factoring.setAmount(collAmountSum);
            ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, BigDecimal.ZERO, factoring,
                    goodsAssignVo, isPrincipal));
            //未分配金额
            BigDecimal unCollAmount = planAmount.subtract(collAmountSum);
            if (currentAssignAmount.compareTo(unCollAmount) >= 0) {
                //如果本次分配大于等于未分配金额
                //生成一笔分配计划
                ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, unCollAmount, unCollAmount,
                        amountType, goodsAssignVo, isPrincipal));
            } else if (currentAssignAmount.compareTo(unCollAmount) <= 0) {
                //如果本次分配小于未分配金额
                //生成一笔分配计划
                ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, currentAssignAmount, currentAssignAmount,
                        amountType, goodsAssignVo, isPrincipal));
                //生成一笔未分配计划
                BigDecimal surplus = unCollAmount.subtract(currentAssignAmount);
                ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(ledgerDate, surplus, BigDecimal.ZERO,
                        amountType, goodsAssignVo, isPrincipal));
            }
        }
    }

    /**
     * 利息或管理费分配
     *
     * @param diffAmount
     * @param planFactoringList
     * @param goodsAssign
     */
    private void interestOrManagementAssign(BigDecimal diffAmount, List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList,
                                            List<PaymentCollectionPlanFactoring> planFactoringList, LedgerFundGoodsAssign goodsAssign,
                                            PaymentCollectionPlanFactoring lastPrincipalFactoring, Dictionary dict) {
        if (CollectionUtil.isNotEmpty(planFactoringList)) {
            //获取部分分配的计划
            List<PaymentCollectionPlanFactoring> partAllocationList = planFactoringList.stream().filter(p -> {
                List<PayCollPlanFactoringAmountAllocation> amountAllocationList = p.getAmountAllocationList();
                if (CollectionUtil.isNotEmpty(amountAllocationList)) {
                    BigDecimal collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                            .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    return collAmountSum.compareTo(p.getAmount()) < 0;
                }
                return false;
            }).sorted(Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate)).collect(Collectors.toList());
            //获取未分配的计划
            List<PaymentCollectionPlanFactoring> unAllocationList = planFactoringList.stream()
                    .filter(p -> CollectionUtil.isEmpty(p.getAmountAllocationList()) && p.getAmount().compareTo(BigDecimal.ZERO) > 0)
                    .sorted(Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate)).collect(Collectors.toList());

            if (CollectionUtil.isEmpty(partAllocationList)) {
                //如果没有部分分配的计划
                if (CollectionUtil.isNotEmpty(unAllocationList)) {
                    //删除掉未分配的计划
                    unAllocationList.stream().forEach(p -> ledgerPlanFactoringAssignList.add(addPlanFactoringDeleteAssign(p, goodsAssign, 0)));
                }
                //生成一条管理费或利息计划（不分配）
                PaymentCollectionPlanFactoring newPlanFactoring = new PaymentCollectionPlanFactoring();
                if (lastPrincipalFactoring != null) {
                    newPlanFactoring.setPlanDate(lastPrincipalFactoring.getPlanDate());
                }
                newPlanFactoring.setAmount(diffAmount);
                newPlanFactoring.setAmountType(dict);
                newPlanFactoring.setPaymentCollectionType(ConstantConversionUtil.PAY_COLL_COLLECTION);
                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(newPlanFactoring.getPlanDate(), BigDecimal.ZERO,
                        newPlanFactoring, goodsAssign, 0));
            } else {
                //如果有部分分配的计划
                BigDecimal planAmountTotal = partAllocationList.stream().filter(p -> p.getAmount() != null)
                        .map(PaymentCollectionPlanFactoring::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);

                BigDecimal actualAmountTotal = BigDecimal.ZERO;
                for (PaymentCollectionPlanFactoring planFactoring : partAllocationList) {
                    List<PayCollPlanFactoringAmountAllocation> amountAllocationList = planFactoring.getAmountAllocationList();
                    if (amountAllocationList != null && amountAllocationList.size() > 0) {
                        BigDecimal collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                                .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        actualAmountTotal = actualAmountTotal.add(collAmountSum);
                    }
                }
                //应收与实收的差值
                BigDecimal planAmountDiff = planAmountTotal.subtract(actualAmountTotal);
                if (diffAmount.compareTo(planAmountDiff) > 0) {
                    //如果大于应收实收差值,判断有没有 未分配的计划
                    if (CollectionUtil.isNotEmpty(unAllocationList)) {
                        BigDecimal diff = diffAmount.subtract(planAmountDiff);
                        for (PaymentCollectionPlanFactoring factoring : unAllocationList) {
                            if (diff.compareTo(BigDecimal.ZERO) == 0) {
                                //删除后续的计划
                                ledgerPlanFactoringAssignList.add(addPlanFactoringDeleteAssign(factoring, goodsAssign, 0));
                            } else {
                                if (diff.compareTo(factoring.getAmount()) > 0) {
                                    diff = diff.subtract(factoring.getAmount());
                                } else if (diff.compareTo(factoring.getAmount()) < 0) {
                                    //修改本笔计划
                                    factoring.setAmount(diff);
                                    ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(factoring.getPlanDate(), BigDecimal.ZERO,
                                            factoring, goodsAssign, 0));
                                    diff = BigDecimal.ZERO;
                                }
                            }
                        }
                    } else {
                        //如果大于应收实收差值，生成一条管理费或利息计划（不分配）
                        if (lastPrincipalFactoring != null) {
                            ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPrincipalFactoring.getPlanDate(),
                                    diffAmount.subtract(planAmountDiff), BigDecimal.ZERO, dict.getCode(), goodsAssign, 0));
                        }
                    }
                } else if (diffAmount.compareTo(planAmountDiff) < 0) {
                    //如果小于应收实收差值
                    for (PaymentCollectionPlanFactoring factoring : partAllocationList) {
                        BigDecimal planAmount = factoring.getAmount();

                        List<PayCollPlanFactoringAmountAllocation> amountAllocationList = factoring.getAmountAllocationList();
                        BigDecimal actualAmount = BigDecimal.ZERO;
                        if (CollectionUtil.isNotEmpty(amountAllocationList)) {
                            actualAmount = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                                    .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                        }
                        BigDecimal planSurplus = planAmount.subtract(actualAmount);

                        if (diffAmount.compareTo(BigDecimal.ZERO) == 0) {
                            //修改计划应收=实收
                            factoring.setAmount(actualAmount);
                            ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(factoring.getPlanDate(), BigDecimal.ZERO,
                                    factoring, goodsAssign, 0));
                        } else {
                            if (diffAmount.compareTo(planSurplus) > 0) {
                                diffAmount = diffAmount.subtract(planSurplus);
                            } else if (diffAmount.compareTo(planSurplus) < 0) {
                                //修改计划
                                factoring.setAmount(diffAmount.add(actualAmount));
                                ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(factoring.getPlanDate(), BigDecimal.ZERO,
                                        factoring, goodsAssign, 0));
                                diffAmount = BigDecimal.ZERO;
                            }
                        }
                    }
                    if (CollectionUtil.isNotEmpty(unAllocationList)) {
                        //如果还有未分配的计划，需要删掉
                        for (PaymentCollectionPlanFactoring factoring : unAllocationList) {
                            ledgerPlanFactoringAssignList.add(addPlanFactoringDeleteAssign(factoring, goodsAssign, 0));
                        }
                    }
                }
            }
        }
    }

    /**
     * 修改部分分配的计划，将计划金额改为实收金额
     *
     * @param planFactoringList
     * @param ledgerPlanFactoringAssignList
     */
    private void updatePartAssignList(List<PaymentCollectionPlanFactoring> planFactoringList,
                                      List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList, LedgerFundGoodsAssign goodsAssign) {
        if (CollectionUtil.isNotEmpty(planFactoringList)) {
            for (PaymentCollectionPlanFactoring planFactoring : planFactoringList) {
                List<PayCollPlanFactoringAmountAllocation> amountAllocationList = planFactoring.getAmountAllocationList();
                if (CollectionUtil.isNotEmpty(amountAllocationList)) {
                    BigDecimal collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                            .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    if (collAmountSum.compareTo(planFactoring.getAmount()) < 0) {
                        //只改计划，不再分配
                        planFactoring.setAmount(collAmountSum);
                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(planFactoring.getPlanDate(), BigDecimal.ZERO,
                                planFactoring, goodsAssign, 0));
                    }
                }
            }
        }
    }

    /**
     * 删除未分配的计划
     *
     * @param planFactoringList
     */
    private void deleteUnAssignList(List<PaymentCollectionPlanFactoring> planFactoringList,
                                    List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList, LedgerFundGoodsAssign goodsAssign) {
        if (CollectionUtil.isNotEmpty(planFactoringList)) {
            //退款的数据虽然没有实际收付但也不能删除
            planFactoringList.stream().filter(p -> CollectionUtil.isEmpty(p.getAmountAllocationList()) && p.getAmount().compareTo(BigDecimal.ZERO) > 0)
                    .forEach(p -> ledgerPlanFactoringAssignList.add(addPlanFactoringDeleteAssign(p, goodsAssign, 0)));
        }
    }

    /**
     * 判断计划是否做过分配
     *
     * @param principalFactoringList
     * @return true:做过 false:未做过
     */
    private Boolean hasPrincipalAssign(List<PaymentCollectionPlanFactoring> principalFactoringList) {
        if (CollectionUtil.isEmpty(principalFactoringList)) {
            return false;
        }
        for (PaymentCollectionPlanFactoring planFactoring : principalFactoringList) {
            List<PayCollPlanFactoringAmountAllocation> amountAllocationList = planFactoring.getAmountAllocationList();
            if (amountAllocationList != null && amountAllocationList.size() > 0) {
                for (PayCollPlanFactoringAmountAllocation amountAllocation : amountAllocationList) {
                    if (amountAllocation.getActualAmount() != null && amountAllocation.getActualAmount().compareTo(BigDecimal.ZERO) > 0) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 本金计划分配
     *
     * @param assignAmount                  分配金额
     * @param principalFactoringList        本金收放款计划
     * @param ledgerDate
     * @param ledgerPlanFactoringAssignList
     * @param goodsAssignVo
     */
    private List<PaymentCollectionPlanFactoring> principalAssign(BigDecimal assignAmount, List<PaymentCollectionPlanFactoring> principalFactoringList,
                                                                 Date ledgerDate, List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList,
                                                                 LedgerFundGoodsAssign goodsAssignVo) {
        BigDecimal principalAssignAmount = assignAmount;
        if (CollectionUtil.isNotEmpty(principalFactoringList)) {
            //按计划日期升序排列
            Collections.sort(principalFactoringList, Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate));

            List<PaymentCollectionPlanFactoring> newPrincipalFactoringList = new ArrayList<>();
            for (PaymentCollectionPlanFactoring planFactoring : principalFactoringList) {
                if (!PaymentCollectionPlanStatusDict.ChildEnum.COMPLETED.getCode().equals(planFactoring.getStatus().getCode()) &&
                        !PaymentCollectionPlanStatusDict.ChildEnum.OVERDUE_COMPLETED.getCode().equals(planFactoring.getStatus().getCode())
                        && principalAssignAmount.compareTo(BigDecimal.ZERO) > 0) {
                    if (principalAssignAmount.compareTo(planFactoring.getAmount()) >= 0) {
                        if (ledgerDate.before(planFactoring.getPlanDate())) {
                            //分账日期早于计划日期
                            planFactoring.setPlanDate(ledgerDate);
                        }
                        //修改一笔本金收款记录
                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, planFactoring.getAmount(),
                                planFactoring, goodsAssignVo, 1));

                        principalAssignAmount = principalAssignAmount.subtract(planFactoring.getAmount());
                    } else {
                        Date planDate = planFactoring.getPlanDate();
                        BigDecimal amount = planFactoring.getAmount();
                        if (ledgerDate.before(planFactoring.getPlanDate())) {
                            //分账日期早于计划日期
                            planFactoring.setPlanDate(ledgerDate);
                        }
                        planFactoring.setAmount(principalAssignAmount);
                        planFactoring.setActualCashFlow(principalAssignAmount);

                        //修改一笔本金收款记录
                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, principalAssignAmount,
                                planFactoring, goodsAssignVo, 1));

                        //增加一笔剩余本金计划
                        BigDecimal surplusAmount = amount.subtract(principalAssignAmount);
                        PaymentCollectionPlanFactoring newPlanFactoring = new PaymentCollectionPlanFactoring();
                        newPlanFactoring.setPlanDate(planDate);
                        newPlanFactoring.setAmount(surplusAmount);
                        newPlanFactoring.setAmountType(planFactoring.getAmountType());
                        newPlanFactoring.setPaymentCollectionType(ConstantConversionUtil.PAY_COLL_COLLECTION);
                        newPrincipalFactoringList.add(newPlanFactoring);

                        //增加一笔本次本金收款记录
                        ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(planDate, surplusAmount, BigDecimal.ZERO,
                                IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode(), goodsAssignVo, 1));

                        principalAssignAmount = BigDecimal.ZERO;
                    }
                }
                newPrincipalFactoringList.add(planFactoring);
            }

            return newPrincipalFactoringList;
        }
        return null;
    }

    /**
     * 本金计划分配-2.0版
     *
     * @param assignAmount                  分配金额
     * @param principalFactoringList        本金收放款计划
     * @param ledgerDate
     * @param ledgerPlanFactoringAssignList
     * @param goodsAssignVo
     */
    private void principalAssignV2(BigDecimal assignAmount, List<PaymentCollectionPlanFactoring> principalFactoringList,
                                   Date ledgerDate, List<LedgerPlanFactoringAssign> ledgerPlanFactoringAssignList,
                                   LedgerFundGoodsAssign goodsAssignVo, PrePaymentCalculateVo paymentCalculateVo, BigDecimal financePrincipal) {
        BigDecimal principalAssignAmount = assignAmount;
        //待回款本金
        BigDecimal returnedAmount = goodsAssignVo.getReturnedAmount();
        if (CollectionUtil.isNotEmpty(principalFactoringList)) {
            //按计划日期升序排列
            Collections.sort(principalFactoringList, Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate));
            Boolean hasPrincipalAssign = hasPrincipalAssign(principalFactoringList);

            Boolean flag = false;
            for (PaymentCollectionPlanFactoring planFactoring : principalFactoringList) {
                if (!PaymentCollectionPlanStatusDict.ChildEnum.COMPLETED.getCode().equals(planFactoring.getStatus().getCode()) &&
                        !PaymentCollectionPlanStatusDict.ChildEnum.OVERDUE_COMPLETED.getCode().equals(planFactoring.getStatus().getCode())) {
                    if (flag) {
                        //金额已分完了
                        addPlanFactoringDeleteAssign(planFactoring, goodsAssignVo, 1);
                        continue;
                    }
                    if (principalAssignAmount.compareTo(planFactoring.getAmount()) >= 0) {
                        //本金分配金额>计划金额、说明本金够分
                        //修改一笔本金收款记录
                        if (ledgerDate.before(planFactoring.getPlanDate())) {
                            //分账日期早于计划日期
                            planFactoring.setPlanDate(ledgerDate);
                        }
                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, planFactoring.getAmount(),
                                planFactoring, goodsAssignVo, 1));
                        principalAssignAmount = principalAssignAmount.subtract(planFactoring.getAmount());
                        returnedAmount = returnedAmount.subtract(planFactoring.getAmount());
                        financePrincipal = financePrincipal.add(planFactoring.getAmount());
                    } else {
                        //说明本金不够分了
                        if (ledgerDate.before(planFactoring.getPlanDate())) {
                            //分账日期早于计划日期
                            planFactoring.setPlanDate(ledgerDate);
                        }
                        planFactoring.setAmount(principalAssignAmount);
                        planFactoring.setActualCashFlow(principalAssignAmount);

                        //修改一笔本金收款记录
                        ledgerPlanFactoringAssignList.add(addPlanFactoringUpdateAssign(ledgerDate, principalAssignAmount,
                                planFactoring, goodsAssignVo, 1));
                        financePrincipal = financePrincipal.add(principalAssignAmount);
                        Date lastPlanDate = goodsAssignVo.getLastPlanDate();
                        //增加一笔剩余本金收款记录
                        ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPlanDate, returnedAmount.subtract(principalAssignAmount), BigDecimal.ZERO,
                                IncomeExpenditureTypeDict.ChildEnum.PRINCIPAL.getCode(), goodsAssignVo, 1));
                        //增加一笔剩余管理费计划
                        //计算剩余应收管理费
                        BigDecimal calculateManagementFee = calculateAssignInterest(returnedAmount, ledgerDate, lastPlanDate,
                                !hasPrincipalAssign, paymentCalculateVo, IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode());
                        ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPlanDate, calculateManagementFee, BigDecimal.ZERO,
                                IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode(), goodsAssignVo, 0));
                        //增加一笔剩余利息计划
                        //计算剩余应收利息
                        BigDecimal calculateInterest = calculateAssignInterest(returnedAmount, ledgerDate, lastPlanDate,
                                !hasPrincipalAssign, paymentCalculateVo, IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode());
                        ledgerPlanFactoringAssignList.add(addPlanFactoringInsertAssign(lastPlanDate, calculateInterest, BigDecimal.ZERO,
                                IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode(), goodsAssignVo, 0));
                        principalAssignAmount = BigDecimal.ZERO;
                    }
                }
            }
        }
    }


    /**
     * 获取分账日期前的新计划
     *
     * @param principalFactoringList 本金收放款计划
     * @param ledgerDate             分账日期
     */
    private List<PaymentCollectionPlanFactoring> getPrincipalFactoringByLedgerDate(List<PaymentCollectionPlanFactoring> principalFactoringList, Date ledgerDate,
                                                                                   BigDecimal returnedAmount) {
        if (CollectionUtil.isNotEmpty(principalFactoringList)) {
            List<PaymentCollectionPlanFactoring> newPrincipalFactoringList = new ArrayList<>();
            List<PaymentCollectionPlanFactoring> filterList = principalFactoringList.stream().filter(factoring -> factoring.getPlanDate() != null && factoring.getPlanDate().compareTo(ledgerDate) < 0)
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(filterList)) {
                for (PaymentCollectionPlanFactoring planFactoring : filterList) {
                    newPrincipalFactoringList.add(planFactoring);
                }
            }
            if (returnedAmount.compareTo(BigDecimal.ZERO) > 0) {
                PaymentCollectionPlanFactoring newPlanFactoring = new PaymentCollectionPlanFactoring();
                newPlanFactoring.setAmount(returnedAmount);
                newPlanFactoring.setPlanDate(ledgerDate);
                newPrincipalFactoringList.add(newPlanFactoring);
            }
            //按计划日期升序排列
            Collections.sort(newPrincipalFactoringList, Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate));
            return newPrincipalFactoringList;
        }
        return null;
    }


    /**
     * 计算已分配的利息或管理费之和
     *
     * @param planFactoringList
     * @param dict
     * @return
     */
    private BigDecimal getInterestTotal(List<PaymentCollectionPlanFactoring> planFactoringList, Dictionary dict) {
        if (planFactoringList == null || planFactoringList.isEmpty()) {
            return BigDecimal.ZERO;
        }
        //获取所有类型为利息或管理费的收款数据
        List<PaymentCollectionPlanFactoring> filterList = planFactoringList.stream().filter(p -> p.getAmountType().getId().equals(dict.getId())
                && p.getPaymentCollectionType().equals(ConstantConversionUtil.PAY_COLL_COLLECTION)
                && (PaymentCollectionPlanStatusDict.ChildEnum.COMPLETED.getCode().equals(p.getStatus().getCode())
                || PaymentCollectionPlanStatusDict.ChildEnum.OVERDUE_COMPLETED.getCode().equals(p.getStatus().getCode()))).collect(Collectors.toList());
        //获取所有二次延期时已收款的利息或管理费
        List<PaymentCollectionPlanFactoring> graceList = filterList.stream().filter(p -> p.getGraceType() != null && p.getGraceType().compareTo(1) > 0)
                .collect(Collectors.toList());

        BigDecimal interestTotal = BigDecimal.ZERO;
        if (graceList != null && graceList.size() > 0) {
            for (PaymentCollectionPlanFactoring planFactoring : graceList) {
                List<PayCollPlanFactoringAmountAllocation> allocationList = planFactoring.getAmountAllocationList();
                if (allocationList != null && allocationList.size() > 0) {
                    for (PayCollPlanFactoringAmountAllocation amountAllocation : allocationList) {
                        BigDecimal actualAmount = amountAllocation.getActualAmount() == null ? BigDecimal.ZERO : amountAllocation.getActualAmount();
                        interestTotal = interestTotal.add(actualAmount);
                    }
                }
            }
        }
        //获取所有已退回给供应商的的利息或管理费
        List<PaymentCollectionPlanFactoring> returnedList = filterList.stream().filter(p -> p.getAmount() != null && p.getAmount().compareTo(BigDecimal.ZERO) < 0)
                .collect(Collectors.toList());
        BigDecimal returnedTotal = BigDecimal.ZERO;
        if (returnedList != null && returnedList.size() > 0) {
            for (PaymentCollectionPlanFactoring planFactoring : returnedList) {
                BigDecimal amount = planFactoring.getAmount() == null ? BigDecimal.ZERO : planFactoring.getAmount();
                returnedTotal = returnedTotal.add(amount);
            }
        }
        return interestTotal.add(returnedTotal);
    }

    /**
     * 获取计划中实际已收的利息或管理费总计
     *
     * @param planFactoringList
     * @param dict
     * @return
     */
    private BigDecimal getActualAmountTotal(List<PaymentCollectionPlanFactoring> planFactoringList, Dictionary dict) {

        if (planFactoringList == null || planFactoringList.isEmpty()) {
            return BigDecimal.ZERO;
        }

        List<PaymentCollectionPlanFactoring> filterList = planFactoringList.stream().filter(p -> p.getAmountType().getId().equals(dict.getId())
                && p.getPaymentCollectionType().equals(ConstantConversionUtil.PAY_COLL_COLLECTION)).collect(Collectors.toList());
        if (filterList == null || filterList.isEmpty()) {
            return BigDecimal.ZERO;
        } else {
            //计算已经收的利息或管理费
            BigDecimal planAmountTotal = BigDecimal.ZERO;
            for (PaymentCollectionPlanFactoring planFactoring : filterList) {
                BigDecimal collAmountSum = BigDecimal.ZERO;
                List<PayCollPlanFactoringAmountAllocation> amountAllocationList = planFactoring.getAmountAllocationList();
                if (amountAllocationList != null && amountAllocationList.size() > 0) {
                    collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                            .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                } else {
                    //退款的数据没有分配记录、所有应该从计划金额里取值
                    if (planFactoring.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                        collAmountSum = planFactoring.getAmount();
                    }
                }
                planAmountTotal = planAmountTotal.add(collAmountSum);
            }
            return planAmountTotal;
        }
    }

    /**
     * 获取对应金额类型的收款计划
     *
     * @param planFactoringList
     * @return
     */
    private List<PaymentCollectionPlanFactoring> getFactoringByAmountType(List<PaymentCollectionPlanFactoring> planFactoringList,
                                                                          Dictionary amountTypeDict) {

        if (planFactoringList == null || planFactoringList.isEmpty()) {
            return null;
        }

        List<PaymentCollectionPlanFactoring> filterList = planFactoringList.stream().filter(p -> p.getAmountType().getId().equals(amountTypeDict.getId())
                && p.getPaymentCollectionType().equals(ConstantConversionUtil.PAY_COLL_COLLECTION)).collect(Collectors.toList());
        if (filterList == null) {
            return new ArrayList<>();
        }
        return filterList;
    }


    /**
     * 获取计划中计算应收的利息或管理费总计
     *
     * @param principalList
     * @param dict
     * @param goodsAssign
     * @param paymentCalculateVo
     * @return
     */
    private BigDecimal getAllocatedAmountByPlanFactoring(List<PaymentCollectionPlanFactoring> principalList, Dictionary dict,
                                                         LedgerFundGoodsAssign goodsAssign, PrePaymentCalculateVo paymentCalculateVo) {
        //计算需要分配掉的利息或管理费
        if (principalList == null || principalList.isEmpty()) {
            return BigDecimal.ZERO;
        }

        //根据已收日期和金额生成新的计划
        List<PaymentCollectionPlanFactoring> newPrincipalList = new ArrayList<>();
        principalList.stream().forEach(p -> {
            List<PayCollPlanFactoringAmountAllocation> amountAllocationList = p.getAmountAllocationList();
            if (CollectionUtil.isNotEmpty(amountAllocationList)) {
                amountAllocationList.stream().forEach(a -> {
                    PaymentCollectionPlanFactoring factoring = new PaymentCollectionPlanFactoring();
                    if (a.getActualDate().before(p.getPlanDate())) {
                        factoring.setPlanDate(a.getActualDate());
                    } else {
                        factoring.setPlanDate(p.getPlanDate());
                    }
                    factoring.setAmount(a.getActualAmount());
                    newPrincipalList.add(factoring);
                });
            } else {
                PaymentCollectionPlanFactoring factoring = new PaymentCollectionPlanFactoring();
                factoring.setPlanDate(p.getPlanDate());
                factoring.setAmount(p.getAmount());
                newPrincipalList.add(factoring);
            }
        });

        //planDate 相同的需要合并处理
        List<PaymentCollectionPlanFactoring> mergeList = new ArrayList<>();
        newPrincipalList.stream().collect(Collectors.groupingBy(p -> DateUtil.beginOfDay(p.getPlanDate()), Collectors.toList())).forEach((id, transfer) -> {
            transfer.stream().reduce((a, b) -> new PaymentCollectionPlanFactoring(a.getPlanDate(), a.getAmount().add(b.getAmount()))).ifPresent(mergeList::add);
        });

        Collections.sort(mergeList, Comparator.comparing(PaymentCollectionPlanFactoring::getPlanDate));

        Date loanDate = goodsAssign.getLoanDate();
        BigDecimal surplusPrincipal = goodsAssign.getLoanAmount();

        BigDecimal allocatedAmountTotal = BigDecimal.ZERO;
        if (mergeList != null && mergeList.size() > 0) {
            Date start;
            Date end;
            BigDecimal allocatedAmount;
            for (int i = 0; i < mergeList.size(); i++) {
                if (i == 0) {
                    start = loanDate;
                    end = mergeList.get(i).getPlanDate();
                    allocatedAmount = calculateAssignInterest(surplusPrincipal, start, end, true, paymentCalculateVo, dict.getCode());
                } else {
                    start = mergeList.get(i - 1).getPlanDate();
                    end = mergeList.get(i).getPlanDate();
                    allocatedAmount = calculateAssignInterest(surplusPrincipal, start, end, false, paymentCalculateVo, dict.getCode());
                }
                surplusPrincipal = surplusPrincipal.subtract(mergeList.get(i).getAmount());
                allocatedAmountTotal = allocatedAmountTotal.add(allocatedAmount);
            }
        }
        return allocatedAmountTotal;
    }

    /**
     * 获取最后一期收款计划
     *
     * @param planFactoringList 计划
     * @param dict              金额类型字典项
     * @return
     */
    private PaymentCollectionPlanFactoring getLastPrincipalFactoring(List<PaymentCollectionPlanFactoring> planFactoringList, Dictionary dict, Date lastPlanDate) {
        if (planFactoringList == null || planFactoringList.isEmpty()) {
            throw new BusinessException(CodeUtil.FAIL, "收放款计划不能为空");
        }

        List<PaymentCollectionPlanFactoring> filterList = planFactoringList.stream().filter(p -> p.getAmountType().getCode().equals(dict.getCode())
                && p.getPaymentCollectionType().equals(ConstantConversionUtil.PAY_COLL_COLLECTION)
                && DateUtil.isSameDay(p.getPlanDate(), lastPlanDate)).collect(Collectors.toList());
        if (filterList != null && filterList.size() > 0) {
            return filterList.get(0);
        } else {
            return null;
        }
    }

    /**
     * 计算分配的利息或保证金
     *
     * @param amount
     * @param startDate
     * @param endDate
     * @param flag               判断是否记头 true:记头,false:不记头
     * @param paymentCalculateVo
     * @param amountType
     * @
     */
    private BigDecimal calculateAssignInterest(BigDecimal amount, Date startDate, Date endDate, Boolean flag,
                                               PrePaymentCalculateVo paymentCalculateVo, String amountType) {

        //判断是否计算投放日
        Integer interestCalculate = paymentCalculateVo.getInterestCalculate();
        long between = 0;
        if (interestCalculate == 1) {
            if (flag) {
                between = DateUtil.betweenDay(startDate, endDate, true) + 1;
            } else {
                between = DateUtil.betweenDay(startDate, endDate, true);
            }
        } else if (interestCalculate == 0) {
            between = DateUtil.betweenDay(startDate, endDate, true);
        }

        Double financingRate = paymentCalculateVo.getFinancingRate();
        Double managementFeeRatio = paymentCalculateVo.getManagementFeeRatio();
        BigDecimal rate = BigDecimal.ZERO;
        if (amountType.equals(IncomeExpenditureTypeDict.ChildEnum.MANAGEMENT_FEE.getCode())) {
            rate = BigDecimal.valueOf(managementFeeRatio);
        } else if (amountType.equals(IncomeExpenditureTypeDict.ChildEnum.INTEREST.getCode())) {
            rate = BigDecimal.valueOf(financingRate);
        }

        //计算管理费或利息
        return amount.multiply(BigDecimal.valueOf(between))
                .multiply(rate).divide(new BigDecimal(360), 2, RoundingMode.HALF_UP);
    }

    /**
     * 添加对应sop收放款计划变更数据
     *
     * @param ledgerDate          入账日期
     * @param currentAssignAmount 本次分配金额
     * @param planFactoring       对应sop收放款计划
     * @param goodsAssign         货物分配信息
     * @param isPrincipal         是否本金类型
     * @return
     */
    private LedgerPlanFactoringAssign addPlanFactoringUpdateAssign(Date ledgerDate, BigDecimal currentAssignAmount,
                                                                   PaymentCollectionPlanFactoring planFactoring,
                                                                   LedgerFundGoodsAssign goodsAssign, Integer isPrincipal) {
        LedgerPlanFactoringAssign planFactoringAssign = new LedgerPlanFactoringAssign();
        planFactoringAssign.setPlanDate(planFactoring.getPlanDate());
        planFactoringAssign.setActualDate(ledgerDate);
        planFactoringAssign.setPlanAmount(planFactoring.getAmount());
        planFactoringAssign.setActualAmount(currentAssignAmount);
        planFactoringAssign.setPlanFactoringId(planFactoring.getId());
        planFactoringAssign.setAmountType(dictService.get(planFactoring.getAmountType().getId()).getCode());
        planFactoringAssign.setPrincipal(isPrincipal);
        planFactoringAssign.setSopAccountsReceivableId(goodsAssign.getSopAccountsReceivableId());
        planFactoringAssign.setBillingFactoringBusinessLoanRecordId(goodsAssign.getBillingFactoringBusinessLoanRecordId());
        planFactoringAssign.setPayCollBasicId(goodsAssign.getPayCollBasicId());
        planFactoringAssign.setDeleteFlag(false);
        return planFactoringAssign;
    }

    /**
     * 添加对应sop收放款计划删除数据
     *
     * @param planFactoring 收放款计划
     * @param goodsAssign   货物分配信息
     * @param isPrincipal   是否为本金分配
     * @return
     */
    private LedgerPlanFactoringAssign addPlanFactoringDeleteAssign(PaymentCollectionPlanFactoring planFactoring,
                                                                   LedgerFundGoodsAssign goodsAssign, Integer isPrincipal) {
        LedgerPlanFactoringAssign planFactoringAssign = new LedgerPlanFactoringAssign();
        planFactoringAssign.setPlanFactoringId(planFactoring.getId());
        planFactoringAssign.setPrincipal(isPrincipal);
        planFactoringAssign.setSopAccountsReceivableId(goodsAssign.getSopAccountsReceivableId());
        planFactoringAssign.setBillingFactoringBusinessLoanRecordId(goodsAssign.getBillingFactoringBusinessLoanRecordId());
        planFactoringAssign.setPayCollBasicId(goodsAssign.getPayCollBasicId());
        planFactoringAssign.setDeleteFlag(true);
        return planFactoringAssign;
    }

    /**
     * 添加对应sop收放款计划新增数据
     *
     * @param ledgerDate   入账日期
     * @param planAmount   计划金额
     * @param actualAmount 实际金额
     * @param amountType   金额类型
     * @param goodsAssign  货物分配信息
     * @param isPrincipal  是否为本金分配
     * @return
     */
    private LedgerPlanFactoringAssign addPlanFactoringInsertAssign(Date ledgerDate, BigDecimal
            planAmount, BigDecimal actualAmount, String amountType, LedgerFundGoodsAssign goodsAssign, Integer isPrincipal) {
        LedgerPlanFactoringAssign planFactoringAssign = new LedgerPlanFactoringAssign();
        planFactoringAssign.setPlanAmount(planAmount);
        planFactoringAssign.setActualAmount(actualAmount);
        planFactoringAssign.setActualDate(ledgerDate);
        planFactoringAssign.setAmountType(amountType);
        planFactoringAssign.setPrincipal(isPrincipal);
        planFactoringAssign.setSopAccountsReceivableId(goodsAssign.getSopAccountsReceivableId());
        planFactoringAssign.setBillingFactoringBusinessLoanRecordId(goodsAssign.getBillingFactoringBusinessLoanRecordId());
        planFactoringAssign.setPayCollBasicId(goodsAssign.getPayCollBasicId());
        planFactoringAssign.setDeleteFlag(false);
        return planFactoringAssign;
    }

    /**
     * 计算分配的金额
     *
     * @param assignAmount
     * @param factoring
     * @return
     */
    private BigDecimal assignAmount(BigDecimal assignAmount, PaymentCollectionPlanFactoring factoring) {
        //先获取已收款金额
        List<PayCollPlanFactoringAmountAllocation> amountAllocationList = factoring.getAmountAllocationList();
        BigDecimal collAmountSum = BigDecimal.ZERO;
        if (amountAllocationList != null && amountAllocationList.size() > 0) {
            collAmountSum = amountAllocationList.stream().filter(a -> a.getActualAmount() != null)
                    .map(PayCollPlanFactoringAmountAllocation::getActualAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        }
        //剩余未分配
        BigDecimal surplus = factoring.getAmount().subtract(collAmountSum);

        //该笔收放款本次分配金额
        BigDecimal currentAssignAmount;
        if (assignAmount.compareTo(surplus) >= 0) {
            currentAssignAmount = surplus;
        } else {
            currentAssignAmount = assignAmount;
        }
        return currentAssignAmount;
    }

    @Override
    public List<SupplierListVo> getSupplierList(Long id) {
        LedgerAccountBasicInfo ledgerAccountBasicInfo = ledgerAccountBasicInfoService.getById(id);
        List<SupplierListVo> supplierList = new ArrayList<>();
//        if (ledgerAccountBasicInfo != null && ledgerAccountBasicInfo.getBusinessNumber() != null) {
//            supplierList = ledgerAccountBasicInfoService.getSupplierList(ledgerAccountBasicInfo.getBusinessNumber());
//        }
        return supplierList;
    }
}
