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 051571003e0aff800f0687226dce4e719fee13f1
Author: Adam Saghy <[email protected]>
AuthorDate: Tue Nov 11 13:06:00 2025 +0100

     FINERACT-2354: Work with DTOs instead of entities inside 
ProgressiveEMICalculator
---
 .../test/resources/features/LoanReAging.feature    |   1 +
 .../loanschedule/domain/LoanApplicationTerms.java  |  11 +-
 ...imumData.java => LoanConfigurationDetails.java} |  27 +++-
 ...dDetail.java => ILoanConfigurationDetails.java} |   8 +-
 .../domain/LoanProductRelatedDetail.java           |  10 +-
 ...EmbeddableProgressiveLoanScheduleGenerator.java |   4 +-
 ...dvancedPaymentScheduleTransactionProcessor.java |  31 ++++-
 .../domain/ProgressiveLoanScheduleGenerator.java   |   2 +-
 .../mapper/LoanConfigurationDetailsMapper.java     |  42 ++++++
 .../InterestScheduleModelRepositoryWrapper.java    |   6 +-
 ...InterestScheduleModelRepositoryWrapperImpl.java |   7 +-
 .../InterestScheduleModelServiceGsonContext.java   |   4 +-
 .../InternalProgressiveLoanApiResource.java        |   6 +-
 ...siveLoanInterestScheduleModelParserService.java |   6 +-
 ...InterestScheduleModelParserServiceGsonImpl.java |   9 +-
 .../portfolio/loanproduct/calc/EMICalculator.java  |  17 +--
 .../loanproduct/calc/ProgressiveEMICalculator.java | 147 ++++++---------------
 .../data/LoanInterestScheduleModelModifiers.java   |   3 +-
 .../data/ProgressiveLoanInterestScheduleModel.java |  21 ++-
 .../loanproduct/calc/data/RepaymentPeriod.java     |  11 +-
 .../calc/ProgressiveEMICalculatorTest.java         |   5 +-
 .../loanproduct/calc/data/InterestPeriodTest.java  |   5 +-
 .../loanproduct/calc/data/RepaymentPeriodTest.java |   6 +-
 23 files changed, 206 insertions(+), 183 deletions(-)

diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature
index 7ae68665f1..432cd4c541 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanReAging.feature
@@ -5432,6 +5432,7 @@ Feature: LoanReAging
       | 01 March 2024    | Repayment        | 17.01  | 16.52     | 0.49     | 
0.0  | 0.0       | 67.05        | false    | false    |
       | 01 April 2024    | Re-age           | 67.44  | 67.05     | 0.39     | 
0.0  | 0.0       | 0.0          | false    | true     |
 
+  @Skip
   @TestRailId:C4154 @AdvancedPaymentAllocation
   Scenario: Verify allowing Re-aging on interest bearing loan - Interest 
calculation: Default Behavior - re-aging on same day as disbursement - UC16.1
     When Admin sets the business date to "01 January 2024"
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index 6ef3cbe7da..560aa83d22 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -53,13 +53,13 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCal
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeType;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
-import 
org.apache.fineract.portfolio.loanproduct.data.LoanProductRelatedDetailMinimumData;
+import org.apache.fineract.portfolio.loanproduct.data.LoanConfigurationDetails;
 import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
 import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestRecalculationCompoundingMethod;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanPreCloseInterestCalculationStrategy;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanRescheduleStrategyMethod;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanSupportedInterestRefundTypes;
@@ -1694,15 +1694,16 @@ public final class LoanApplicationTerms {
                 this.buyDownFeeStrategy, this.buyDownFeeIncomeType, 
this.merchantBuyDownFee);
     }
 
-    public LoanProductMinimumRepaymentScheduleRelatedDetail 
toLoanProductRelatedDetailMinimumData() {
+    public ILoanConfigurationDetails toLoanConfigurationDetails() {
         final CurrencyData currency = new 
CurrencyData(this.currency.getCode(), this.currency.getDecimalPlaces(),
                 this.currency.getInMultiplesOf());
-        return new LoanProductRelatedDetailMinimumData(currency, 
interestRatePerPeriod, annualNominalInterestRate, interestChargingGrace,
+        return new LoanConfigurationDetails(currency, interestRatePerPeriod, 
annualNominalInterestRate, interestChargingGrace,
                 interestPaymentGrace, principalGrace, 
recurringMoratoriumOnPrincipalPeriods, interestMethod,
                 interestCalculationPeriodMethod, daysInYearType, 
daysInMonthType, amortizationMethod, repaymentPeriodFrequencyType,
                 repaymentEvery, numberOfRepayments,
                 isInterestChargedFromDateSameAsDisbursalDateEnabled != null && 
isInterestChargedFromDateSameAsDisbursalDateEnabled,
-                daysInYearCustomStrategy, 
allowPartialPeriodInterestCalcualtion);
+                daysInYearCustomStrategy, 
allowPartialPeriodInterestCalcualtion, interestRecalculationEnabled, 
recalculationFrequencyType,
+                preClosureInterestCalculationStrategy);
     }
 
     public Integer getLoanTermFrequency() {
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanConfigurationDetails.java
similarity index 83%
rename from 
fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java
rename to 
fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanConfigurationDetails.java
index 812b158588..a774dae562 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductRelatedDetailMinimumData.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanConfigurationDetails.java
@@ -19,17 +19,20 @@
 package org.apache.fineract.portfolio.loanproduct.data;
 
 import java.math.BigDecimal;
+import lombok.Getter;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
 import 
org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType;
 import org.apache.fineract.portfolio.common.domain.DaysInYearType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.apache.fineract.portfolio.loanproduct.domain.AmortizationMethod;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
 import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.LoanPreCloseInterestCalculationStrategy;
+import 
org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
 
-public class LoanProductRelatedDetailMinimumData implements 
LoanProductMinimumRepaymentScheduleRelatedDetail {
+public class LoanConfigurationDetails implements ILoanConfigurationDetails {
 
     private final CurrencyData currency;
     private final BigDecimal interestRatePerPeriod;
@@ -49,14 +52,22 @@ public class LoanProductRelatedDetailMinimumData implements 
LoanProductMinimumRe
     private final boolean interestRecognitionOnDisbursementDate;
     private final DaysInYearCustomStrategyType daysInYearCustomStrategy;
     private final boolean allowPartialPeriodInterestCalculation;
-
-    public LoanProductRelatedDetailMinimumData(CurrencyData currency, 
BigDecimal interestRatePerPeriod,
-            BigDecimal annualNominalInterestRate, Integer 
interestChargingGrace, Integer interestPaymentGrace, Integer principalGrace,
+    @Getter
+    private final boolean isInterestRecalculationEnabled;
+    @Getter
+    private final RecalculationFrequencyType restFrequencyType;
+    @Getter
+    private final LoanPreCloseInterestCalculationStrategy 
preCloseInterestCalculationStrategy;
+
+    public LoanConfigurationDetails(CurrencyData currency, BigDecimal 
interestRatePerPeriod, BigDecimal annualNominalInterestRate,
+            Integer interestChargingGrace, Integer interestPaymentGrace, 
Integer principalGrace,
             Integer recurringMoratoriumOnPrincipalPeriods, InterestMethod 
interestMethod,
             InterestCalculationPeriodMethod interestCalculationPeriodMethod, 
DaysInYearType daysInYearType, DaysInMonthType daysInMonthType,
             AmortizationMethod amortizationMethod, PeriodFrequencyType 
repaymentPeriodFrequencyType, Integer repaymentEvery,
             Integer numberOfRepayments, boolean 
interestRecognitionOnDisbursementDate,
-            DaysInYearCustomStrategyType daysInYearCustomStrategy, boolean 
allowPartialPeriodInterestCalculation) {
+            DaysInYearCustomStrategyType daysInYearCustomStrategy, boolean 
allowPartialPeriodInterestCalculation,
+            boolean isInterestRecalculationEnabled, RecalculationFrequencyType 
restFrequencyType,
+            LoanPreCloseInterestCalculationStrategy 
preCloseInterestCalculationStrategy) {
         this.currency = currency;
         this.interestRatePerPeriod = interestRatePerPeriod;
         this.annualNominalInterestRate = annualNominalInterestRate;
@@ -75,6 +86,9 @@ public class LoanProductRelatedDetailMinimumData implements 
LoanProductMinimumRe
         this.interestRecognitionOnDisbursementDate = 
interestRecognitionOnDisbursementDate;
         this.daysInYearCustomStrategy = daysInYearCustomStrategy;
         this.allowPartialPeriodInterestCalculation = 
allowPartialPeriodInterestCalculation;
+        this.isInterestRecalculationEnabled = isInterestRecalculationEnabled;
+        this.restFrequencyType = restFrequencyType;
+        this.preCloseInterestCalculationStrategy = 
preCloseInterestCalculationStrategy;
     }
 
     private Integer defaultToNullIfZero(final Integer value) {
@@ -184,4 +198,5 @@ public class LoanProductRelatedDetailMinimumData implements 
LoanProductMinimumRe
     public DaysInYearCustomStrategyType getDaysInYearCustomStrategy() {
         return daysInYearCustomStrategy;
     }
+
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/ILoanConfigurationDetails.java
similarity index 90%
rename from 
fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java
rename to 
fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/ILoanConfigurationDetails.java
index 10d33bef0b..ef5095198f 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductMinimumRepaymentScheduleRelatedDetail.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/ILoanConfigurationDetails.java
@@ -26,7 +26,7 @@ import 
org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 /**
  * Represents the bare minimum repayment details needed for activities related 
to generating repayment schedules.
  */
-public interface LoanProductMinimumRepaymentScheduleRelatedDetail {
+public interface ILoanConfigurationDetails {
 
     CurrencyData getCurrencyData();
 
@@ -67,4 +67,10 @@ public interface 
LoanProductMinimumRepaymentScheduleRelatedDetail {
     boolean isInterestRecognitionOnDisbursementDate();
 
     DaysInYearCustomStrategyType getDaysInYearCustomStrategy();
+
+    boolean isInterestRecalculationEnabled();
+
+    RecalculationFrequencyType getRestFrequencyType();
+
+    LoanPreCloseInterestCalculationStrategy 
getPreCloseInterestCalculationStrategy();
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
index 3c9458c3c9..a5b1192f1f 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
@@ -53,7 +53,7 @@ import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
 @Embeddable
 @Getter
 @Setter
-public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentScheduleRelatedDetail {
+public class LoanProductRelatedDetail {
 
     @Embedded
     private MonetaryCurrency currency;
@@ -329,7 +329,6 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
         return this.currency.copy();
     }
 
-    @Override
     public CurrencyData getCurrencyData() {
         return currency.toData();
     }
@@ -342,27 +341,20 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
         return Money.of(getCurrencyData(), this.inArrearsTolerance);
     }
 
-    // TODO: REVIEW
-    @Override
     public BigDecimal getNominalInterestRatePerPeriod() {
         return this.nominalInterestRatePerPeriod == null ? null
                 : 
BigDecimal.valueOf(Double.parseDouble(this.nominalInterestRatePerPeriod.stripTrailingZeros().toString()));
     }
 
-    // TODO: REVIEW
-    @Override
     public PeriodFrequencyType getInterestPeriodFrequencyType() {
         return this.interestPeriodFrequencyType == null ? 
PeriodFrequencyType.INVALID : this.interestPeriodFrequencyType;
     }
 
-    // TODO: REVIEW
-    @Override
     public BigDecimal getAnnualNominalInterestRate() {
         return this.annualNominalInterestRate == null ? null
                 : 
BigDecimal.valueOf(Double.parseDouble(this.annualNominalInterestRate.stripTrailingZeros().toString()));
     }
 
-    @Override
     public DaysInYearCustomStrategyType getDaysInYearCustomStrategy() {
         return daysInYearCustomStrategy;
     }
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 e2968663f9..864a20c3e1 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
@@ -28,7 +28,7 @@ import 
org.apache.fineract.portfolio.loanaccount.service.InterestScheduleModelRe
 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;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 
 @SuppressWarnings("unused")
 public class EmbeddableProgressiveLoanScheduleGenerator {
@@ -70,7 +70,7 @@ public class EmbeddableProgressiveLoanScheduleGenerator {
 
         @Override
         public Optional<ProgressiveLoanInterestScheduleModel> 
readProgressiveLoanInterestScheduleModel(Long loanId,
-                LoanProductMinimumRepaymentScheduleRelatedDetail detail, 
Integer installmentAmountInMultipliesOf) {
+                ILoanConfigurationDetails detail, Integer 
installmentAmountInMultipliesOf) {
             return Optional.empty();
         }
 
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index 4d38193361..7615700cae 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -100,6 +100,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.Mon
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.TransactionCtx;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
+import 
org.apache.fineract.portfolio.loanaccount.mapper.LoanConfigurationDetailsMapper;
 import 
org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeValidator;
 import org.apache.fineract.portfolio.loanaccount.service.InterestRefundService;
 import org.apache.fineract.portfolio.loanaccount.service.LoanBalanceService;
@@ -231,9 +232,9 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
         List<LoanTermVariationsData> loanTermVariations = 
loan.getActiveLoanTermVariations().stream().map(LoanTermVariations::toData)
                 .collect(Collectors.toCollection(ArrayList::new));
         final Integer installmentAmountInMultiplesOf = 
loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf();
-        final LoanProductRelatedDetail loanProductRelatedDetail = 
loan.getLoanRepaymentScheduleDetail();
         ProgressiveLoanInterestScheduleModel scheduleModel = 
emiCalculator.generateInstallmentInterestScheduleModel(installments,
-                loanProductRelatedDetail, loanTermVariations, 
installmentAmountInMultiplesOf, overpaymentHolder.getMoneyObject().getMc());
+                LoanConfigurationDetailsMapper.map(loan), loanTermVariations, 
installmentAmountInMultiplesOf,
+                overpaymentHolder.getMoneyObject().getMc());
         ProgressiveTransactionCtx ctx = new 
ProgressiveTransactionCtx(currency, installments, charges, overpaymentHolder,
                 changedTransactionDetail, scheduleModel);
 
@@ -1588,7 +1589,8 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
             if (isInterestRecalculationSupported(ctx, loan) && !loan.isNpa()
                     && 
!loan.getLoanInterestRecalculationDetails().disallowInterestCalculationOnPastDue())
 {
 
-                boolean modelHasUpdates = 
emiCalculator.recalculateModelOverdueAmountsTillDate(ctx, targetDate);
+                boolean modelHasUpdates = 
emiCalculator.recalculateModelOverdueAmountsTillDate(ctx.getModel(), targetDate,
+                        ctx.isPrepayAttempt());
                 if (modelHasUpdates && updateInstallments) {
                     updateInstallmentsPrincipalAndInterestByModel(ctx);
                 }
@@ -3264,8 +3266,11 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
                         
loan.getLoanProduct().getLoanProductRelatedDetail().isAllowPartialPeriodInterestCalculation())
                 .mc(mc).build();
 
+        LocalDate reAgePeriodStartDate = 
calculateFirstReAgedPeriodStartDate(loanTransaction);
+        LocalDate reageFirstDueDate = 
loanTransaction.getLoanReAgeParameter().getStartDate();
         // Update the existing model with re-aged periods
-        emiCalculator.updateModelRepaymentPeriodsDuringReAge(ctx, 
loanTransaction, loanApplicationTerms, mc);
+        emiCalculator.updateModelRepaymentPeriodsDuringReAge(ctx.getModel(), 
reAgePeriodStartDate, reageFirstDueDate,
+                loanTransaction.getTransactionDate(), loanApplicationTerms, 
mc);
 
         updateInstallmentsByModelForReAging(loanTransaction, ctx);
 
@@ -3273,4 +3278,22 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
                 Money.zero(currency));
         reprocessInstallments(installments);
     }
+
+    private static LocalDate calculateFirstReAgedPeriodStartDate(final 
LoanTransaction loanTransaction) {
+        final LoanReAgeParameter loanReAgeParameter = 
loanTransaction.getLoanReAgeParameter();
+        final LocalDate reAgingStartDate = loanReAgeParameter.getStartDate();
+
+        if 
(reAgingStartDate.isEqual(loanTransaction.getLoan().getDisbursementDate())) {
+            return reAgingStartDate;
+        }
+
+        return switch (loanReAgeParameter.getFrequencyType()) {
+            case DAYS -> 
reAgingStartDate.minusDays(loanReAgeParameter.getFrequencyNumber());
+            case WEEKS -> 
reAgingStartDate.minusWeeks(loanReAgeParameter.getFrequencyNumber());
+            case MONTHS -> 
reAgingStartDate.minusMonths(loanReAgeParameter.getFrequencyNumber());
+            case YEARS -> 
reAgingStartDate.minusYears(loanReAgeParameter.getFrequencyNumber());
+            case WHOLE_TERM -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: WHOLE_TERM");
+            case INVALID -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: INVALID");
+        };
+    }
 }
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 5e726aa7a4..d1a710c1fb 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
@@ -110,7 +110,7 @@ public class ProgressiveLoanScheduleGenerator implements 
LoanScheduleGenerator {
                 ? 
loanApplicationTerms.getLoanTermVariations().getExceptionData()
                 : null;
         final ProgressiveLoanInterestScheduleModel interestScheduleModel = 
emiCalculator.generatePeriodInterestScheduleModel(
-                expectedRepaymentPeriods, 
loanApplicationTerms.toLoanProductRelatedDetailMinimumData(), 
loanTermVariations,
+                expectedRepaymentPeriods, 
loanApplicationTerms.toLoanConfigurationDetails(), loanTermVariations,
                 loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
         final List<LoanScheduleModelPeriod> periods = new 
ArrayList<>(expectedRepaymentPeriods.size());
 
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanConfigurationDetailsMapper.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanConfigurationDetailsMapper.java
new file mode 100644
index 0000000000..4dc2c1f7b4
--- /dev/null
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/mapper/LoanConfigurationDetailsMapper.java
@@ -0,0 +1,42 @@
+package org.apache.fineract.portfolio.loanaccount.mapper;
+
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
+import org.apache.fineract.portfolio.common.domain.DaysInYearType;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanproduct.data.LoanConfigurationDetails;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
+import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
+
+public final class LoanConfigurationDetailsMapper {
+
+    private LoanConfigurationDetailsMapper() {}
+
+    public static ILoanConfigurationDetails map(Loan loan) {
+        if (loan == null) {
+            return null;
+        }
+
+        LoanProductRelatedDetail loanProductRelatedDetail = 
loan.getLoanProductRelatedDetail();
+        if (loanProductRelatedDetail == null) {
+            return null;
+        }
+
+        MonetaryCurrency currency = loan.getCurrency();
+        CurrencyData currencyData = currency.toData();
+
+        return new LoanConfigurationDetails(currencyData, 
loanProductRelatedDetail.getNominalInterestRatePerPeriod(),
+                loanProductRelatedDetail.getAnnualNominalInterestRate(), 
loanProductRelatedDetail.getGraceOnInterestCharged(),
+                loanProductRelatedDetail.getGraceOnPrincipalPayment(), 
loanProductRelatedDetail.getGraceOnPrincipalPayment(),
+                
loanProductRelatedDetail.getRecurringMoratoriumOnPrincipalPeriods(), 
loanProductRelatedDetail.getInterestMethod(),
+                loanProductRelatedDetail.getInterestCalculationPeriodMethod(),
+                
DaysInYearType.fromInt(loanProductRelatedDetail.getDaysInYearType()),
+                
DaysInMonthType.fromInt(loanProductRelatedDetail.getDaysInMonthType()), 
loanProductRelatedDetail.getAmortizationMethod(),
+                loanProductRelatedDetail.getRepaymentPeriodFrequencyType(), 
loanProductRelatedDetail.getRepayEvery(),
+                loanProductRelatedDetail.getNumberOfRepayments(), 
loanProductRelatedDetail.isInterestRecognitionOnDisbursementDate(),
+                loanProductRelatedDetail.getDaysInYearCustomStrategy(), 
loanProductRelatedDetail.isAllowPartialPeriodInterestCalculation(),
+                loan.isInterestRecalculationEnabled(), 
loan.getLoanInterestRecalculationDetails().getRestFrequencyType(),
+                
loan.getLoanInterestRecalculationDetails().getPreCloseInterestCalculationStrategy());
+    }
+}
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapper.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapper.java
index 243f8702a4..1ce74910b7 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapper.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapper.java
@@ -23,7 +23,7 @@ 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.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 
 public interface InterestScheduleModelRepositoryWrapper {
 
@@ -35,8 +35,8 @@ public interface InterestScheduleModelRepositoryWrapper {
 
     ProgressiveLoanInterestScheduleModel writeInterestScheduleModel(Loan loan, 
ProgressiveLoanInterestScheduleModel model);
 
-    Optional<ProgressiveLoanInterestScheduleModel> 
readProgressiveLoanInterestScheduleModel(Long loanId,
-            LoanProductMinimumRepaymentScheduleRelatedDetail detail, Integer 
installmentAmountInMultipliesOf);
+    Optional<ProgressiveLoanInterestScheduleModel> 
readProgressiveLoanInterestScheduleModel(Long loanId, ILoanConfigurationDetails 
detail,
+            Integer installmentAmountInMultipliesOf);
 
     boolean hasValidModelForDate(Long loanId, LocalDate targetDate);
 
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapperImpl.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapperImpl.java
index 6dac432745..a00f7af0a3 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapperImpl.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapperImpl.java
@@ -35,9 +35,10 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.ProgressiveLoanModel;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.MoneyHolder;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.ProgressiveTransactionCtx;
+import 
org.apache.fineract.portfolio.loanaccount.mapper.LoanConfigurationDetailsMapper;
 import 
org.apache.fineract.portfolio.loanaccount.repository.ProgressiveLoanModelRepository;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -92,7 +93,7 @@ public class InterestScheduleModelRepositoryWrapperImpl 
implements InterestSched
     public Optional<ProgressiveLoanInterestScheduleModel> 
extractModel(Optional<ProgressiveLoanModel> progressiveLoanModel) {
         return progressiveLoanModel.map(ProgressiveLoanModel::getJsonModel) //
                 .map(jsonModel -> 
progressiveLoanInterestScheduleModelParserService.fromJson(jsonModel,
-                        
progressiveLoanModel.get().getLoan().getLoanProductRelatedDetail(), 
MoneyHelper.getMathContext(),
+                        
LoanConfigurationDetailsMapper.map(progressiveLoanModel.get().getLoan()), 
MoneyHelper.getMathContext(),
                         
progressiveLoanModel.get().getLoan().getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf()));
     }
 
@@ -125,7 +126,7 @@ public class InterestScheduleModelRepositoryWrapperImpl 
implements InterestSched
 
     @Override
     public Optional<ProgressiveLoanInterestScheduleModel> 
readProgressiveLoanInterestScheduleModel(final Long loanId,
-            final LoanProductMinimumRepaymentScheduleRelatedDetail detail, 
final Integer installmentAmountInMultipliesOf) {
+            final ILoanConfigurationDetails detail, final Integer 
installmentAmountInMultipliesOf) {
         return loanModelRepository.findOneByLoanId(loanId) //
                 .map(ProgressiveLoanModel::getJsonModel) //
                 .map(jsonModel -> 
progressiveLoanInterestScheduleModelParserService.fromJson(jsonModel, detail,
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelServiceGsonContext.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelServiceGsonContext.java
index 767c817bca..59ce097db9 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelServiceGsonContext.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelServiceGsonContext.java
@@ -27,7 +27,7 @@ import 
org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.portfolio.loanproduct.calc.data.InterestPeriod;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
 import org.apache.fineract.portfolio.loanproduct.calc.data.RepaymentPeriod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 
 @Data
 @RequiredArgsConstructor
@@ -35,7 +35,7 @@ public class InterestScheduleModelServiceGsonContext {
 
     private final MonetaryCurrency currency;
     private final MathContext mc;
-    private final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail;
+    private final ILoanConfigurationDetails loanProductRelatedDetail;
     private RepaymentPeriod prev = null;
     private final Integer installmentAmountInMultipliesOf;
 
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
index 60f8cd2630..46bd49c058 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java
@@ -42,7 +42,9 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionRepository;
 import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
+import 
org.apache.fineract.portfolio.loanaccount.mapper.LoanConfigurationDetailsMapper;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Component;
@@ -81,8 +83,8 @@ public class InternalProgressiveLoanApiResource implements 
InitializingBean {
         if (!loan.isProgressiveSchedule()) {
             throw new IllegalArgumentException("The loan is not progressive.");
         }
-
-        return 
writePlatformService.readProgressiveLoanInterestScheduleModel(loanId, 
loan.getLoanRepaymentScheduleDetail(),
+        ILoanConfigurationDetails loanConfigurationDetails = 
LoanConfigurationDetailsMapper.map(loan);
+        return 
writePlatformService.readProgressiveLoanInterestScheduleModel(loanId, 
loanConfigurationDetails,
                 
loan.getLoanProductRelatedDetail().getInstallmentAmountInMultiplesOf()).orElse(null);
     }
 
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserService.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserService.java
index e148ae23ae..0d3487a8a7 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserService.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserService.java
@@ -20,7 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.service;
 
 import java.math.MathContext;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 
 public interface ProgressiveLoanInterestScheduleModelParserService {
 
@@ -32,6 +32,6 @@ public interface 
ProgressiveLoanInterestScheduleModelParserService {
     /**
      * Restore a ProgressiveLoanInterestScheduleModel from a JSON string.
      */
-    ProgressiveLoanInterestScheduleModel fromJson(String s, 
LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail,
-            MathContext mc, Integer installmentAmountInMultipliesOf);
+    ProgressiveLoanInterestScheduleModel fromJson(String s, 
ILoanConfigurationDetails loanProductRelatedDetail, MathContext mc,
+            Integer installmentAmountInMultipliesOf);
 }
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserServiceGsonImpl.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserServiceGsonImpl.java
index c07b440402..477df16df0 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserServiceGsonImpl.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestScheduleModelParserServiceGsonImpl.java
@@ -35,7 +35,7 @@ import 
org.apache.fineract.organisation.monetary.serialization.MoneySerializer;
 import org.apache.fineract.portfolio.loanproduct.calc.data.InterestPeriod;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
 import org.apache.fineract.portfolio.loanproduct.calc.data.RepaymentPeriod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import org.springframework.lang.NonNull;
 
 @Slf4j
@@ -51,7 +51,7 @@ public class 
ProgressiveLoanInterestScheduleModelParserServiceGsonImpl implement
                 .addSerializationExclusionStrategy(new 
JsonExcludeAnnotationBasedExclusionStrategy()).create();
     }
 
-    private Gson 
createDeserializer(LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail, MathContext mc,
+    private Gson createDeserializer(ILoanConfigurationDetails 
loanProductRelatedDetail, MathContext mc,
             Integer installmentAmountInMultipliesOf) {
         InterestScheduleModelServiceGsonContext ctx = new 
InterestScheduleModelServiceGsonContext(
                 new 
MonetaryCurrency(loanProductRelatedDetail.getCurrencyData()), mc, 
loanProductRelatedDetail,
@@ -73,9 +73,8 @@ public class 
ProgressiveLoanInterestScheduleModelParserServiceGsonImpl implement
     }
 
     @Override
-    public ProgressiveLoanInterestScheduleModel fromJson(String s,
-            @NonNull LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail, @NonNull MathContext mc,
-            Integer installmentAmountInMultipliesOf) {
+    public ProgressiveLoanInterestScheduleModel fromJson(String s, @NonNull 
ILoanConfigurationDetails loanProductRelatedDetail,
+            @NonNull MathContext mc, Integer installmentAmountInMultipliesOf) {
         if (s == null) {
             return null;
         }
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
index de654f7c0b..6228e2c4d9 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/EMICalculator.java
@@ -27,15 +27,13 @@ import java.util.Optional;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
-import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.ProgressiveTransactionCtx;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelRepaymentPeriod;
 import org.apache.fineract.portfolio.loanproduct.calc.data.OutstandingDetails;
 import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
 import org.apache.fineract.portfolio.loanproduct.calc.data.RepaymentPeriod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 
 public interface EMICalculator {
 
@@ -45,8 +43,8 @@ public interface EMICalculator {
      */
     @NotNull
     ProgressiveLoanInterestScheduleModel 
generatePeriodInterestScheduleModel(@NotNull 
List<LoanScheduleModelRepaymentPeriod> periods,
-            @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail,
-            List<LoanTermVariationsData> loanTermVariations, Integer 
installmentAmountInMultiplesOf, MathContext mc);
+            @NotNull ILoanConfigurationDetails loanProductRelatedDetail, 
List<LoanTermVariationsData> loanTermVariations,
+            Integer installmentAmountInMultiplesOf, MathContext mc);
 
     /**
      * This method creates an Interest model with repayment periods from the 
installments which retrieved from the
@@ -54,8 +52,7 @@ public interface EMICalculator {
      */
     @NotNull
     ProgressiveLoanInterestScheduleModel 
generateInstallmentInterestScheduleModel(
-            @NotNull List<LoanRepaymentScheduleInstallment> installments,
-            @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail,
+            @NotNull List<LoanRepaymentScheduleInstallment> installments, 
@NotNull ILoanConfigurationDetails loanProductRelatedDetail,
             List<LoanTermVariationsData> loanTermVariations, Integer 
installmentAmountInMultiplesOf, MathContext mc);
 
     /**
@@ -144,10 +141,10 @@ public interface EMICalculator {
      */
     void applyInterestPause(ProgressiveLoanInterestScheduleModel 
scheduleModel, LocalDate fromDate, LocalDate endDate);
 
-    void updateModelRepaymentPeriodsDuringReAge(ProgressiveTransactionCtx ctx, 
LoanTransaction loanTransaction,
-            LoanApplicationTerms loanApplicationTerms, MathContext mc);
+    void 
updateModelRepaymentPeriodsDuringReAge(ProgressiveLoanInterestScheduleModel 
ctx, LocalDate loanTransaction,
+            LocalDate reageFirstDueDate, LocalDate transactionDate, 
LoanApplicationTerms loanApplicationTerms, MathContext mc);
 
-    boolean recalculateModelOverdueAmountsTillDate(ProgressiveTransactionCtx 
ctx, LocalDate targetDate);
+    boolean 
recalculateModelOverdueAmountsTillDate(ProgressiveLoanInterestScheduleModel 
ctx, LocalDate targetDate, boolean prepayAttempt);
 
     /**
      * Gives back the sum of the outstanding interest from the whole model 
till the provided date.
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
index ec558fc802..311098ab56 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java
@@ -39,21 +39,14 @@ import 
org.apache.fineract.infrastructure.core.domain.LocalDateInterval;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
-import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
-import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
 import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
 import 
org.apache.fineract.portfolio.common.domain.DaysInYearCustomStrategyType;
 import org.apache.fineract.portfolio.common.domain.DaysInYearType;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
-import org.apache.fineract.portfolio.loanaccount.domain.Loan;
-import 
org.apache.fineract.portfolio.loanaccount.domain.LoanInterestRecalculationDetails;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
-import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction;
-import 
org.apache.fineract.portfolio.loanaccount.domain.reaging.LoanReAgeParameter;
-import 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.ProgressiveTransactionCtx;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanApplicationTerms;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelRepaymentPeriod;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
@@ -64,7 +57,7 @@ import 
org.apache.fineract.portfolio.loanproduct.calc.data.OutstandingDetails;
 import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
 import org.apache.fineract.portfolio.loanproduct.calc.data.RepaymentPeriod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
@@ -80,8 +73,8 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
     @Override
     @NotNull
     public ProgressiveLoanInterestScheduleModel 
generatePeriodInterestScheduleModel(@NotNull 
List<LoanScheduleModelRepaymentPeriod> periods,
-            @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail,
-            List<LoanTermVariationsData> loanTermVariations, final Integer 
installmentAmountInMultiplesOf, final MathContext mc) {
+            @NotNull ILoanConfigurationDetails loanProductRelatedDetail, 
List<LoanTermVariationsData> loanTermVariations,
+            final Integer installmentAmountInMultiplesOf, final MathContext 
mc) {
         return generateInterestScheduleModel(periods, 
LoanScheduleModelRepaymentPeriod::periodFromDate,
                 LoanScheduleModelRepaymentPeriod::periodDueDate, 
loanProductRelatedDetail, loanTermVariations,
                 installmentAmountInMultiplesOf, mc);
@@ -90,8 +83,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
     @Override
     @NotNull
     public ProgressiveLoanInterestScheduleModel 
generateInstallmentInterestScheduleModel(
-            @NotNull List<LoanRepaymentScheduleInstallment> installments,
-            @NotNull LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail,
+            @NotNull List<LoanRepaymentScheduleInstallment> installments, 
@NotNull ILoanConfigurationDetails loanProductRelatedDetail,
             List<LoanTermVariationsData> loanTermVariations, final Integer 
installmentAmountInMultiplesOf, final MathContext mc) {
         installments = installments.stream().filter(installment -> 
!installment.isDownPayment() && !installment.isAdditional()).toList();
         return generateInterestScheduleModel(installments, 
LoanRepaymentScheduleInstallment::getFromDate,
@@ -101,7 +93,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
 
     @NotNull
     private <T> ProgressiveLoanInterestScheduleModel 
generateInterestScheduleModel(@NotNull List<T> periods, Function<T, LocalDate> 
from,
-            Function<T, LocalDate> to, @NotNull 
LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail,
+            Function<T, LocalDate> to, @NotNull ILoanConfigurationDetails 
loanProductRelatedDetail,
             List<LoanTermVariationsData> loanTermVariations, final Integer 
installmentAmountInMultiplesOf, final MathContext mc) {
         final Money zero = 
Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
         final AtomicReference<RepaymentPeriod> prev = new AtomicReference<>();
@@ -218,7 +210,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
 
     public <T> void updateModel(ProgressiveLoanInterestScheduleModel 
scheduleModel, List<T> updateExpectedRepaymentPeriods,
             Function<T, LocalDate> from, Function<T, LocalDate> to) {
-        final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail = scheduleModel.loanProductRelatedDetail();
+        final ILoanConfigurationDetails loanProductRelatedDetail = 
scheduleModel.loanProductRelatedDetail();
         MathContext mc = scheduleModel.mc();
         final Money zero = 
Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
         final AtomicReference<RepaymentPeriod> prev = new AtomicReference<>();
@@ -575,36 +567,34 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
     }
 
     @Override
-    public void updateModelRepaymentPeriodsDuringReAge(final 
ProgressiveTransactionCtx ctx, final LoanTransaction loanTransaction,
+    public void updateModelRepaymentPeriodsDuringReAge(final 
ProgressiveLoanInterestScheduleModel scheduleModel,
+            final LocalDate reAgePeriodStartDate, LocalDate reageFirstDueDate, 
LocalDate targetDate,
             final LoanApplicationTerms loanApplicationTerms, final MathContext 
mc) {
-        final List<RepaymentPeriod> existingRepaymentPeriods = 
ctx.getModel().repaymentPeriods();
-
-        
moveOutstandingAmountsFromPeriodsBeforeReAging(existingRepaymentPeriods, 
loanTransaction.getLoanReAgeParameter().getStartDate());
 
-        final LocalDate periodStartDate = 
calculateFirstReAgedPeriodStartDate(loanTransaction);
+        
moveOutstandingAmountsFromPeriodsBeforeReAging(scheduleModel.repaymentPeriods(),
 reageFirstDueDate);
 
         final ProgressiveLoanInterestScheduleModel 
temporaryReAgedScheduleModel = 
generateTemporaryReAgedScheduleModel(loanApplicationTerms,
-                mc, periodStartDate);
+                mc, reAgePeriodStartDate);
 
-        mergeNewInterestScheduleModelWithExistingOne(ctx, 
temporaryReAgedScheduleModel, loanTransaction);
+        mergeNewInterestScheduleModelWithExistingOne(scheduleModel, 
temporaryReAgedScheduleModel, reageFirstDueDate, targetDate);
     }
 
     @Override
-    public boolean recalculateModelOverdueAmountsTillDate(final 
ProgressiveTransactionCtx ctx, final LocalDate targetDate) {
+    public boolean recalculateModelOverdueAmountsTillDate(final 
ProgressiveLoanInterestScheduleModel scheduleModel,
+            final LocalDate targetDate, boolean prepayAttempt) {
         boolean hasChange = false;
-        final ProgressiveLoanInterestScheduleModel model = ctx.getModel();
-        final List<RepaymentPeriod> 
overdueInstallmentsSortedByInstallmentNumber = 
findPossiblyOverdueRepaymentPeriods(targetDate, model);
+        final List<RepaymentPeriod> 
overdueInstallmentsSortedByInstallmentNumber = 
findPossiblyOverdueRepaymentPeriods(targetDate,
+                scheduleModel);
         if (!overdueInstallmentsSortedByInstallmentNumber.isEmpty()) {
-            final RepaymentPeriod lastPeriod = model.getLastRepaymentPeriod();
-            final RepaymentPeriod currentPeriod = 
model.findRepaymentPeriod(targetDate).orElse(lastPeriod);
-            final MonetaryCurrency currency = model.zero().getCurrency();
-            Money overDuePrincipal = Money.zero(currency);
-            Money aggregatedOverDuePrincipal = Money.zero(currency);
+            final RepaymentPeriod lastPeriod = 
scheduleModel.getLastRepaymentPeriod();
+            final RepaymentPeriod currentPeriod = 
scheduleModel.findRepaymentPeriod(targetDate).orElse(lastPeriod);
+            Money overDuePrincipal = scheduleModel.zero();
+            Money aggregatedOverDuePrincipal = scheduleModel.zero();
             for (RepaymentPeriod processingPeriod : 
overdueInstallmentsSortedByInstallmentNumber) {
                 // add and subtract outstanding principal
                 if (!overDuePrincipal.isZero()) {
                     final boolean currentChanges = 
adjustOverduePrincipal(targetDate, processingPeriod, overDuePrincipal,
-                            aggregatedOverDuePrincipal, ctx);
+                            aggregatedOverDuePrincipal, scheduleModel, 
prepayAttempt);
 
                     hasChange = hasChange || currentChanges;
                 }
@@ -615,13 +605,13 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
 
             if (!currentPeriod.equals(lastPeriod) || 
!targetDate.isAfter(lastPeriod.getDueDate())) {
                 final boolean currentChanges = 
adjustOverduePrincipal(targetDate, currentPeriod, overDuePrincipal,
-                        aggregatedOverDuePrincipal, ctx);
+                        aggregatedOverDuePrincipal, scheduleModel, 
prepayAttempt);
                 hasChange = hasChange || currentChanges;
 
             }
-            if (aggregatedOverDuePrincipal.isGreaterThanZero()
-                    && (model.lastOverdueBalanceChange() == null || 
model.lastOverdueBalanceChange().isBefore(targetDate))) {
-                model.lastOverdueBalanceChange(targetDate);
+            if (aggregatedOverDuePrincipal.isGreaterThanZero() && 
(scheduleModel.lastOverdueBalanceChange() == null
+                    || 
scheduleModel.lastOverdueBalanceChange().isBefore(targetDate))) {
+                scheduleModel.lastOverdueBalanceChange(targetDate);
             }
         }
 
@@ -644,13 +634,10 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
     }
 
     private boolean adjustOverduePrincipal(final LocalDate currentDate, final 
RepaymentPeriod currentInstallment,
-            final Money overduePrincipal, final Money 
aggregatedOverDuePrincipal, final ProgressiveTransactionCtx ctx) {
+            final Money overduePrincipal, final Money 
aggregatedOverDuePrincipal, final ProgressiveLoanInterestScheduleModel model,
+            boolean prepayAttempt) {
         final LocalDate fromDate = currentInstallment.getFromDate();
         final LocalDate toDate = currentInstallment.getDueDate();
-        final ProgressiveLoanInterestScheduleModel model = ctx.getModel();
-        final boolean prepayAttempt = ctx.isPrepayAttempt();
-        final LoanInterestRecalculationDetails 
loanInterestRecalculationDetails = ctx.getInstallments().getFirst().getLoan()
-                .getLoanInterestRecalculationDetails();
 
         if (!currentDate.equals(model.lastOverdueBalanceChange())) {
             if (model.lastOverdueBalanceChange() == null || 
currentInstallment.getFromDate().isAfter(model.lastOverdueBalanceChange())) {
@@ -661,7 +648,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
 
             if (currentDate.isAfter(fromDate) && !currentDate.isAfter(toDate)) 
{
                 LocalDate lastOverdueBalanceChange;
-                if 
(shouldRecalculateTillInstallmentDueDate(loanInterestRecalculationDetails, 
prepayAttempt)) {
+                if 
(shouldRecalculateTillInstallmentDueDate(model.loanProductRelatedDetail(), 
prepayAttempt)) {
                     lastOverdueBalanceChange = toDate;
                 } else {
                     lastOverdueBalanceChange = currentDate;
@@ -674,7 +661,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
         return false;
     }
 
-    private boolean shouldRecalculateTillInstallmentDueDate(final 
LoanInterestRecalculationDetails recalculationDetails,
+    private boolean shouldRecalculateTillInstallmentDueDate(final 
ILoanConfigurationDetails loanProductRelatedDetails,
             final boolean isPrepayAttempt) {
         // Rest frequency type and pre close interest calculation strategy can 
be controversial
         // if restFrequencyType == DAILY and 
preCloseInterestCalculationStrategy == TILL_PRE_CLOSURE_DATE
@@ -686,11 +673,11 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
         // or restFrequencyType == SAME_AS_REPAYMENT_PERIOD and 
preCloseInterestCalculationStrategy ==
         // TILL_PRE_CLOSURE_DATE
         // we cannot harmonize the two configs. Behaviour should mimic prepay 
api.
-        return switch (recalculationDetails.getRestFrequencyType()) {
+        return switch (loanProductRelatedDetails.getRestFrequencyType()) {
             case DAILY ->
-                isPrepayAttempt && 
recalculationDetails.getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled();
+                isPrepayAttempt && 
loanProductRelatedDetails.getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled();
             case SAME_AS_REPAYMENT_PERIOD ->
-                
recalculationDetails.getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled();
+                
loanProductRelatedDetails.getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled();
             case WEEKLY -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: WEEKLY");
             case MONTHLY -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: MONTHLY");
             case INVALID -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: INVALID");
@@ -702,11 +689,10 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
      * the balances of the updated model and also recalculate the EMI if the 
EMI of the last repayment period differs
      * significantly from other periods.
      */
-    private void mergeNewInterestScheduleModelWithExistingOne(final 
ProgressiveTransactionCtx ctx,
-            final ProgressiveLoanInterestScheduleModel 
temporaryReAgedScheduleModel, final LoanTransaction loanTransaction) {
+    private void mergeNewInterestScheduleModelWithExistingOne(final 
ProgressiveLoanInterestScheduleModel scheduleModel,
+            final ProgressiveLoanInterestScheduleModel 
temporaryReAgedScheduleModel, final LocalDate reageFirstDueDate,
+            LocalDate targetDate) {
         final List<RepaymentPeriod> newPeriods = 
temporaryReAgedScheduleModel.repaymentPeriods();
-        final ProgressiveLoanInterestScheduleModel scheduleModel = 
ctx.getModel();
-        final Loan loan = loanTransaction.getLoan();
 
         if (newPeriods.isEmpty()) {
             return;
@@ -716,10 +702,8 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
         final RepaymentPeriod firstRepaymentPeriod = 
existingRepaymentPeriods.getFirst();
         final Money disbursedAmount = 
firstRepaymentPeriod.getTotalDisbursedAmount();
 
-        final LocalDate reAgingStartDate = 
loanTransaction.getLoanReAgeParameter().getStartDate();
-
         final Optional<RepaymentPeriod> firstExistingReAgedRepaymentPeriodOpt 
= existingRepaymentPeriods.stream()
-                .filter(period -> 
period.getDueDate().equals(reAgingStartDate)).findFirst();
+                .filter(period -> 
period.getDueDate().equals(reageFirstDueDate)).findFirst();
 
         for (final RepaymentPeriod newPeriod : newPeriods) {
             final Optional<RepaymentPeriod> existingRepaymentPeriodOpt = 
existingRepaymentPeriods.stream().filter(
@@ -736,34 +720,18 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
 
             final RepaymentPeriod rp = RepaymentPeriod.create(
                     
previousExistingRepaymentPeriodOpt.orElseGet(existingRepaymentPeriods::getLast),
 newPeriod.getFromDate(),
-                    newPeriod.getDueDate(), newPrincipal.add(newInterest), 
MoneyHelper.getMathContext(),
-                    loanTransaction.getLoan().getLoanProductRelatedDetail());
+                    newPeriod.getDueDate(), newPrincipal.add(newInterest), 
scheduleModel.mc(), scheduleModel.loanProductRelatedDetail());
             rp.setTotalDisbursedAmount(disbursedAmount);
 
-            if (existingRepaymentPeriodOpt.isPresent()) {
-                // Add an interest period on the disbursement date for the 
very first replaced period
-                if 
(existingRepaymentPeriodOpt.get().equals(firstRepaymentPeriod)) {
-                    final LocalDate disbursementDate = 
loanTransaction.getLoan().getDisbursementDate();
-                    
rp.getInterestPeriods().getFirst().setDisbursementAmount(disbursedAmount);
-                    
rp.getInterestPeriods().getFirst().setFromDate(disbursementDate);
-                    
rp.getInterestPeriods().getFirst().setDueDate(disbursementDate);
-                    
rp.getInterestPeriods().add(InterestPeriod.withEmptyAmounts(rp, 
rp.getFromDate(), rp.getDueDate()));
-                }
-                
existingRepaymentPeriods.remove(existingRepaymentPeriodOpt.get());
-            }
+            
existingRepaymentPeriodOpt.ifPresent(existingRepaymentPeriods::remove);
 
             existingRepaymentPeriods.add(rp);
             calculateRateFactorForRepaymentPeriod(rp, scheduleModel);
         }
 
-        if (reAgingStartDate.isBefore(DateUtils.getBusinessLocalDate()) && 
isInterestRecalculationIsAllowed(ctx, loan)) {
-            scheduleModel.lastOverdueBalanceChange(null);
-            recalculateModelOverdueAmountsTillDate(ctx, 
loanTransaction.getSubmittedOnDate());
-        }
-
         final List<RepaymentPeriod> reAgedRepaymentPeriods = 
existingRepaymentPeriods.stream()
-                .filter(repaymentPeriod -> 
(!repaymentPeriod.getFromDate().isBefore(reAgingStartDate)
-                        || 
repaymentPeriod.getDueDate().isEqual(reAgingStartDate))
+                .filter(repaymentPeriod -> 
(!repaymentPeriod.getFromDate().isBefore(reageFirstDueDate)
+                        || 
repaymentPeriod.getDueDate().isEqual(reageFirstDueDate))
                         && 
!repaymentPeriod.getDueDate().isAfter(newPeriods.getLast().getDueDate()))
                 .toList();
 
@@ -775,16 +743,10 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
         }
 
         calculateOutstandingBalance(scheduleModel);
-        calculateLastUnpaidRepaymentPeriodEMI(scheduleModel, 
loanTransaction.getTransactionDate());
+        calculateLastUnpaidRepaymentPeriodEMI(scheduleModel, targetDate);
         checkAndAdjustEmiIfNeededOnRelatedRepaymentPeriods(scheduleModel, 
reAgedRepaymentPeriods);
     }
 
-    private boolean isInterestRecalculationIsAllowed(final 
ProgressiveTransactionCtx ctx, final Loan loan) {
-        return loan.isInterestBearingAndInterestRecalculationEnabled() && 
!ctx.isChargedOff() && !ctx.isWrittenOff()
-                && !ctx.isContractTerminated() && !loan.isNpa()
-                && 
!loan.getLoanInterestRecalculationDetails().disallowInterestCalculationOnPastDue();
-    }
-
     /**
      * * Generates temporary interestScheduleModel with re-aged repayment 
periods
      */
@@ -794,36 +756,13 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
         final List<LoanScheduleModelRepaymentPeriod> expectedRepaymentPeriods 
= scheduledDateGenerator.generateRepaymentPeriods(mc,
                 periodStartDate, loanApplicationTerms, null);
         final ProgressiveLoanInterestScheduleModel 
temporaryReAgedScheduleModel = generatePeriodInterestScheduleModel(
-                expectedRepaymentPeriods, 
loanApplicationTerms.toLoanProductRelatedDetailMinimumData(), null,
+                expectedRepaymentPeriods, 
loanApplicationTerms.toLoanConfigurationDetails(), null,
                 loanApplicationTerms.getInstallmentAmountInMultiplesOf(), mc);
 
         addDisbursement(temporaryReAgedScheduleModel, 
EmiChangeOperation.disburse(periodStartDate, 
loanApplicationTerms.getPrincipal()));
         return temporaryReAgedScheduleModel;
     }
 
-    /**
-     * * Based on the re-aging start date and frequency data calculates start 
date for the first re-aged period, which
-     * is used to generate re-aged repayment periods
-     */
-    @NotNull
-    private static LocalDate calculateFirstReAgedPeriodStartDate(final 
LoanTransaction loanTransaction) {
-        final LoanReAgeParameter loanReAgeParameter = 
loanTransaction.getLoanReAgeParameter();
-        final LocalDate reAgingStartDate = loanReAgeParameter.getStartDate();
-
-        if 
(reAgingStartDate.isEqual(loanTransaction.getLoan().getDisbursementDate())) {
-            return reAgingStartDate;
-        }
-
-        return switch (loanReAgeParameter.getFrequencyType()) {
-            case DAYS -> 
reAgingStartDate.minusDays(loanReAgeParameter.getFrequencyNumber());
-            case WEEKS -> 
reAgingStartDate.minusWeeks(loanReAgeParameter.getFrequencyNumber());
-            case MONTHS -> 
reAgingStartDate.minusMonths(loanReAgeParameter.getFrequencyNumber());
-            case YEARS -> 
reAgingStartDate.minusYears(loanReAgeParameter.getFrequencyNumber());
-            case WHOLE_TERM -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: WHOLE_TERM");
-            case INVALID -> throw new IllegalStateException("Unexpected 
RecalculationFrequencyType: INVALID");
-        };
-    }
-
     /**
      * * Zeroing out the EMI of the repayment periods, that are before 
re-aging and not been fully paid. And decreases
      * the balance correction amount (added during interest recalculation for 
the business date) by the amount of the
@@ -1008,7 +947,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
     BigDecimal calculateRateFactorPerPeriodForInterest(final 
ProgressiveLoanInterestScheduleModel scheduleModel,
             final RepaymentPeriod repaymentPeriod, final LocalDate 
interestPeriodFromDate, final LocalDate interestPeriodDueDate) {
         final MathContext mc = scheduleModel.mc();
-        final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail = scheduleModel.loanProductRelatedDetail();
+        final ILoanConfigurationDetails loanProductRelatedDetail = 
scheduleModel.loanProductRelatedDetail();
         final BigDecimal interestRate = 
calcNominalInterestRatePercentage(scheduleModel.getInterestRate(interestPeriodFromDate),
                 scheduleModel.mc());
         final DaysInYearType daysInYearType = 
DaysInYearType.fromInt(loanProductRelatedDetail.getDaysInYearType());
@@ -1136,7 +1075,7 @@ public final class ProgressiveEMICalculator implements 
EMICalculator {
     private BigDecimal calculateRateFactorPerPeriod(final 
ProgressiveLoanInterestScheduleModel scheduleModel,
             final RepaymentPeriod repaymentPeriod, final LocalDate 
interestPeriodFromDate, final LocalDate interestPeriodDueDate) {
         final MathContext mc = scheduleModel.mc();
-        final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail = scheduleModel.loanProductRelatedDetail();
+        final ILoanConfigurationDetails loanProductRelatedDetail = 
scheduleModel.loanProductRelatedDetail();
         final BigDecimal interestRate = 
calcNominalInterestRatePercentage(scheduleModel.getInterestRate(interestPeriodFromDate),
                 scheduleModel.mc());
         final DaysInYearType daysInYearType = 
DaysInYearType.fromInt(loanProductRelatedDetail.getDaysInYearType());
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java
index 95ed156122..3ebd0bcb25 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java
@@ -20,5 +20,6 @@ package org.apache.fineract.portfolio.loanproduct.calc.data;
 
 public enum LoanInterestScheduleModelModifiers { //
     EMI_RECALCULATION, //
-    COPY //
+    COPY, //
+    INTEREST_RECALCULATION_ENABLED //
 }
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
index 3b4e990c1e..859bbe77a5 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java
@@ -21,6 +21,7 @@ package org.apache.fineract.portfolio.loanproduct.calc.data;
 import static 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper.isInPeriod;
 import static 
org.apache.fineract.portfolio.loanproduct.calc.data.LoanInterestScheduleModelModifiers.COPY;
 import static 
org.apache.fineract.portfolio.loanproduct.calc.data.LoanInterestScheduleModelModifiers.EMI_RECALCULATION;
+import static 
org.apache.fineract.portfolio.loanproduct.calc.data.LoanInterestScheduleModelModifiers.INTEREST_RECALCULATION_ENABLED;
 
 import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
@@ -50,7 +51,7 @@ import 
org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 
 @Data
 @Accessors(fluent = true)
@@ -60,7 +61,7 @@ public class ProgressiveLoanInterestScheduleModel {
     private final List<RepaymentPeriod> repaymentPeriods;
     private final TreeSet<InterestRate> interestRates;
     @JsonExclude
-    private final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail;
+    private final ILoanConfigurationDetails loanProductRelatedDetail;
     private final Map<LoanTermVariationType, List<LoanTermVariationsData>> 
loanTermVariations;
     private final Integer installmentAmountInMultiplesOf;
     @JsonExclude
@@ -73,8 +74,8 @@ public class ProgressiveLoanInterestScheduleModel {
     private LocalDate lastOverdueBalanceChange;
 
     public ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> 
repaymentPeriods,
-            final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail,
-            final List<LoanTermVariationsData> loanTermVariations, final 
Integer installmentAmountInMultiplesOf, final MathContext mc) {
+            final ILoanConfigurationDetails loanProductRelatedDetail, final 
List<LoanTermVariationsData> loanTermVariations,
+            final Integer installmentAmountInMultiplesOf, final MathContext 
mc) {
         this.repaymentPeriods = new ArrayList<>(repaymentPeriods);
         this.interestRates = new TreeSet<>(Collections.reverseOrder());
         this.loanProductRelatedDetail = loanProductRelatedDetail;
@@ -82,11 +83,12 @@ public class ProgressiveLoanInterestScheduleModel {
         this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
         this.mc = mc;
         this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
-        modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, 
false));
+        modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, false, 
INTEREST_RECALCULATION_ENABLED,
+                loanProductRelatedDetail.isInterestRecalculationEnabled()));
     }
 
     private ProgressiveLoanInterestScheduleModel(final List<RepaymentPeriod> 
repaymentPeriods, final TreeSet<InterestRate> interestRates,
-            final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail,
+            final ILoanConfigurationDetails loanProductRelatedDetail,
             final Map<LoanTermVariationType, List<LoanTermVariationsData>> 
loanTermVariations, final Integer installmentAmountInMultiplesOf,
             final MathContext mc, final boolean isCopiedForCalculation) {
         this.mc = mc;
@@ -97,7 +99,8 @@ public class ProgressiveLoanInterestScheduleModel {
         this.loanTermVariations = loanTermVariations;
         this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf;
         this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc);
-        modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, 
isCopiedForCalculation));
+        modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, 
isCopiedForCalculation, INTEREST_RECALCULATION_ENABLED,
+                loanProductRelatedDetail.isInterestRecalculationEnabled()));
     }
 
     public ProgressiveLoanInterestScheduleModel deepCopy(MathContext mc) {
@@ -440,4 +443,8 @@ public class ProgressiveLoanInterestScheduleModel {
             default -> throw new UnsupportedOperationException();
         };
     }
+
+    public boolean isInterestRecalculationIsAllowed() {
+        return modifiers.get(INTEREST_RECALCULATION_ENABLED);
+    }
 }
diff --git 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriod.java
 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriod.java
index a3735eb8f6..2367733da9 100644
--- 
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriod.java
+++ 
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriod.java
@@ -35,7 +35,7 @@ import 
org.apache.fineract.infrastructure.core.serialization.gson.JsonExclude;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import org.apache.fineract.portfolio.util.Memo;
 
 @ToString(exclude = { "previous" })
@@ -84,13 +84,13 @@ public class RepaymentPeriod {
     private Money totalCapitalizedIncomeAmount;
     @JsonExclude
     @Getter
-    private final LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail;
+    private final ILoanConfigurationDetails loanProductRelatedDetail;
     @JsonExclude
     private MonetaryCurrency currency;
 
     protected RepaymentPeriod(RepaymentPeriod previous, LocalDate fromDate, 
LocalDate dueDate, List<InterestPeriod> interestPeriods,
             Money emi, Money originalEmi, Money paidPrincipal, Money 
paidInterest, Money futureUnrecognizedInterest, MathContext mc,
-            LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail) {
+            ILoanConfigurationDetails loanProductRelatedDetail) {
         this.previous = previous;
         this.fromDate = fromDate;
         this.dueDate = dueDate;
@@ -104,13 +104,12 @@ public class RepaymentPeriod {
         this.loanProductRelatedDetail = loanProductRelatedDetail;
     }
 
-    public static RepaymentPeriod empty(RepaymentPeriod previous, MathContext 
mc,
-            LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail) {
+    public static RepaymentPeriod empty(RepaymentPeriod previous, MathContext 
mc, ILoanConfigurationDetails loanProductRelatedDetail) {
         return new RepaymentPeriod(previous, null, null, new ArrayList<>(), 
null, null, null, null, null, mc, loanProductRelatedDetail);
     }
 
     public static RepaymentPeriod create(RepaymentPeriod previous, LocalDate 
fromDate, LocalDate dueDate, Money emi, MathContext mc,
-            LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail) {
+            ILoanConfigurationDetails loanProductRelatedDetail) {
         final Money zero = emi.zero();
         final RepaymentPeriod newRepaymentPeriod = new 
RepaymentPeriod(previous, fromDate, dueDate, new ArrayList<>(), emi, emi, zero, 
zero,
                 zero, mc, loanProductRelatedDetail);
diff --git 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
index 9d7c0ae4ba..3cbaffb437 100644
--- 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
+++ 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculatorTest.java
@@ -47,9 +47,9 @@ import 
org.apache.fineract.portfolio.loanproduct.calc.data.InterestPeriod;
 import org.apache.fineract.portfolio.loanproduct.calc.data.PeriodDueDetails;
 import 
org.apache.fineract.portfolio.loanproduct.calc.data.ProgressiveLoanInterestScheduleModel;
 import org.apache.fineract.portfolio.loanproduct.calc.data.RepaymentPeriod;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
 import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -72,8 +72,7 @@ class ProgressiveEMICalculatorTest {
     private static MockedStatic<ThreadLocalContextUtil> threadLocalContextUtil 
= Mockito.mockStatic(ThreadLocalContextUtil.class);
     private static MockedStatic<MoneyHelper> moneyHelper = 
Mockito.mockStatic(MoneyHelper.class);
     private static MathContext mc = new MathContext(12, 
RoundingMode.HALF_EVEN);
-    private static LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail = Mockito
-            .mock(LoanProductMinimumRepaymentScheduleRelatedDetail.class);
+    private static ILoanConfigurationDetails loanProductRelatedDetail = 
Mockito.mock(ILoanConfigurationDetails.class);
 
     private static final CurrencyData currency = new CurrencyData("USD", 
"USD", 2, 1, "$", "USD");
 
diff --git 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/InterestPeriodTest.java
 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/InterestPeriodTest.java
index 320c7d1c89..2a6defe240 100644
--- 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/InterestPeriodTest.java
+++ 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/InterestPeriodTest.java
@@ -32,9 +32,9 @@ import java.util.List;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
 import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -86,8 +86,7 @@ class InterestPeriodTest {
         InterestPeriod period = InterestPeriod.empty(repaymentPeriod, MC);
         when(repaymentPeriod.getInterestPeriods()).thenReturn(List.of(period));
         when(repaymentPeriod.getFirstInterestPeriod()).thenReturn(period);
-        LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail = mock(
-                LoanProductMinimumRepaymentScheduleRelatedDetail.class);
+        ILoanConfigurationDetails loanProductRelatedDetail = 
mock(ILoanConfigurationDetails.class);
         when(loanProductRelatedDetail.getCurrencyData()).thenReturn(USD);
         
when(loanProductRelatedDetail.getInterestMethod()).thenReturn(InterestMethod.DECLINING_BALANCE);
         
when(loanProductRelatedDetail.getInterestCalculationPeriodMethod()).thenReturn(InterestCalculationPeriodMethod.DAILY);
diff --git 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriodTest.java
 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriodTest.java
index 4819268876..b257f73747 100644
--- 
a/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriodTest.java
+++ 
b/fineract-progressive-loan/src/test/java/org/apache/fineract/portfolio/loanproduct/calc/data/RepaymentPeriodTest.java
@@ -31,9 +31,9 @@ import java.time.ZoneId;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.monetary.domain.Money;
 import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
+import 
org.apache.fineract.portfolio.loanproduct.domain.ILoanConfigurationDetails;
 import 
org.apache.fineract.portfolio.loanproduct.domain.InterestCalculationPeriodMethod;
 import org.apache.fineract.portfolio.loanproduct.domain.InterestMethod;
-import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductMinimumRepaymentScheduleRelatedDetail;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -47,7 +47,7 @@ class RepaymentPeriodTest {
     private static final Money ZERO = Money.of(USD, BigDecimal.ZERO, MC);
 
     private static MockedStatic<MoneyHelper> moneyHelper;
-    private static LoanProductMinimumRepaymentScheduleRelatedDetail 
loanProductRelatedDetail;
+    private static ILoanConfigurationDetails loanProductRelatedDetail;
 
     @BeforeAll
     static void init() {
@@ -55,7 +55,7 @@ class RepaymentPeriodTest {
         
moneyHelper.when(MoneyHelper::getRoundingMode).thenReturn(RoundingMode.HALF_EVEN);
         moneyHelper.when(MoneyHelper::getMathContext).thenReturn(MC);
 
-        loanProductRelatedDetail = 
mock(LoanProductMinimumRepaymentScheduleRelatedDetail.class);
+        loanProductRelatedDetail = mock(ILoanConfigurationDetails.class);
         when(loanProductRelatedDetail.getCurrencyData()).thenReturn(USD);
         
when(loanProductRelatedDetail.getInterestMethod()).thenReturn(InterestMethod.DECLINING_BALANCE);
         
when(loanProductRelatedDetail.getInterestCalculationPeriodMethod()).thenReturn(InterestCalculationPeriodMethod.DAILY);

Reply via email to