This is an automated email from the ASF dual-hosted git repository. adamsaghy pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 2ee19f9825894a66ce5b98bb8fa134a790c5b62f Author: Soma Sörös <[email protected]> AuthorDate: Wed Jan 28 15:48:43 2026 +0100 FINERACT-2413: Allow multiple Re-amortization on a loan account --- .../reamortization/LoanReAmortizationService.java | 2 +- .../LoanReAmortizationValidator.java | 33 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationService.java index 1311e0deb1..73ad6bfd11 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationService.java @@ -150,7 +150,7 @@ public class LoanReAmortizationService { } private LoanScheduleData previewReAmortization(final Loan loan, final ReAmortizationPreviewRequest reAmortizationPreviewRequest) { - reAmortizationValidator.validateReAmortize(loan); + reAmortizationValidator.validateReAmortize(loan, reAmortizationPreviewRequest); final LoanTransaction reAmortizeTransaction = createReAmortizeTransactionFromPreviewRequest(loan, reAmortizationPreviewRequest); processReAmortizationTransaction(loan, reAmortizeTransaction, false); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationValidator.java index 5faeed9141..b535721e6d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationValidator.java @@ -34,9 +34,11 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants; import org.apache.fineract.portfolio.loanaccount.api.LoanReAmortizationApiConstants; +import org.apache.fineract.portfolio.loanaccount.api.request.ReAmortizationPreviewRequest; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; import org.apache.fineract.portfolio.loanaccount.domain.reamortization.LoanReAmortizationInterestHandlingType; +import org.apache.fineract.portfolio.loanaccount.domain.reamortization.LoanReAmortizationParameter; import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType; import org.springframework.stereotype.Component; @@ -49,11 +51,9 @@ public class LoanReAmortizationValidator { public void validateReAmortize(Loan loan, JsonCommand command) { validateReAmortizeRequest(command); - validateReAmortizeBusinessRules(loan); - } - - public void validateReAmortize(final Loan loan) { - validateReAmortizeBusinessRules(loan); + LoanReAmortizationInterestHandlingType interestHandlingType = command.enumValueOfParameterNamed( + LoanReAmortizationApiConstants.reAmortizationInterestHandlingParamName, LoanReAmortizationInterestHandlingType.class); + validateReAmortizeBusinessRules(loan, interestHandlingType); } private void validateReAmortizeRequest(JsonCommand command) { @@ -84,7 +84,7 @@ public class LoanReAmortizationValidator { throwExceptionIfValidationErrorsExist(dataValidationErrors); } - private void validateReAmortizeBusinessRules(Loan loan) { + private void validateReAmortizeBusinessRules(Loan loan, LoanReAmortizationInterestHandlingType interestHandlingType) { // validate reamortization shouldn't happen after maturity if (DateUtils.isAfter(getBusinessLocalDate(), loan.getMaturityDate())) { throw new GeneralPlatformDomainRuleException("error.msg.loan.reamortize.cannot.be.submitted.after.maturity", @@ -120,6 +120,22 @@ public class LoanReAmortizationValidator { loan.getId()); } + // validate if there is active re-amortization transaction, it should have the same interest handling strategy + Optional<LoanTransaction> previousReAmortizationTransaction = loan.getLoanTransactions().stream() + .filter(LoanTransaction::isNotReversed).filter(LoanTransaction::isReAmortize).findAny(); + if (previousReAmortizationTransaction.isPresent()) { + LoanReAmortizationInterestHandlingType previousInterestHandlingType = Optional + .ofNullable(previousReAmortizationTransaction.get().getLoanReAmortizationParameter()) + .map(LoanReAmortizationParameter::getInterestHandlingType).orElse(LoanReAmortizationInterestHandlingType.DEFAULT); + LoanReAmortizationInterestHandlingType currentInterestHandlingType = Optional.ofNullable(interestHandlingType) + .orElse(LoanReAmortizationInterestHandlingType.DEFAULT); + if (!previousInterestHandlingType.equals(currentInterestHandlingType)) { + throw new GeneralPlatformDomainRuleException( + "error.msg.loan.reamortize.reamortize.transaction.interest.handling.strategy.missmatch", + "Previous active reamortization transactiuon has different interest handling strategy.", loan.getId()); + } + } + // validate loan is not charged-off if (loan.isChargedOff()) { throw new GeneralPlatformDomainRuleException("error.msg.loan.reamortize.not.allowed.on.charged.off", @@ -163,4 +179,9 @@ public class LoanReAmortizationValidator { } } + public void validateReAmortize(Loan loan, ReAmortizationPreviewRequest reAmortizationPreviewRequest) { + LoanReAmortizationInterestHandlingType interestHandlingType = LoanReAmortizationInterestHandlingType + .valueOf(reAmortizationPreviewRequest.getReAmortizationInterestHandling()); + validateReAmortizeBusinessRules(loan, interestHandlingType); + } }
