From 3829c4404f4d1c23eb5f6d239dd0ff200ab68b25 Mon Sep 17 00:00:00 2001 From: "mark.vituska" Date: Thu, 19 Jun 2025 13:57:10 +0200 Subject: [PATCH] FINERACT-2181: ensure loan transactions are saved and linked to loan object consistently across business steps --- .../domain/LoanAccountDomainServiceJpa.java | 5 ++-- ...nAccrualActivityProcessingServiceImpl.java | 11 +++++---- .../LoanAccrualsProcessingServiceImpl.java | 24 ++++++++++++------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 08f66a085..c546060ab 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -809,8 +809,9 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { } for (LoanTransaction newTransaction : newTransactions) { - loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newTransaction); - transactionIds.add(newTransaction.getId()); + LoanTransaction savedNewTransaction = loanAccountService.saveLoanTransactionWithDataIntegrityViolationChecks(newTransaction); + loan.addLoanTransaction(savedNewTransaction); + transactionIds.add(savedNewTransaction.getId()); } changes.put("transactions", transactionIds); changes.put("eventAmount", payPrincipal.getAmount().negate()); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java index c30ea365b..d069b352f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java @@ -274,16 +274,19 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi transactionDate); if (newAccrualActivityTransaction != null) { - makeAccrualActivityTransaction(loan, newAccrualActivityTransaction); + LoanTransaction savedNewTransaction = makeAccrualActivityTransaction(loan, newAccrualActivityTransaction); + loan.addLoanTransaction(savedNewTransaction); } } - private void makeAccrualActivityTransaction(final @NonNull Loan loan, @NonNull LoanTransaction newAccrualActivityTransaction) { + private LoanTransaction makeAccrualActivityTransaction(final @NonNull Loan loan, + @NonNull LoanTransaction newAccrualActivityTransaction) { businessEventNotifierService.notifyPreBusinessEvent(new LoanTransactionAccrualActivityPreBusinessEvent(loan)); - newAccrualActivityTransaction = loanAccountService + LoanTransaction savedNewAccrualActivityTransaction = loanAccountService .saveLoanTransactionWithDataIntegrityViolationChecks(newAccrualActivityTransaction); businessEventNotifierService - .notifyPostBusinessEvent(new LoanTransactionAccrualActivityPostBusinessEvent(newAccrualActivityTransaction)); + .notifyPostBusinessEvent(new LoanTransactionAccrualActivityPostBusinessEvent(savedNewAccrualActivityTransaction)); + return savedNewAccrualActivityTransaction; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java index d3289ed6d..c3534e441 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java @@ -678,9 +678,9 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing // update repayment schedule portions addTransactionMappings(transaction, accrualPeriod, adjustment); - loanTransactionRepository.save(transaction); - - return transaction; + LoanTransaction savedTransaction = loanTransactionRepository.save(transaction); + loan.addLoanTransaction(savedTransaction); + return savedTransaction; } private void mergeAccrualTransaction(@NotNull final LoanTransaction transaction, final AccrualPeriodData accrualPeriod, @@ -825,7 +825,8 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing } final LoanTransaction interestAccrualTransaction = LoanTransaction.accrueInterest(loan.getOffice(), loan, interestApplied, loan.getDisbursementDate(), externalId); - loanTransactionRepository.save(interestAccrualTransaction); + LoanTransaction savedInterestAccrualTransaction = loanTransactionRepository.save(interestAccrualTransaction); + loan.addLoanTransaction(savedInterestAccrualTransaction); } } else { Set chargePaidBies = accrualTransaction.getLoanChargesPaid(); @@ -940,12 +941,14 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing if (incomeTransaction.isEmpty()) { LoanTransaction transaction = LoanTransaction.incomePosting(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(), compoundingDetail.getAmount(), interest, fee, penalties, externalId); - loanTransactionRepository.save(transaction); + LoanTransaction savedTransaction = loanTransactionRepository.save(transaction); + loan.addLoanTransaction(savedTransaction); } else if (incomeTransaction.get().getAmount(loan.getCurrency()).getAmount().compareTo(compoundingDetail.getAmount()) != 0) { incomeTransaction.get().reverse(); LoanTransaction transaction = LoanTransaction.incomePosting(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(), compoundingDetail.getAmount(), interest, fee, penalties, externalId); - loanTransactionRepository.save(transaction); + LoanTransaction savedTransaction = loanTransactionRepository.save(transaction); + loan.addLoanTransaction(savedTransaction); } } @@ -964,7 +967,8 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing LoanTransaction accrual = LoanTransaction.accrueTransaction(loan, loan.getOffice(), compoundingDetail.getEffectiveDate(), compoundingDetail.getAmount(), interest, fee, penalties, externalId); updateLoanChargesPaidBy(loan, accrual, feeDetails, null); - loanTransactionRepository.save(accrual); + LoanTransaction savedAccrual = loanTransactionRepository.save(accrual); + loan.addLoanTransaction(savedAccrual); } } } @@ -1025,7 +1029,8 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing } LoanTransaction finalIncomeTransaction = LoanTransaction.incomePosting(loan, loan.getOffice(), closedDate, amountToPost, interestToPost, feeToPost, penaltyToPost, externalId); - loanTransactionRepository.save(finalIncomeTransaction); + LoanTransaction savedFinalIncomeTransaction = loanTransactionRepository.save(finalIncomeTransaction); + loan.addLoanTransaction(savedFinalIncomeTransaction); if (loan.isPeriodicAccrualAccountingEnabledOnLoanProduct()) { final LocalDate lastAccruedDate = loanTransactionRepository @@ -1040,7 +1045,8 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing LoanTransaction finalAccrual = LoanTransaction.accrueTransaction(loan, loan.getOffice(), closedDate, amountToPost, interestToPost, feeToPost, penaltyToPost, externalId); updateLoanChargesPaidBy(loan, finalAccrual, feeDetails, null); - loanTransactionRepository.save(finalAccrual); + LoanTransaction savedFinalAccrual = loanTransactionRepository.save(finalAccrual); + loan.addLoanTransaction(savedFinalAccrual); } }