我写过的最繁琐的业务逻辑
boolean flag = true;
boolean firstFlag = true;
int alreadyPlusTimes = 0;
//计算差值用
BigDecimal zero = new BigDecimal(0);
//违约金利率
BigDecimal rate = BigDecimal.valueOf(0.0005);
//已理赔的总和
BigDecimal tmpAmount = zero;
BigDecimal surplusClaimAmount = zero;
BigDecimal claimAmount = zero;
BigDecimal claimPenalty = zero;
//总违约金
BigDecimal totalClaimPenalty = zero;
//已偿还的理赔金总和
BigDecimal totalRepayClaimAmount = zero;
String loanNo = "";
int times = 0;
for (WanningClaimDto wanningClaimDto : wanningClaimDtos) {
List<DateAndAmount> dateAndAmounts = transfer(wanningClaimDto.getAmount_array());
//判断是否同一个人的数据,不是同一个人全部重置
if (!loanNo.equals(wanningClaimDto.getLoan_no())) {
surplusClaimAmount = zero;
alreadyPlusTimes = 0;
tmpAmount = zero;
totalClaimPenalty = zero;
totalRepayClaimAmount = zero;
claimPenalty = zero;
flag = true;
firstFlag = true;
claimAmount = dateAndAmounts.get(times).getAmount();
loanNo = wanningClaimDto.getLoan_no();
}
//当次理赔金额
BigDecimal currentClaimAmount = wanningClaimDto.getClaim_amt();
//依次累加的理赔金额
tmpAmount = tmpAmount.add(currentClaimAmount);
//flag = false 代表回款金额用完了
if (flag) {
while (times < dateAndAmounts.size()) {
//如果有多条,依次累加追偿金额和剩余追偿金额
if (times > 0 && alreadyPlusTimes < dateAndAmounts.size() - 1) {
alreadyPlusTimes++;
claimAmount = claimAmount.add(dateAndAmounts.get(alreadyPlusTimes).getAmount());
surplusClaimAmount = surplusClaimAmount.add(dateAndAmounts.get(alreadyPlusTimes).getAmount());
}
//理赔还款日期
Date claimDate = dateAndAmounts.get(alreadyPlusTimes).getDate();
//总追偿 >= 总理赔
if (claimAmount.compareTo(tmpAmount) > -1) {
//追偿还款日期
wanningClaimDto.setClaim_repay_amt(currentClaimAmount);
wanningClaimDto.setClaim_last_repay_date(claimDate);
//如果只有一期完全冲抵才算违约金
if (claimAmount.compareTo(dateAndAmounts.get(alreadyPlusTimes).getAmount()) == 0) {
wanningClaimDto.setClaim_penalty_amt(currentClaimAmount.multiply(new BigDecimal(DateUtils.getDayDiff(claimDate, wanningClaimDto.getRf_date())).multiply(rate)));
}
//剩余追偿金额
surplusClaimAmount = claimAmount.subtract(tmpAmount);
//当期追偿金额不足以抵扣,去加下一次的追偿金额
break;
//总追偿 < 总理赔
} else {
//最后一次进来
if (dateAndAmounts.size() - 1 == times) {
//剩余追偿大于 0
if (surplusClaimAmount.compareTo(zero) == 1) {
wanningClaimDto.setClaim_repay_amt(surplusClaimAmount);
//追偿金额不足时违约金
//理赔 * (还款日期 - 理赔日期) + (理赔 - 已理赔) * (当前日期 - 理赔日期)
//可能发生多次还款,要分别考虑
//总的违约金 = 0
if (totalClaimPenalty.compareTo(zero) == 0) {
claimPenalty = currentClaimAmount.multiply(new BigDecimal(DateUtils.getDayDiff(claimDate, wanningClaimDto.getRf_date()))).multiply(rate);
BigDecimal leftClaimPenalty = currentClaimAmount.subtract(surplusClaimAmount).multiply(new BigDecimal(DateUtils.getDayDiff(new Date(), dateAndAmounts.get(alreadyPlusTimes).getDate())).multiply(rate));
wanningClaimDto.setClaim_penalty_amt(claimPenalty.add(leftClaimPenalty));
}
//有多次还款 且没有冲抵多期
if (dateAndAmounts.size() > 1 && dateAndAmounts.size() - 1 != times) {
BigDecimal leftClaimPenalty = currentClaimAmount.subtract(surplusClaimAmount).multiply(new BigDecimal(DateUtils.getDayDiff(new Date(), dateAndAmounts.get(alreadyPlusTimes).getDate())).multiply(rate));
wanningClaimDto.setClaim_penalty_amt(totalClaimPenalty.add(leftClaimPenalty));
}
claimAmount = zero;
surplusClaimAmount = zero;
flag = false;
//理赔还款 < 第一个理赔金额(特殊情况)
} else {
wanningClaimDto.setClaim_repay_amt(dateAndAmounts.get(times).getAmount());
totalRepayClaimAmount = totalRepayClaimAmount.add(dateAndAmounts.get(alreadyPlusTimes).getAmount());
claimPenalty = currentClaimAmount.multiply(new BigDecimal(DateUtils.getDayDiff(claimDate, wanningClaimDto.getRf_date()))).multiply(rate);
BigDecimal leftClaimPenalty = currentClaimAmount.subtract(totalRepayClaimAmount).multiply(new BigDecimal(DateUtils.getDayDiff(new Date(), dateAndAmounts.get(alreadyPlusTimes).getDate())).multiply(rate));
wanningClaimDto.setClaim_penalty_amt(claimPenalty.add(leftClaimPenalty));
flag = false;
}
//当期理赔金额 > 每次还款的和 (有多次还款对应一期理赔)
} else {
//如果加下期的回款 >= 当期理赔
if (dateAndAmounts.size() - 1 != alreadyPlusTimes && currentClaimAmount.compareTo(surplusClaimAmount.add(dateAndAmounts.get(alreadyPlusTimes + 1).getAmount())) < 1) {
//前一期剩下的钱 * 回款时间 - 理赔时间
claimPenalty = surplusClaimAmount.multiply(new BigDecimal(DateUtils.getDayDiff(dateAndAmounts.get(times + 1).getDate(), claimDate))).multiply(rate);
wanningClaimDto.setClaim_penalty_amt(claimPenalty.add(currentClaimAmount.subtract(surplusClaimAmount).
multiply(new BigDecimal(DateUtils.getDayDiff(claimDate, wanningClaimDto.getRf_date()))).multiply(rate)));
} else {
//总追偿(还款)金额
//未偿还前的违约金,只在开始时执行一次
if (firstFlag || surplusClaimAmount.compareTo(zero) == 1) {
claimPenalty = currentClaimAmount.multiply(new BigDecimal(DateUtils.getDayDiff(claimDate, wanningClaimDto.getRf_date()))).multiply(rate);
}
//当期偿还部分总和
if (firstFlag || surplusClaimAmount.compareTo(zero) == 1) {
totalRepayClaimAmount = totalRepayClaimAmount.add(surplusClaimAmount);
} else {
totalRepayClaimAmount = totalRepayClaimAmount.add(dateAndAmounts.get(times).getAmount());
}
//最后一次进来
BigDecimal leftClaimPenalty;
if (dateAndAmounts.size() - 1 == times) {
leftClaimPenalty = currentClaimAmount.subtract(totalRepayClaimAmount).multiply(new BigDecimal(DateUtils.getDayDiff(new Date(), wanningClaimDto.getRf_date())).multiply(rate));
//使用最后一期回款金额时进入
} else if (dateAndAmounts.size() - 1 == alreadyPlusTimes) {
leftClaimPenalty = currentClaimAmount.subtract(totalRepayClaimAmount).multiply(new BigDecimal(DateUtils.getDayDiff(new Date(), dateAndAmounts.get(alreadyPlusTimes).getDate())).multiply(rate));
} else {
leftClaimPenalty = currentClaimAmount.subtract(totalRepayClaimAmount).multiply(new BigDecimal(DateUtils.getDayDiff(dateAndAmounts.get(times + 1).getDate(), dateAndAmounts.get(times).getDate())).multiply(rate));
}
//总违约金 = 分期加和
if (firstFlag | surplusClaimAmount.compareTo(zero) == 1) {
totalClaimPenalty = claimPenalty.add(leftClaimPenalty);
firstFlag = false;
} else {
totalClaimPenalty = totalClaimPenalty.add(leftClaimPenalty);
}
wanningClaimDto.setClaim_penalty_amt(totalClaimPenalty);
}
}
}
times++;
}
times = 0;
}
}