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
The following commit(s) were added to refs/heads/develop by this push:
new 071592eceb FINERACT-2220: Use stored
ProgressiveLoanInterestScheduleModel for Periodic Accrual Calculation
071592eceb is described below
commit 071592eceb4a920c0a198d3cd7d4b0dd9c8c5824
Author: Soma Sörös <[email protected]>
AuthorDate: Thu Apr 24 15:30:48 2025 +0200
FINERACT-2220: Use stored ProgressiveLoanInterestScheduleModel for Periodic
Accrual Calculation
---
.../service/LoanDownPaymentHandlerServiceImpl.java | 5 +++
...EmbeddableProgressiveLoanScheduleGenerator.java | 39 +++++++++++++++++++++-
.../domain/ProgressiveLoanScheduleGenerator.java | 16 +++++++--
.../domain/LoanScheduleGeneratorTest.java | 9 +++--
4 files changed, 63 insertions(+), 6 deletions(-)
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
index 8b984321bb..9b0a1d8304 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanDownPaymentHandlerServiceImpl.java
@@ -131,6 +131,11 @@ public class LoanDownPaymentHandlerServiceImpl implements
LoanDownPaymentHandler
||
!DateUtils.isEqualBusinessDate(loanTransaction.getTransactionDate()) ||
currentInstallment == null
||
!currentInstallment.getTotalOutstanding(loan.getCurrency()).isEqualTo(loanTransaction.getAmount(loan.getCurrency()));
+ // TODO FINERACT-2220 fix processLatestTransaction to save model.
+ if (loan.isProgressiveSchedule() && loan.isInterestBearing()) {
+ reprocess = true;
+ }
+
if (isTransactionChronologicallyLatest && adjustedTransaction == null
&& (!reprocess ||
!loan.isInterestBearingAndInterestRecalculationEnabled()) &&
!loan.isForeclosure()) {
loanTransactionProcessingService.processLatestTransaction(loan.getTransactionProcessingStrategyCode(),
loanTransaction,
diff --git
a/fineract-progressive-loan-embeddable-schedule-generator/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGenerator.java
b/fineract-progressive-loan-embeddable-schedule-generator/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGenerator.java
index 1b77749768..1c3a19bbd4 100644
---
a/fineract-progressive-loan-embeddable-schedule-generator/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGenerator.java
+++
b/fineract-progressive-loan-embeddable-schedule-generator/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGenerator.java
@@ -19,9 +19,16 @@
package org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
import java.math.MathContext;
+import java.time.LocalDate;
+import java.util.Optional;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.ProgressiveLoanModel;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlan;
+import
org.apache.fineract.portfolio.loanaccount.service.InterestScheduleModelRepositoryWrapper;
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
import org.apache.fineract.portfolio.loanproduct.calc.ProgressiveEMICalculator;
+import
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
+import
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
@SuppressWarnings("unused")
public class EmbeddableProgressiveLoanScheduleGenerator {
@@ -33,10 +40,40 @@ public class EmbeddableProgressiveLoanScheduleGenerator {
public EmbeddableProgressiveLoanScheduleGenerator() {
this.emiCalculator = new ProgressiveEMICalculator();
this.scheduledDateGenerator = new DefaultScheduledDateGenerator();
- this.scheduleGenerator = new
ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
+ this.scheduleGenerator = new
ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator,
+ new NoopInterestScheduleModelRepositoryWrapper());
}
public LoanSchedulePlan generate(final MathContext mc, final
LoanRepaymentScheduleModelData modelData) {
return scheduleGenerator.generate(mc, modelData);
}
+
+ private static final class NoopInterestScheduleModelRepositoryWrapper
implements InterestScheduleModelRepositoryWrapper {
+
+ @Override
+ public Optional<ProgressiveLoanModel> findOneByLoanId(Long loanId) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<ProgressiveLoanInterestScheduleModel>
extractModel(Optional<ProgressiveLoanModel> progressiveLoanModel) {
+ return Optional.empty();
+ }
+
+ @Override
+ public String writeInterestScheduleModel(Loan loan,
ProgressiveLoanInterestScheduleModel model) {
+ return "";
+ }
+
+ @Override
+ public Optional<ProgressiveLoanInterestScheduleModel>
readProgressiveLoanInterestScheduleModel(Long loanId,
+ LoanProductMinimumRepaymentScheduleRelatedDetail detail,
Integer installmentAmountInMultipliesOf) {
+ return Optional.empty();
+ }
+
+ @Override
+ public Optional<ProgressiveLoanInterestScheduleModel>
getSavedModel(Loan loan, LocalDate businessDate) {
+ return Optional.empty();
+ }
+ }
}
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
index caa7ea5edc..5e3f85ffd9 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
@@ -29,6 +29,7 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import org.apache.fineract.infrastructure.core.service.MathUtil;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
@@ -48,6 +49,7 @@ import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleM
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleParams;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlan;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.exception.MultiDisbursementOutstandingAmoutException;
+import
org.apache.fineract.portfolio.loanaccount.service.InterestScheduleModelRepositoryWrapper;
import
org.apache.fineract.portfolio.loanaccount.service.LoanTransactionProcessingService;
import org.apache.fineract.portfolio.loanproduct.calc.EMICalculator;
import org.apache.fineract.portfolio.loanproduct.calc.data.OutstandingDetails;
@@ -61,12 +63,15 @@ public class ProgressiveLoanScheduleGenerator implements
LoanScheduleGenerator {
private final ScheduledDateGenerator scheduledDateGenerator;
private final EMICalculator emiCalculator;
+ private final InterestScheduleModelRepositoryWrapper
interestScheduleModelRepositoryWrapper;
private LoanTransactionProcessingService loanTransactionProcessingService;
- public ProgressiveLoanScheduleGenerator(ScheduledDateGenerator
scheduledDateGenerator, EMICalculator emiCalculator) {
+ public ProgressiveLoanScheduleGenerator(ScheduledDateGenerator
scheduledDateGenerator, EMICalculator emiCalculator,
+ InterestScheduleModelRepositoryWrapper
interestScheduleModelRepositoryWrapper) {
this.scheduledDateGenerator = scheduledDateGenerator;
this.emiCalculator = emiCalculator;
+ this.interestScheduleModelRepositoryWrapper =
interestScheduleModelRepositoryWrapper;
}
@Autowired(required = false)
@@ -187,7 +192,10 @@ public class ProgressiveLoanScheduleGenerator implements
LoanScheduleGenerator {
case NONE -> throw new IllegalStateException("Unexpected
PreClosureInterestCalculationStrategy: NONE");
};
- ProgressiveLoanInterestScheduleModel model =
processor.calculateInterestScheduleModel(loan.getId(), onDate);
+ Optional<ProgressiveLoanInterestScheduleModel> savedModel =
interestScheduleModelRepositoryWrapper.getSavedModel(loan,
+ transactionDate);
+ ProgressiveLoanInterestScheduleModel model = savedModel
+ .orElseGet(() ->
processor.calculateInterestScheduleModel(loan.getId(), onDate));
OutstandingDetails outstandingAmounts =
emiCalculator.getOutstandingAmountsTillDate(model, transactionDate);
// TODO: We should add all the past due outstanding amounts as well
OutstandingAmountsDTO result = new OutstandingAmountsDTO(currency) //
@@ -228,7 +236,9 @@ public class ProgressiveLoanScheduleGenerator implements
LoanScheduleGenerator {
if (installment.isAdditional() || installment.isDownPayment() ||
installment.isReAged()) {
return Money.zero(loan.getCurrency());
}
- ProgressiveLoanInterestScheduleModel model =
processor.calculateInterestScheduleModel(loan.getId(), targetDate);
+ Optional<ProgressiveLoanInterestScheduleModel> savedModel =
interestScheduleModelRepositoryWrapper.getSavedModel(loan, targetDate);
+ ProgressiveLoanInterestScheduleModel model = savedModel
+ .orElseGet(() ->
processor.calculateInterestScheduleModel(loan.getId(), targetDate));
return emiCalculator.getPeriodInterestTillDate(model,
installment.getDueDate(), targetDate, false);
}
diff --git
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
index e56927d6b8..552c52c80d 100644
---
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
+++
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleGeneratorTest.java
@@ -33,6 +33,7 @@ import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleP
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanDisbursementPeriod;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanDownPaymentPeriod;
import
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePlanRepaymentPeriod;
+import
org.apache.fineract.portfolio.loanaccount.service.InterestScheduleModelRepositoryWrapper;
import
org.apache.fineract.portfolio.loanaccount.service.LoanTransactionProcessingService;
import org.apache.fineract.portfolio.loanproduct.calc.ProgressiveEMICalculator;
import org.junit.jupiter.api.Test;
@@ -55,6 +56,8 @@ class LoanScheduleGeneratorTest {
private static final MathContext mc = new MathContext(12,
RoundingMode.HALF_EVEN);
private static final BigDecimal DOWN_PAYMENT_PORTION =
BigDecimal.valueOf(25);
private static final LoanTransactionProcessingService
loanTransactionProcessingService = mock(LoanTransactionProcessingService.class);
+ private static final InterestScheduleModelRepositoryWrapper
interestScheduleModelRepositoryWrapperMock = mock(
+ InterestScheduleModelRepositoryWrapper.class);
@Test
void testGenerateLoanSchedule() {
@@ -63,7 +66,8 @@ class LoanScheduleGeneratorTest {
NOMINAL_INTEREST_RATE, false, DaysInMonthType.DAYS_30,
DaysInYearType.DAYS_360, null, null, null, false, null);
ScheduledDateGenerator scheduledDateGenerator = new
DefaultScheduledDateGenerator();
- ProgressiveLoanScheduleGenerator generator = new
ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
+ ProgressiveLoanScheduleGenerator generator = new
ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator,
+ interestScheduleModelRepositoryWrapperMock);
generator.setLoanTransactionProcessingService(loanTransactionProcessingService);
LoanSchedulePlan loanSchedule = generator.generate(mc, modelData);
@@ -100,7 +104,8 @@ class LoanScheduleGeneratorTest {
null);
ScheduledDateGenerator scheduledDateGenerator = new
DefaultScheduledDateGenerator();
- ProgressiveLoanScheduleGenerator generator = new
ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator);
+ ProgressiveLoanScheduleGenerator generator = new
ProgressiveLoanScheduleGenerator(scheduledDateGenerator, emiCalculator,
+ interestScheduleModelRepositoryWrapperMock);
generator.setLoanTransactionProcessingService(loanTransactionProcessingService);
LoanSchedulePlan loanSchedule = generator.generate(mc, modelData);