FINERACT-2220: Use stored ProgressiveLoanInterestScheduleModel for processLatestTransaction if applicable

This commit is contained in:
Soma Sörös
2025-05-16 10:03:54 +02:00
committed by Adam Saghy
parent 1fc2aae654
commit cd03dc020e
9 changed files with 129 additions and 51 deletions
@@ -1225,6 +1225,10 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
adjustOverduePrincipalForInstallment(targetDate, currentInstallment, overDuePrincipal, aggregatedOverDuePrincipal,
ctx);
}
if (aggregatedOverDuePrincipal.isGreaterThanZero() && (ctx.getModel().lastOverdueBalanceChange() == null
|| ctx.getModel().lastOverdueBalanceChange().isBefore(targetDate))) {
ctx.getModel().lastOverdueBalanceChange(targetDate);
}
}
}
}
@@ -47,8 +47,14 @@ public class ProgressiveTransactionCtx extends TransactionCtx {
public ProgressiveTransactionCtx(MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments,
Set<LoanCharge> charges, MoneyHolder overpaymentHolder, ChangedTransactionDetail changedTransactionDetail,
ProgressiveLoanInterestScheduleModel model) {
this(currency, installments, charges, overpaymentHolder, changedTransactionDetail, model, Money.zero(currency));
}
public ProgressiveTransactionCtx(MonetaryCurrency currency, List<LoanRepaymentScheduleInstallment> installments,
Set<LoanCharge> charges, MoneyHolder overpaymentHolder, ChangedTransactionDetail changedTransactionDetail,
ProgressiveLoanInterestScheduleModel model, Money sumOfInterestRefundAmount) {
super(currency, installments, charges, overpaymentHolder, changedTransactionDetail);
sumOfInterestRefundAmount = model.zero();
this.sumOfInterestRefundAmount = sumOfInterestRefundAmount;
this.model = model;
}
}
@@ -36,5 +36,7 @@ public interface InterestScheduleModelRepositoryWrapper {
Optional<ProgressiveLoanInterestScheduleModel> readProgressiveLoanInterestScheduleModel(Long loanId,
LoanProductMinimumRepaymentScheduleRelatedDetail detail, Integer installmentAmountInMultipliesOf);
boolean hasValidModelForDate(Long loanId, LocalDate targetDate);
Optional<ProgressiveLoanInterestScheduleModel> getSavedModel(Loan loan, LocalDate businessDate);
}
@@ -58,6 +58,7 @@ public class InterestScheduleModelRepositoryWrapperImpl implements InterestSched
}
String jsonModel = progressiveLoanInterestScheduleModelParserService.toJson(model);
try {
// Note: FlushMode set because otherwise it could cause a concurrent writing exception
entityManager.setFlushMode(FlushModeType.COMMIT);
ProgressiveLoanModel progressiveLoanModel = loanModelRepository.findOneByLoanId(loan.getId()).orElseGet(() -> {
ProgressiveLoanModel plm = new ProgressiveLoanModel();
@@ -88,21 +89,41 @@ public class InterestScheduleModelRepositoryWrapperImpl implements InterestSched
}
@Override
public boolean hasValidModelForDate(Long loanId, LocalDate targetDate) {
try {
// Note: FlushMode set because an unwanted flush caused reverse replay new transactions
entityManager.setFlushMode(FlushModeType.COMMIT);
Optional<ProgressiveLoanModel> progressiveLoanModel = findOneByLoanId(loanId);
LocalDate modelUpdatedTilDate = progressiveLoanModel.map(ProgressiveLoanModel::getBusinessDate).orElse(null);
return progressiveLoanModel.isPresent() && !targetDate.isBefore(modelUpdatedTilDate);
} finally {
entityManager.setFlushMode(FlushModeType.AUTO);
}
}
@Override
public Optional<ProgressiveLoanInterestScheduleModel> getSavedModel(Loan loan, LocalDate businessDate) {
Optional<ProgressiveLoanModel> progressiveLoanModel = findOneByLoanId(loan.getId());
Optional<ProgressiveLoanInterestScheduleModel> savedModel;
if (progressiveLoanModel.isPresent() && !progressiveLoanModel.get().getBusinessDate().isAfter(businessDate)) {
savedModel = extractModel(progressiveLoanModel);
if (progressiveLoanModel.get().getBusinessDate().isBefore(businessDate) && savedModel.isPresent()) {
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(loan.getCurrency(), loan.getRepaymentScheduleInstallments(),
Set.of(), new MoneyHolder(loan.getTotalOverpaidAsMoney()), new ChangedTransactionDetail(), savedModel.get());
ctx.setChargedOff(loan.isChargedOff());
advancedPaymentScheduleTransactionProcessor.recalculateInterestForDate(businessDate, ctx);
try {
// Note: FlushMode set because an unwanted flush caused reverse replay new transactions
entityManager.setFlushMode(FlushModeType.COMMIT);
Optional<ProgressiveLoanModel> progressiveLoanModel = findOneByLoanId(loan.getId());
Optional<ProgressiveLoanInterestScheduleModel> savedModel;
if (progressiveLoanModel.isPresent() && !progressiveLoanModel.get().getBusinessDate().isAfter(businessDate)) {
savedModel = extractModel(progressiveLoanModel);
if (savedModel.isPresent() && progressiveLoanModel.get().getBusinessDate().isBefore(businessDate)) {
ProgressiveTransactionCtx ctx = new ProgressiveTransactionCtx(loan.getCurrency(),
loan.getRepaymentScheduleInstallments(), Set.of(), new MoneyHolder(loan.getTotalOverpaidAsMoney()),
new ChangedTransactionDetail(), savedModel.get());
ctx.setChargedOff(loan.isChargedOff());
advancedPaymentScheduleTransactionProcessor.recalculateInterestForDate(businessDate, ctx);
}
} else {
savedModel = Optional.empty();
}
} else {
savedModel = Optional.empty();
return savedModel;
} finally {
entityManager.setFlushMode(FlushModeType.AUTO);
}
return savedModel;
}
@Override