diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 21c4fae08..4890a56aa 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -713,28 +713,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_ADDED, this); } - public ChangedTransactionDetail reprocessTransactions() { - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = getTransactionProcessor(); - final List allNonContraTransactionsPostDisbursement = retrieveListOfTransactionsForReprocessing(); - ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions( - getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), getRepaymentScheduleInstallments(), - getActiveCharges()); - for (TransactionChangeData change : changedTransactionDetail.getTransactionChanges()) { - change.getNewTransaction().updateLoan(this); - } - final List newTransactions = changedTransactionDetail.getTransactionChanges().stream() - .map(TransactionChangeData::getNewTransaction).toList(); - this.loanTransactions.addAll(newTransactions); - updateLoanSummaryDerivedFields(); - return changedTransactionDetail; - } - - public ChangedTransactionDetail reprocessTransactionsWithPostTransactionChecks(LocalDate transactionDate) { - ChangedTransactionDetail changedDetail = reprocessTransactions(); - doPostLoanTransactionChecks(transactionDate, loanLifecycleStateMachine); - return changedDetail; - } - /** * Creates a loanTransaction for "Apply Charge Event" with transaction date set to "suppliedTransactionDate". The * newly created transaction is also added to the Loan on which this method is called. @@ -832,34 +810,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { return lastRepaymentDate; } - public Optional removeLoanCharge(final LoanCharge loanCharge) { - final boolean removed = loanCharge.isActive(); - if (removed) { - loanCharge.setActive(false); - final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); - wrapper.reprocess(getCurrency(), getDisbursementDate(), getRepaymentScheduleInstallments(), getActiveCharges()); - updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); - } - - removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(loanCharge); - - if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(getCurrency())) { - /* - * TODO Vishwas Currently we do not allow removing a loan charge after a loan is approved (hence there is no - * need to adjust any loan transactions). - * - * Consider removing this block of code or logically completing it for the future by getting the list of - * affected Transactions - */ - return Optional.ofNullable(reprocessTransactions()); - } - this.charges.remove(loanCharge); - updateLoanSummaryDerivedFields(); - - return Optional.empty(); - } - - private void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) { + public void removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(final LoanCharge loanCharge) { if (loanCharge.isDueAtDisbursement()) { LoanTransaction transactionToRemove = null; List transactions = getLoanTransactions(); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsService.java index ed11c5ee7..936afb709 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsService.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsService.java @@ -28,7 +28,7 @@ public interface ReprocessLoanTransactionsService { void reprocessTransactions(Loan loan); - void reprocessTransactions(Loan loan, List loanTransactions); + void reprocessParticularTransactions(Loan loan, List loanTransactions); void reprocessTransactionsWithPostTransactionChecks(Loan loan, LocalDate transactionDate); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsServiceImpl.java index 334fedbc1..9d023d729 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ReprocessLoanTransactionsServiceImpl.java @@ -27,6 +27,7 @@ import org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountService; import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.LoanRepaymentScheduleTransactionProcessor; import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder; @@ -43,34 +44,24 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa @Override public void reprocessTransactions(final Loan loan) { - final ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactions(); - if (changedTransactionDetail != null) { - handleChangedDetail(changedTransactionDetail); - } + final List allNonContraTransactionsPostDisbursement = loan.retrieveListOfTransactionsForReprocessing(); + final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, + allNonContraTransactionsPostDisbursement); + handleChangedDetail(changedTransactionDetail); } @Override - public void reprocessTransactions(final Loan loan, final List loanTransactions) { - final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor(); - final ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions( - loan.getDisbursementDate(), loanTransactions, loan.getCurrency(), loan.getRepaymentScheduleInstallments(), - loan.getActiveCharges()); - for (TransactionChangeData change : changedTransactionDetail.getTransactionChanges()) { - change.getNewTransaction().updateLoan(loan); - } - final List newTransactions = changedTransactionDetail.getTransactionChanges().stream() - .map(TransactionChangeData::getNewTransaction).toList(); - loan.getLoanTransactions().addAll(newTransactions); - loan.updateLoanSummaryDerivedFields(); + public void reprocessParticularTransactions(final Loan loan, final List loanTransactions) { + final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, loanTransactions); handleChangedDetail(changedTransactionDetail); } @Override public void reprocessTransactionsWithPostTransactionChecks(final Loan loan, final LocalDate transactionDate) { - final ChangedTransactionDetail changedTransactionDetail = loan.reprocessTransactionsWithPostTransactionChecks(transactionDate); - if (changedTransactionDetail != null) { - handleChangedDetail(changedTransactionDetail); - } + final ChangedTransactionDetail changedTransactionDetail = reprocessTransactionsAndFetchChangedTransactions(loan, + loan.retrieveListOfTransactionsForReprocessing()); + loan.doPostLoanTransactionChecks(transactionDate, loan.getLoanLifecycleStateMachine()); + handleChangedDetail(changedTransactionDetail); } @Override @@ -80,7 +71,30 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa @Override public void removeLoanCharge(final Loan loan, final LoanCharge loanCharge) { - loan.removeLoanCharge(loanCharge).ifPresent(this::handleChangedDetail); + final boolean removed = loanCharge.isActive(); + if (removed) { + loanCharge.setActive(false); + final LoanRepaymentScheduleProcessingWrapper wrapper = new LoanRepaymentScheduleProcessingWrapper(); + wrapper.reprocess(loan.getCurrency(), loan.getDisbursementDate(), loan.getRepaymentScheduleInstallments(), + loan.getActiveCharges()); + loan.updateSummaryWithTotalFeeChargesDueAtDisbursement(loan.deriveSumTotalOfChargesDueAtDisbursement()); + } + + loan.removeOrModifyTransactionAssociatedWithLoanChargeIfDueAtDisbursement(loanCharge); + + if (!loanCharge.isDueAtDisbursement() && loanCharge.isPaidOrPartiallyPaid(loan.getCurrency())) { + /* + * TODO Vishwas Currently we do not allow removing a loan charge after a loan is approved (hence there is no + * need to adjust any loan transactions). + * + * Consider removing this block of code or logically completing it for the future by getting the list of + * affected Transactions + */ + reprocessTransactions(loan); + return; + } + loan.getLoanCharges().remove(loanCharge); + loan.updateLoanSummaryDerivedFields(); } @Override @@ -109,4 +123,20 @@ public class ReprocessLoanTransactionsServiceImpl implements ReprocessLoanTransa } replayedTransactionBusinessEventService.raiseTransactionReplayedEvents(changedTransactionDetail); } + + private ChangedTransactionDetail reprocessTransactionsAndFetchChangedTransactions(final Loan loan, + final List loanTransactions) { + final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = loan.getTransactionProcessor(); + final ChangedTransactionDetail changedTransactionDetail = loanRepaymentScheduleTransactionProcessor.reprocessLoanTransactions( + loan.getDisbursementDate(), loanTransactions, loan.getCurrency(), loan.getRepaymentScheduleInstallments(), + loan.getActiveCharges()); + for (TransactionChangeData change : changedTransactionDetail.getTransactionChanges()) { + change.getNewTransaction().updateLoan(loan); + } + final List newTransactions = changedTransactionDetail.getTransactionChanges().stream() + .map(TransactionChangeData::getNewTransaction).toList(); + loan.getLoanTransactions().addAll(newTransactions); + loan.updateLoanSummaryDerivedFields(); + return changedTransactionDetail; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 018c9255c..264046d73 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -2918,7 +2918,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } final List loanTransactions = loan.retrieveListOfTransactionsForReprocessing(); loanTransactions.add(chargeOffTransaction); - reprocessLoanTransactionsService.reprocessTransactions(loan, loanTransactions); + reprocessLoanTransactionsService.reprocessParticularTransactions(loan, loanTransactions); loan.addLoanTransaction(chargeOffTransaction); } else { reprocessLoanTransactionsService.processLatestTransaction(chargeOffTransaction, loan); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java index ea17d40e2..223dc4fdd 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java @@ -130,11 +130,11 @@ public class LoanReAmortizationServiceImpl { private void reverseReAmortizeTransaction(LoanTransaction reAmortizeTransaction, JsonCommand command) { ExternalId reversalExternalId = externalIdFactory.createFromCommand(command, LoanReAmortizationApiConstants.externalIdParameterName); - loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(reAmortizeTransaction.getLoan(), reAmortizeTransaction, - "reversed"); + final Loan loan = reAmortizeTransaction.getLoan(); + loanChargeValidator.validateRepaymentTypeTransactionNotBeforeAChargeRefund(loan, reAmortizeTransaction, "reversed"); reAmortizeTransaction.reverse(reversalExternalId); reAmortizeTransaction.manuallyAdjustedOrReversed(); - reprocessLoanTransactionsService.reprocessTransactions(reAmortizeTransaction.getLoan()); + reprocessLoanTransactionsService.reprocessTransactions(loan); } private LoanTransaction findLatestNonReversedReAmortizeTransaction(Loan loan) {