背景:在保单申请提前结清退保时,发现计算的退保保费与实收保费值不符。
经过排查发现,此时需要计算退保保费,保费根据业务不同,可以按照在保天数收取,也可以按照在保期次收取。
这个渠道就是采用,天数的方式收取保费,公式:退保日期之前的所有期次保费全收,退保日期所在期次保费按天收取(该期次应收保费/30*(提前结清退保日期-该期次起始日期+1))。
应收保费采用的BigDecimal类型,BigDecimal在进行计算时,会进行四舍五入。
原代码中:
该期次应收保费/30:会进行一次四舍五入。
再乘以天数时。
//每天保费
oneDayDueInsamt = dueInsamt.divide(new BigDecimal(30),2,ROUND_HALF_UP);
//当期应收保费
dueInsamtSum = oneDayDueInsamt.multiply(days);
这样计算就造成了保费的精度丢失。
改为先相乘、再进行除法计算。就不会导致精度丢失。
BigDecimal dueInsamtSum = dueInsamt.multiply(days).divide(new BigDecimal(30), 2, ROUND_HALF_UP);
在上一版修改后,精度问题已经修复,但是在进行退保时,发现退保保费计算出来的误差更大了。
经过排查发现,开发人员又犯了另一个错误。
//计算相差天数,起始天数与退保天数差值
String dateGap = getDateGap(startDay, endorseDate);
BigDecimal days= new BigDecimal(dateGap + 1);
//当期应收保费
dueInsamtSum = oneDayDueInsamt.multiply(days);
重点在于dateGap +1,此时是字符串拼接,dateGap 为3时,days的值就是31。导致最后保费计算误差更大。