荆轲刺秦王
先看产品需求:
贷款总额合计:取还款明细子表所有的贷款金额之和;
已还款合计:取还款明细子表所有已还款之和;
已还款占比:自动计算,等于:(已还款合计/贷款总额合计)*100%,四舍五入取整(注:小于1%的统一取1%,大于99%小于100%的统一取99%);
剩余本息合计:取还款明细子表所有的剩余本息之和;
先上问题代码:
private CalculationTotalVo getCalculationTotalVo( List<RepayDetailEntity> targetList ){
CalculationTotalVo calculationTotalVo = new CalculationTotalVo();
BigDecimal totalLoanAmount = BigDecimal.ZERO;
BigDecimal totalRepaymentAmount = BigDecimal.ZERO;
if(!CollectionUtils.isEmpty(targetList)){
for (RepayDetailEntity item : targetList){
if(Objects.equals(item.getIsDelete(), RepayDetailEntity.NOTDELETE)){
totalLoanAmount = totalLoanAmount.add( item.getLoanAmount() == null ? BigDecimal.ZERO : item.getLoanAmount() );
totalRepaymentAmount = totalRepaymentAmount.add( item.getRepaymentAmount() == null ? BigDecimal.ZERO : item.getRepaymentAmount() );
}
}
}
// calculate rate
calculationTotalVo.setTotalLoanAmount( totalLoanAmount.compareTo(BigDecimal.ZERO) == 0 ? null : totalLoanAmount );
calculationTotalVo.setTotalRepaymentAmount( totalRepaymentAmount.compareTo(BigDecimal.ZERO) == 0 ? null : totalRepaymentAmount );
calculationTotalVo.setRateRepayment( null );
calculationTotalVo.setTotalRestPrincipalInterest( null );
if( totalRepaymentAmount.compareTo(BigDecimal.ZERO) != 0 && totalLoanAmount.compareTo(BigDecimal.ZERO) != 0 ){
BigDecimal rateRepayment = totalRepaymentAmount.divide(totalLoanAmount, 3, RoundingMode.DOWN).multiply( BigDecimal.valueOf(100) );
if( rateRepayment.compareTo(BigDecimal.ZERO) > 0 && rateRepayment.compareTo(BigDecimal.valueOf(1)) < 0 ){
rateRepayment = BigDecimal.valueOf(1);
}else if ( rateRepayment.compareTo(BigDecimal.valueOf(99)) > 0 && rateRepayment.compareTo(BigDecimal.valueOf(100)) < 0 ){
rateRepayment = BigDecimal.valueOf(99);
}
calculationTotalVo.setRateRepayment( rateRepayment );
calculationTotalVo.setTotalRestPrincipalInterest( totalLoanAmount.subtract(totalRepaymentAmount) );
}
return calculationTotalVo;
}
这段代码逻辑则是完全按照产品方案上的来,通过 已还款合计/贷款总额合计 计算得出占比。但是这里遇到的问题是 如果是 123456789/1 类似于一个特别大的数除以一个特别小的数就会导致结果为 0
看一下改进的代码:
private CalculationTotalVo getCalculationTotalVo( List<RepayDetailEntity> targetList ){
CalculationTotalVo calculationTotalVo = new CalculationTotalVo();
BigDecimal totalLoanAmount = BigDecimal.ZERO;
BigDecimal totalRepaymentAmount = BigDecimal.ZERO;
BigDecimal rateRepayment = BigDecimal.ZERO;
if(!CollectionUtils.isEmpty(targetList)){
for (RepayDetailEntity item : targetList){
if(Objects.equals(item.getIsDelete(), RepayDetailEntity.NOTDELETE)){
totalLoanAmount = totalLoanAmount.add( item.getLoanAmount() == null ? BigDecimal.ZERO : item.getLoanAmount() );
totalRepaymentAmount = totalRepaymentAmount.add( item.getRepaymentAmount() == null ? BigDecimal.ZERO : item.getRepaymentAmount() );
}
}
}
// calculate rate
// 已还款占比:(已还款合计/贷款总额合计)*100%,四舍五入取整(注:小于1%的统一取1%,大于99%小于100%的统一取99%)
// 这里反向计算
calculationTotalVo.setTotalLoanAmount( totalLoanAmount.compareTo(BigDecimal.ZERO) == 0 ? null : totalLoanAmount );
calculationTotalVo.setTotalRepaymentAmount( totalRepaymentAmount.compareTo(BigDecimal.ZERO) == 0 ? null : totalRepaymentAmount );
calculationTotalVo.setRateRepayment( null );
calculationTotalVo.setTotalRestPrincipalInterest( null );
if( totalRepaymentAmount.compareTo(BigDecimal.ZERO) != 0 && totalLoanAmount.compareTo(BigDecimal.ZERO) != 0 ){
BigDecimal rateRepaymentMin = totalLoanAmount.multiply( BigDecimal.valueOf(0.01) );
BigDecimal rateRepaymentMax = totalLoanAmount.multiply( BigDecimal.valueOf(0.99) );
if( rateRepaymentMin.compareTo(BigDecimal.ZERO) > 0 && totalRepaymentAmount.compareTo(rateRepaymentMin) <= 0 ){
rateRepayment = new BigDecimal("0.01");
}else if( totalRepaymentAmount.compareTo(rateRepaymentMax) > 0 && totalRepaymentAmount.compareTo(totalLoanAmount) < 0 ){
rateRepayment = new BigDecimal("0.99");
}else if( totalRepaymentAmount.compareTo(totalLoanAmount) > 0 ){
rateRepayment = new BigDecimal("1");
}else{
rateRepayment = totalRepaymentAmount.divide(totalLoanAmount, 3, RoundingMode.HALF_UP);
}
calculationTotalVo.setRateRepayment( rateRepayment );
calculationTotalVo.setTotalRestPrincipalInterest( totalLoanAmount.subtract(totalRepaymentAmount) );
}
return calculationTotalVo;
}
前端会将占比乘以100并加上百分号,所以这里仅存小数