放款(提现、用信)-试算还款计划-JAVA实现

1、等额本金:每期本金相同

2、等额本息:每期还款额相同

/**
 * @author wzh
 * @date 2019-11-20 18:45
 * @description 试算还款计划-入参
 */
@Data
@Builder
public class CalculateRepayPlanReq implements Serializable {
    /**
     * 借款金额(元),非空
     */
    private BigDecimal principle;
    /**
     * 期限天,非空
     */
    private Integer termDay;
    /**
     * 年利率,比如一年期贷款4.35,传入4.35,非空
     */
    private BigDecimal yearRate;
    /**
     * 起息日,非空
     */
    private Date beginProfitDate;
    /**
     * 费率集合,可空
     */
    private List feeRulePojoList;
    /**
     * 特殊日期范围,例如:28-31
     */
    private String specialDateRange;
    /**
     * 特殊日期调整日,27
     */
    private String specialDateAdjustDay;
    
}
/** 
 * @Author: wzh
 * @Date: 2019-03-28T15:33:47.526
 * @Description: 还款计划
 */

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RepayPlanRes implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 总期次
     */
    @NotNull
    private Integer repayNum;

    /**
     * 当前期次
     */
    @NotNull
    private Integer currentNum;

    /**
     * 开始时间
     */
    @NotNull
    private Date startDate;

    /**
     * 到期时间
     */
    @NotNull
    private Date endDate;

    /**
     * 收益天数
     */
    @NotNull
    private Integer profitDays;

    /**
     * 应还时间
     */
    @NotNull
    private Date preRepayDate;

    /**
     * 应还总额
     */
    @NotNull
    private BigDecimal preRepayAmt;

    /**
     * 应还本金
     */
    @NotNull
    private BigDecimal preRepayPrincipal;

    /**
     * 应还利息
     */
    @NotNull
    private BigDecimal preRepayInterest;

    /**
     * 应还手续费
     */
    @NotNull
    private BigDecimal preRepayFee;

    /**
     * 应还账户管理费
     */
    @NotNull
    private BigDecimal preRepayManagementFee;
    /**
     * 剩余本金
     */
    @NotNull
    private BigDecimal leftPrincipal;

}
/**
 * 包装公共方法
 *
 * @author wzh
 * @date 2019年09月23日11:27:04
 */
public abstract class AbstractCalculateServiceImpl implements CalculateService {

    /**
     * 期限天转期限月
     * 备注:主要适用于按月计息的
     * @param termDay
     * @return
     */
    protected Integer transTermMonth(Integer termDay) {
        //按月计算,除以30取整
        BigDecimal termDayBg=new BigDecimal(termDay);
        return termDayBg.divide(new BigDecimal(30),0,BigDecimal.ROUND_HALF_UP).intValue();
    }

    /**
     * 月利率
     * 备注:主要适用于按月计息的
     * @param yearRate
     * @return
     */
    protected BigDecimal transMonthRate(BigDecimal yearRate) {
        //月利率
        return yearRate.divide(new BigDecimal(12),6,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(0.01));
    }


    /**
     * 返回日利率
     *
     * @param yearRate
     * @return
     */
    protected BigDecimal transDayRate(BigDecimal yearRate) {
        return yearRate.divide(new BigDecimal(360),6,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(0.01));
    }
    /**
     * 计算手续费
     * @param principle     本金
     * @param feeRulePojoList       费率规则
     * @return
     */
    protected BigDecimal calculateFee(BigDecimal principle,List feeRulePojoList) {

        if(CollectionUtils.isEmpty(feeRulePojoList)){
            return BigDecimal.ZERO;
        }

        BigDecimal feeTotal = BigDecimal.ZERO;

        for(FeeRuleReq feeRulePojo:feeRulePojoList) {
            BigDecimal fee = BigDecimal.ZERO;
            EnumFeeType enumFeeType = feeRulePojo.getFeeType();
            if (ONCE_SERVICE_FEE.equals(enumFeeType)) {
                fee = principle.multiply(feeRulePojo.getFeeRate()).multiply(new BigDecimal(0.01));
            } else if (FEE.equals(enumFeeType)) {
                fee = principle.multiply(feeRulePojo.getFeeRate()).multiply(new BigDecimal(0.01));
            }
            feeTotal=feeTotal.add(fee);
        }
        return feeTotal;

    }

    /**
     * 计算账户管理费
     * @param principle     本金
     * @param leftPrinciple 剩余本金
     * @param feeRulePojoList       费率规则
     * @return
     */
    protected BigDecimal calculateManagementFee(BigDecimal principle, BigDecimal leftPrinciple, List feeRulePojoList) {

        if(CollectionUtils.isEmpty(feeRulePojoList)){
            return BigDecimal.ZERO;
        }

        BigDecimal feeTotal = BigDecimal.ZERO;

        for(FeeRuleReq feeRulePojo:feeRulePojoList) {
            BigDecimal fee = BigDecimal.ZERO;
            EnumFeeType enumFeeType = feeRulePojo.getFeeType();
            if (MANAGEMENT_FEE.equals(enumFeeType)) {
                if (feeRulePojo.getFeeCalculateType() == EnumFeeCalculateType.LOANAMT_FEERATE) {
                    fee = principle.multiply(feeRulePojo.getFeeRate()).multiply(new BigDecimal(0.01));
                } else if (feeRulePojo.getFeeCalculateType() == EnumFeeCalculateType.LEFTPRINCIPLE_FEERATE) {
                    fee = leftPrinciple.multiply(feeRulePojo.getFeeRate()).multiply(new BigDecimal(0.01));
                }
            }
            feeTotal=feeTotal.add(fee);
        }
        return feeTotal;

    }

}
/**
 * 等额本息
 *
 * @author wzh
 * @date 2019年09月19日16:17:12
 */
@Slf4j
@Component
public class EqualAmtInterestCalculate extends AbstractCalculateServiceImpl {

@Override
    public List calculateRepayPlan(CalculateRepayPlanReq calculateRepayPlanDto) {

        BigDecimal principle=calculateRepayPlanDto.getPrinciple();

        Date date=calculateRepayPlanDto.getBeginProfitDate();

        List repayPlanList=new ArrayList();
        //转期限月
        Integer termMonth=transTermMonth(calculateRepayPlanDto.getTermDay());
        //月利率
        BigDecimal monthRate=transMonthRate(calculateRepayPlanDto.getYearRate());
        /**
         * 计算每期应还息费总额=(贷款本金×期利率×(1+期利率)^还款期数)÷((1+期利率)^还款期数-1) (四舍五入)
         */
        BigDecimal periodAmt = principle.multiply(monthRate).multiply((BigDecimal.ONE.add(monthRate)).pow(termMonth))
                .divide(((BigDecimal.ONE.add(monthRate)).pow(termMonth)).subtract(BigDecimal.ONE), 2,BigDecimal.ROUND_HALF_UP);
        //应还总利息
        //BigDecimal preRepayInterestTotal=principle.multiply(BigDecimal.valueOf(repayNum+1)).multiply(monthRate).divide(new BigDecimal(2));

        //剩余本金
        BigDecimal leftPrincipal=principle;

        for(int i=1;i<=termMonth;i++) {

            RepayPlanRes repayPlanPojo = new RepayPlanRes();
            //总期次
            repayPlanPojo.setRepayNum(termMonth);
            //当期期次
            repayPlanPojo.setCurrentNum(i);
            if(i==1){
                //起息日
                repayPlanPojo.setStartDate(date);
            }else{

                Date startDate=DateUtil.dateAddMonth(date,i-1);
                if(!CollectionUtils.isEmpty(dayList)&&dayList.contains(DateUtil.formateDate(startDate,DateUtil.FMT_DD))){
                    //处于范围期,下移一个月,再取月初X号
                    Date nextMonthDate=DateUtil.dateAddMonth(startDate,1);
                    repayPlanPojo.setStartDate(DateUtil.getMonthBegin(nextMonthDate, Integer.parseInt(calculateRepayPlanDto.getSpecialDateAdjustDay())));
                }else{
                    //起息日
                    repayPlanPojo.setStartDate(startDate);
                }
            }
            Date endDate=DateUtil.dateAddMonth(date,i);
            if(!CollectionUtils.isEmpty(dayList)&&dayList.contains(DateUtil.formateDate(endDate,DateUtil.FMT_DD))){
                //处于范围期,下移一个月,再取月初X号
                Date nextMonthDate=DateUtil.dateAddMonth(endDate,1);
                repayPlanPojo.setEndDate(DateUtil.getMonthBegin(nextMonthDate, Integer.parseInt(calculateRepayPlanDto.getSpecialDateAdjustDay())));
                //应还日
                repayPlanPojo.setPreRepayDate(DateUtil.getMonthBegin(nextMonthDate, Integer.parseInt(calculateRepayPlanDto.getSpecialDateAdjustDay())));

            }else{
                //起息日
                repayPlanPojo.setEndDate(endDate);
                //应还日
                repayPlanPojo.setPreRepayDate(endDate);
            }

            //收益天数
            int profitDays=DateUtil.getBetweenDays(repayPlanPojo.getStartDate(),repayPlanPojo.getEndDate());

            //应还利息
            BigDecimal preRepayInterest=leftPrincipal.multiply(monthRate);
            //应还利息赋值
            repayPlanPojo.setPreRepayInterest(preRepayInterest.setScale(2,BigDecimal.ROUND_HALF_UP));
            //应还本金
            BigDecimal preRepayPrinciple=periodAmt.subtract(preRepayInterest).setScale(2,BigDecimal.ROUND_HALF_UP);
            //应还本金,判断是否最后一期
            if(i==termMonth){
                //最后一期应还本金
                repayPlanPojo.setPreRepayPrincipal(leftPrincipal.setScale(2,BigDecimal.ROUND_HALF_UP));
                //应还利息赋值
                repayPlanPojo.setPreRepayInterest(periodAmt.subtract(leftPrincipal).setScale(2,BigDecimal.ROUND_HALF_UP));
            }else{
                //应还本金赋值
                repayPlanPojo.setPreRepayPrincipal(preRepayPrinciple.setScale(2,BigDecimal.ROUND_HALF_UP));
                //应还利息赋值
                repayPlanPojo.setPreRepayInterest(preRepayInterest.setScale(2,BigDecimal.ROUND_HALF_UP));
            }

            //应还手续费
            BigDecimal preRepayFee=calculateFee(principle,calculateRepayPlanDto.getFeeRulePojoList());
            repayPlanPojo.setPreRepayFee(preRepayFee);
            //应还账户管理费
            BigDecimal preRepayManagementFee=calculateManagementFee(principle,leftPrincipal,calculateRepayPlanDto.getFeeRulePojoList());
            repayPlanPojo.setPreRepayManagementFee(preRepayManagementFee);
            //应还总额=应还本金+应还利息+应还手续费+应还账户管理费
            repayPlanPojo.setPreRepayAmt(periodAmt.add(preRepayFee.add(preRepayManagementFee)).setScale(2,BigDecimal.ROUND_HALF_UP));
            //剩余应还本金
            repayPlanPojo.setLeftPrincipal(leftPrincipal.setScale(2,BigDecimal.ROUND_HALF_UP));
            //以下内容暂且注释
            //repayPlanPojo.setLeftRepayPrincipal(leftPrincipal.setScale(2,BigDecimal.ROUND_HALF_UP));
            //剩余应还利息
            //BigDecimal leftRepayInterest=preRepayInterestTotal.subtract(preRepayInterest);
            //repayPlanPojo.setLeftRepayInterest(leftRepayInterest.setScale(4,BigDecimal.ROUND_HALF_UP));
            //剩余应还总金额
            //repayPlanPojo.setLeftRepayAmt(leftPrincipal.add(leftRepayInterest).setScale(4,BigDecimal.ROUND_HALF_UP));
            //当期——剩余应还本金
            leftPrincipal=leftPrincipal.subtract(preRepayPrinciple);

            repayPlanList.add(repayPlanPojo);

        }

        return repayPlanList;
    }
}
/**
 * 等额本金
 *
 * @author wzh
 * @date 2019年09月19日16:16:54
 */
@Component
public class EqualAmtPrincipleCalculate extends AbstractCalculateServiceImpl {

    @Override
    public List calculateRepayPlan(CalculateRepayPlanReq calculateRepayPlanDto) {

        BigDecimal principle=calculateRepayPlanDto.getPrinciple();

        Date date=calculateRepayPlanDto.getBeginProfitDate();

        List repayPlanList=new ArrayList();
        //转期限月
        Integer termMonth=transTermMonth(calculateRepayPlanDto.getTermDay());
        //月利率
        BigDecimal monthRate=transMonthRate(calculateRepayPlanDto.getYearRate());
        //日利率
        //BigDecimal dayRate=yearRate.divide(new BigDecimal(360),6,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(0.01));

        //应还总利息
        //BigDecimal preRepayInterestTotal=principle.multiply(BigDecimal.valueOf(repayNum+1)).multiply(monthRate).divide(new BigDecimal(2));
        //必须进行循环处理,最后一期用总数减去累加值,防止小数点误差
        BigDecimal preRepayPrincipleTotal=BigDecimal.ZERO;

        BigDecimal preRepayPrinciple=principle.divide(BigDecimal.valueOf(termMonth),2,BigDecimal.ROUND_HALF_UP).setScale(2,BigDecimal.ROUND_HALF_UP);

        for(int i=1;i<=termMonth;i++) {

            RepayPlanRes repayPlanPojo = new RepayPlanRes();
            //总期次
            repayPlanPojo.setRepayNum(termMonth);
            //当期期次
            repayPlanPojo.setCurrentNum(i);
            //起息日
            repayPlanPojo.setStartDate(DateUtil.dateAddMonth(date,i-1));

            //结息日
            repayPlanPojo.setEndDate(DateUtil.dateAddMonth(date,i));
            //应还日
            repayPlanPojo.setPreRepayDate(DateUtil.dateAddMonth(date,i));
            //收益天数
            repayPlanPojo.setProfitDays(DateUtil.getBetweenDays(DateUtil.dateAddMonth(date,i-1),DateUtil.dateAddMonth(date,i)));

            //应还本金,判断是否最后一期
            if(i==termMonth){
                //最后一期应还本金
                repayPlanPojo.setPreRepayPrincipal(principle.subtract(preRepayPrincipleTotal));
            }else{
                //应还本金
                repayPlanPojo.setPreRepayPrincipal(preRepayPrinciple);
            }

            //剩余本金
            BigDecimal leftPrincipal=principle.subtract(preRepayPrincipleTotal);
            //应还利息
            BigDecimal preRepayInterest=leftPrincipal.multiply(monthRate);
            //应还利息
            repayPlanPojo.setPreRepayInterest(preRepayInterest.setScale(2,BigDecimal.ROUND_HALF_UP));
            //应还费用
            BigDecimal preRepayFee=calculateFee(principle,calculateRepayPlanDto.getFeeRulePojoList());
            repayPlanPojo.setPreRepayFee(preRepayFee);
            //应还账户管理费
            BigDecimal preRepayManagementFee=calculateManagementFee(principle,leftPrincipal,calculateRepayPlanDto.getFeeRulePojoList());
            repayPlanPojo.setPreRepayManagementFee(preRepayManagementFee);
            //应还总额=应还本金+应还利息+应还手续费+应还账户管理费
            repayPlanPojo.setPreRepayAmt(preRepayPrinciple.add(preRepayInterest).add(preRepayFee.add(preRepayManagementFee)).setScale(2,BigDecimal.ROUND_HALF_UP));
            //剩余应还本金
            repayPlanPojo.setLeftPrincipal(leftPrincipal.setScale(2,BigDecimal.ROUND_HALF_UP));
            //以下内容暂且注释
            //repayPlanPojo.setLeftRepayPrincipal(leftPrincipal.setScale(2,BigDecimal.ROUND_HALF_UP));
            //剩余应还利息
            //BigDecimal leftRepayInterest=preRepayInterestTotal.subtract(preRepayInterest);
            //repayPlanPojo.setLeftRepayInterest(leftRepayInterest.setScale(4,BigDecimal.ROUND_HALF_UP));
            //剩余应还总金额
            //repayPlanPojo.setLeftRepayAmt(leftPrincipal.add(leftRepayInterest).setScale(4,BigDecimal.ROUND_HALF_UP));
            //当期——累计应还总本金
            preRepayPrincipleTotal=preRepayPrincipleTotal.add(preRepayPrinciple);

            repayPlanList.add(repayPlanPojo);

        }

        return repayPlanList;
    }
}

 

你可能感兴趣的:(java开发,银行业务)