FINERACT-2354: Handle N+1 installment together with re-aged installment correctly

This commit is contained in:
Oleksii Novikov
2025-09-16 10:54:00 +02:00
committed by Aleksandar Vidakovic
parent e02aaa9a1c
commit 8bddd15113
@@ -2856,8 +2856,10 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
adjustCalculatedPrincipal = outstandingPrincipalBalance.get() adjustCalculatedPrincipal = outstandingPrincipalBalance.get()
.minus(calculatedPrincipal.multipliedBy(loanTransaction.getLoanReAgeParameter().getNumberOfInstallments())); .minus(calculatedPrincipal.multipliedBy(loanTransaction.getLoanReAgeParameter().getNumberOfInstallments()));
} }
LoanRepaymentScheduleInstallment lastNormalInstallment = installments.stream().filter(i -> !i.isDownPayment()) final LoanRepaymentScheduleInstallment lastNormalInstallment = installments.stream() //
.reduce((first, second) -> second).orElseThrow(); .filter(i -> i.getDueDate().isBefore(loanTransaction.getTransactionDate())) //
.reduce((first, second) -> second) //
.orElseThrow();
LoanRepaymentScheduleInstallment reAgedInstallment = LoanRepaymentScheduleInstallment.newReAgedInstallment( LoanRepaymentScheduleInstallment reAgedInstallment = LoanRepaymentScheduleInstallment.newReAgedInstallment(
lastNormalInstallment.getLoan(), lastNormalInstallment.getInstallmentNumber() + 1, lastNormalInstallment.getDueDate(), lastNormalInstallment.getLoan(), lastNormalInstallment.getInstallmentNumber() + 1, lastNormalInstallment.getDueDate(),
loanTransaction.getLoanReAgeParameter().getStartDate(), calculatedPrincipal.getAmount()); loanTransaction.getLoanReAgeParameter().getStartDate(), calculatedPrincipal.getAmount());
@@ -2874,17 +2876,25 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
reAgedInstallment.updateObligationsMet(currency, loanTransaction.getTransactionDate()); reAgedInstallment.updateObligationsMet(currency, loanTransaction.getTransactionDate());
} }
reAgedInstallment.addToPrincipal(loanTransaction.getTransactionDate(), adjustCalculatedPrincipal); reAgedInstallment.addToPrincipal(loanTransaction.getTransactionDate(), adjustCalculatedPrincipal);
reprocessInstallmentsOrder(installments); reprocessInstallments(installments);
} }
protected void calculateAccrualActivity(LoanTransaction transaction, TransactionCtx ctx) { protected void calculateAccrualActivity(LoanTransaction transaction, TransactionCtx ctx) {
super.calculateAccrualActivity(transaction, ctx.getCurrency(), ctx.getInstallments()); super.calculateAccrualActivity(transaction, ctx.getCurrency(), ctx.getInstallments());
} }
private void reprocessInstallmentsOrder(List<LoanRepaymentScheduleInstallment> installments) { private void reprocessInstallments(final List<LoanRepaymentScheduleInstallment> installments) {
AtomicInteger counter = new AtomicInteger(1); final AtomicInteger counter = new AtomicInteger(1);
installments.stream().sorted(LoanRepaymentScheduleInstallment::compareToByDueDate) final AtomicReference<LocalDate> previousDueDate = new AtomicReference<>(null);
.forEachOrdered(i -> i.updateInstallmentNumber(counter.getAndIncrement())); installments.stream().sorted(LoanRepaymentScheduleInstallment::compareToByDueDate).forEachOrdered(i -> {
i.updateInstallmentNumber(counter.getAndIncrement());
final LocalDate prev = previousDueDate.get();
if (prev != null && i.isAdditional()) {
i.updateFromDate(prev);
}
previousDueDate.set(i.getDueDate());
});
} }
private LocalDate calculateReAgedInstallmentDueDate(LoanReAgeParameter reAgeParameter, LocalDate dueDate) { private LocalDate calculateReAgedInstallmentDueDate(LoanReAgeParameter reAgeParameter, LocalDate dueDate) {