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 ae77d29be FINERACT-1958: Fix down-payment for loan reschedule and for 
interest bearing loans
ae77d29be is described below

commit ae77d29be240f7239173f7996bc601006a6fc85f
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Dec 7 14:43:24 2023 +0100

    FINERACT-1958: Fix down-payment for loan reschedule and for interest 
bearing loans
---
 .../portfolio/loanaccount/domain/Loan.java         |  11 +-
 .../portfolio/loanaccount/domain/LoanCharge.java   |   2 +-
 .../loanschedule/domain/LoanApplicationTerms.java  |  15 +
 .../loanaccount/api/LoansApiResourceSwagger.java   |   6 +-
 .../loanschedule/data/LoanScheduleParams.java      | 138 ++++---
 .../AbstractCumulativeLoanScheduleGenerator.java   | 163 ++++----
 .../AbstractProgressiveLoanScheduleGenerator.java  |   9 +-
 .../service/LoanScheduleAssembler.java             |  12 +-
 .../LoanReschedulePreviewPlatformServiceImpl.java  |   5 +-
 ...nRescheduleRequestWritePlatformServiceImpl.java |   4 +-
 ...PaymentAllocationLoanRepaymentScheduleTest.java |  95 ++---
 .../integrationtests/BaseLoanIntegrationTest.java  |  14 +-
 .../ClientLoanIntegrationTest.java                 |   6 +-
 .../ExternalIdSupportIntegrationTest.java          |   9 +-
 ...gePaymentWithAdvancedPaymentAllocationTest.java |   6 +-
 .../LoanInstallmentMultiplesOfTest.java            |  10 +-
 .../LoanRescheduleTestWithDownpayment.java         | 415 ++++++++++++++++++++-
 ...LoanSpecificDueDateChargeAfterMaturityTest.java |   6 +-
 .../integrationtests/LoanWaiveChargeTest.java      |   2 +-
 ...tiveLoansWithAdvancedPaymentAllocationTest.java |  10 +-
 20 files changed, 717 insertions(+), 221 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index d8432f0cb..e89880f11 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -41,7 +41,6 @@ import jakarta.persistence.Version;
 import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.math.MathContext;
-import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
@@ -2823,8 +2822,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
     public LoanScheduleModel regenerateScheduleModel(final 
ScheduleGeneratorDTO scheduleGeneratorDTO) {
 
-        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-        final MathContext mc = new MathContext(8, roundingMode);
+        final MathContext mc = MoneyHelper.getMathContext();
 
         final LoanApplicationTerms loanApplicationTerms = 
constructLoanApplicationTerms(scheduleGeneratorDTO);
         LoanScheduleGenerator loanScheduleGenerator;
@@ -5762,8 +5760,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         final LoanScheduleGenerator loanScheduleGenerator = 
generatorDTO.getLoanScheduleFactory()
                 
.create(this.loanRepaymentScheduleDetail.getLoanScheduleType(), interestMethod);
 
-        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-        final MathContext mc = new MathContext(19, roundingMode);
+        final MathContext mc = MoneyHelper.getMathContext();
 
         final LoanApplicationTerms loanApplicationTerms = 
constructLoanApplicationTerms(generatorDTO);
 
@@ -5778,8 +5775,8 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         LoanRepaymentScheduleInstallment installment = null;
 
         if (this.loanRepaymentScheduleDetail.isInterestRecalculationEnabled()) 
{
-            final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-            final MathContext mc = new MathContext(8, roundingMode);
+
+            final MathContext mc = MoneyHelper.getMathContext();
 
             final InterestMethod interestMethod = 
this.loanRepaymentScheduleDetail.getInterestMethod();
             final LoanApplicationTerms loanApplicationTerms = 
constructLoanApplicationTerms(scheduleGeneratorDTO);
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
index 252886de6..42ec041a6 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanCharge.java
@@ -565,7 +565,7 @@ public class LoanCharge extends 
AbstractAuditableWithUTCDateTimeCustom {
         BigDecimal percentageOf = BigDecimal.ZERO;
 
         if (isGreaterThanZero(value)) {
-            final MathContext mc = new MathContext(8, 
MoneyHelper.getRoundingMode());
+            final MathContext mc = MoneyHelper.getMathContext();
             final BigDecimal multiplicand = 
percentage.divide(BigDecimal.valueOf(100L), mc);
             percentageOf = value.multiply(multiplicand, mc);
         }
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 52e43ac1e..19bee527a 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
@@ -28,6 +28,7 @@ import java.util.List;
 import java.util.Set;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
@@ -212,6 +213,7 @@ public final class LoanApplicationTerms {
     private LocalDate newScheduledDueDateStart;
     private boolean isDownPaymentEnabled;
     private BigDecimal disbursedAmountPercentageForDownPayment;
+    private Money downPaymentAmount;
     private boolean isAutoRepaymentForDownPaymentEnabled;
 
     private RepaymentStartDateType repaymentStartDateType;
@@ -450,6 +452,15 @@ public final class LoanApplicationTerms {
         this.isPrincipalCompoundingDisabledForOverdueLoans = 
isPrincipalCompoundingDisabledForOverdueLoans;
         this.isDownPaymentEnabled = isDownPaymentEnabled;
         this.disbursedAmountPercentageForDownPayment = 
disbursedAmountPercentageForDownPayment;
+        this.downPaymentAmount = Money.zero(getCurrency());
+        if (isDownPaymentEnabled) {
+            this.downPaymentAmount = Money.of(getCurrency(),
+                    MathUtil.percentageOf(getPrincipal().getAmount(), 
getDisbursedAmountPercentageForDownPayment(), 19));
+            if (getInstallmentAmountInMultiplesOf() != null) {
+                downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount, 
getInstallmentAmountInMultiplesOf());
+            }
+        }
+
         this.isAutoRepaymentForDownPaymentEnabled = 
isAutoRepaymentForDownPaymentEnabled;
         this.repaymentStartDateType = repaymentStartDateType;
         this.submittedOnDate = submittedOnDate;
@@ -1817,4 +1828,8 @@ public final class LoanApplicationTerms {
     public LoanScheduleType getLoanScheduleType() {
         return loanScheduleType;
     }
+
+    public Money getDownPaymentAmount() {
+        return downPaymentAmount;
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
index a06bcb780..b90d184d3 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
@@ -1082,7 +1082,7 @@ final class LoansApiResourceSwagger {
         public Integer repaymentEvery;
         public GetLoansLoanIdRepaymentFrequencyType repaymentFrequencyType;
         @Schema(example = "24")
-        public Integer interestRatePerPeriod;
+        public BigDecimal interestRatePerPeriod;
         public GetLoansLoanIdInterestRateFrequencyType 
interestRateFrequencyType;
         @Schema(example = "24")
         public Integer annualInterestRate;
@@ -1180,7 +1180,7 @@ final class LoansApiResourceSwagger {
         @Schema(example = "2")
         public Integer repaymentFrequencyType;
         @Schema(example = "2")
-        public Integer interestRatePerPeriod;
+        public BigDecimal interestRatePerPeriod;
         @Schema(example = "1")
         public Integer amortizationType;
         @Schema(example = "5.5")
@@ -1318,7 +1318,7 @@ final class LoansApiResourceSwagger {
         @Schema(example = "0")
         public Integer repaymentFrequencyType;
         @Schema(example = "2")
-        public Integer interestRatePerPeriod;
+        public BigDecimal interestRatePerPeriod;
         @Schema(example = "0")
         public Integer interestType;
         @Schema(example = "0")
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
index 282915b45..f73f67b19 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/data/LoanScheduleParams.java
@@ -180,7 +180,7 @@ public final class LoanScheduleParams {
         final Money principalToBeScheduled = null;
         final Money outstandingBalance = null;
         final Money outstandingBalanceAsPerRest = null;
-        final List<LoanRepaymentScheduleInstallment> installments = null;
+        final List<LoanRepaymentScheduleInstallment> installments = new 
ArrayList<>();
         final boolean partialUpdate = false;
         final int loanTermInDays = 0;
         final Money totalOutstandingInterestPaymentDueToGrace = null;
@@ -266,6 +266,10 @@ public final class LoanScheduleParams {
         return this.periodNumber;
     }
 
+    public void setPeriodNumber(int periodNumber) {
+        this.periodNumber = periodNumber;
+    }
+
     public int getInstalmentNumber() {
         return this.instalmentNumber;
     }
@@ -274,12 +278,20 @@ public final class LoanScheduleParams {
         return this.actualRepaymentDate;
     }
 
+    public void setActualRepaymentDate(LocalDate actualRepaymentDate) {
+        this.actualRepaymentDate = actualRepaymentDate;
+    }
+
     public Money getTotalCumulativePrincipal() {
         return this.totalCumulativePrincipal;
     }
 
     public void addTotalCumulativePrincipal(final Money 
totalCumulativePrincipal) {
-        this.totalCumulativePrincipal = 
this.totalCumulativePrincipal.plus(totalCumulativePrincipal);
+        if (this.totalCumulativePrincipal != null) {
+            this.totalCumulativePrincipal = 
this.totalCumulativePrincipal.plus(totalCumulativePrincipal);
+        } else {
+            this.totalCumulativePrincipal = totalCumulativePrincipal;
+        }
     }
 
     public Money getTotalCumulativeInterest() {
@@ -287,7 +299,11 @@ public final class LoanScheduleParams {
     }
 
     public void addTotalCumulativeInterest(final Money 
totalCumulativeInterest) {
-        this.totalCumulativeInterest = 
this.totalCumulativeInterest.plus(totalCumulativeInterest);
+        if (this.totalCumulativeInterest != null) {
+            this.totalCumulativeInterest = 
this.totalCumulativeInterest.plus(totalCumulativeInterest);
+        } else {
+            this.totalCumulativeInterest = totalCumulativeInterest;
+        }
     }
 
     public Money getTotalFeeChargesCharged() {
@@ -295,7 +311,11 @@ public final class LoanScheduleParams {
     }
 
     public void addTotalFeeChargesCharged(final Money totalFeeChargesCharged) {
-        this.totalFeeChargesCharged = 
this.totalFeeChargesCharged.plus(totalFeeChargesCharged);
+        if (this.totalFeeChargesCharged != null) {
+            this.totalFeeChargesCharged = 
this.totalFeeChargesCharged.plus(totalFeeChargesCharged);
+        } else {
+            this.totalFeeChargesCharged = totalFeeChargesCharged;
+        }
     }
 
     public Money getTotalPenaltyChargesCharged() {
@@ -303,7 +323,11 @@ public final class LoanScheduleParams {
     }
 
     public void addTotalPenaltyChargesCharged(final Money 
totalPenaltyChargesCharged) {
-        this.totalPenaltyChargesCharged = 
this.totalPenaltyChargesCharged.plus(totalPenaltyChargesCharged);
+        if (this.totalPenaltyChargesCharged != null) {
+            this.totalPenaltyChargesCharged = 
this.totalPenaltyChargesCharged.plus(totalPenaltyChargesCharged);
+        } else {
+            this.totalPenaltyChargesCharged = totalPenaltyChargesCharged;
+        }
     }
 
     public Money getTotalRepaymentExpected() {
@@ -311,13 +335,21 @@ public final class LoanScheduleParams {
     }
 
     public void addTotalRepaymentExpected(final Money totalRepaymentExpected) {
-        this.totalRepaymentExpected = 
this.totalRepaymentExpected.plus(totalRepaymentExpected);
+        if (this.totalRepaymentExpected != null) {
+            this.totalRepaymentExpected = 
this.totalRepaymentExpected.plus(totalRepaymentExpected);
+        } else {
+            this.totalRepaymentExpected = totalRepaymentExpected;
+        }
     }
 
     public Money getReducePrincipal() {
         return this.reducePrincipal;
     }
 
+    public void setReducePrincipal(Money reducePrincipal) {
+        this.reducePrincipal = reducePrincipal;
+    }
+
     public Map<LocalDate, Money> getPrincipalPortionMap() {
         return this.principalPortionMap;
     }
@@ -338,10 +370,18 @@ public final class LoanScheduleParams {
         return this.outstandingBalance;
     }
 
+    public void setOutstandingBalance(Money outstandingBalance) {
+        this.outstandingBalance = outstandingBalance;
+    }
+
     public Money getOutstandingBalanceAsPerRest() {
         return this.outstandingBalanceAsPerRest;
     }
 
+    public void setOutstandingBalanceAsPerRest(Money 
outstandingBalanceAsPerRest) {
+        this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
+    }
+
     public List<LoanRepaymentScheduleInstallment> getInstallments() {
         return this.installments;
     }
@@ -366,12 +406,16 @@ public final class LoanScheduleParams {
         return this.periodStartDate;
     }
 
+    public void setPeriodStartDate(LocalDate periodStartDate) {
+        this.periodStartDate = periodStartDate;
+    }
+
     public Money getPrincipalToBeScheduled() {
         return this.principalToBeScheduled;
     }
 
-    public void setPeriodNumber(int periodNumber) {
-        this.periodNumber = periodNumber;
+    public void setPrincipalToBeScheduled(Money principalToBeScheduled) {
+        this.principalToBeScheduled = principalToBeScheduled;
     }
 
     public void incrementPeriodNumber() {
@@ -382,56 +426,54 @@ public final class LoanScheduleParams {
         this.instalmentNumber++;
     }
 
-    public void setPeriodStartDate(LocalDate periodStartDate) {
-        this.periodStartDate = periodStartDate;
-    }
-
-    public void setActualRepaymentDate(LocalDate actualRepaymentDate) {
-        this.actualRepaymentDate = actualRepaymentDate;
-    }
-
-    public void setReducePrincipal(Money reducePrincipal) {
-        this.reducePrincipal = reducePrincipal;
-    }
-
     public void addReducePrincipal(Money reducePrincipal) {
-        this.reducePrincipal = this.reducePrincipal.plus(reducePrincipal);
+        if (this.reducePrincipal != null) {
+            this.reducePrincipal = this.reducePrincipal.plus(reducePrincipal);
+        } else {
+            this.reducePrincipal = reducePrincipal;
+        }
     }
 
     public void reduceReducePrincipal(Money reducePrincipal) {
-        this.reducePrincipal = this.reducePrincipal.minus(reducePrincipal);
-    }
-
-    public void setPrincipalToBeScheduled(Money principalToBeScheduled) {
-        this.principalToBeScheduled = principalToBeScheduled;
+        if (this.reducePrincipal != null) {
+            this.reducePrincipal = this.reducePrincipal.minus(reducePrincipal);
+        }
     }
 
     public void addPrincipalToBeScheduled(Money principalToBeScheduled) {
-        this.principalToBeScheduled = 
this.principalToBeScheduled.plus(principalToBeScheduled);
-    }
-
-    public void setOutstandingBalance(Money outstandingBalance) {
-        this.outstandingBalance = outstandingBalance;
+        if (this.principalToBeScheduled != null) {
+            this.principalToBeScheduled = 
this.principalToBeScheduled.plus(principalToBeScheduled);
+        } else {
+            this.principalToBeScheduled = principalToBeScheduled;
+        }
     }
 
     public void addOutstandingBalance(Money outstandingBalance) {
-        this.outstandingBalance = 
this.outstandingBalance.plus(outstandingBalance);
+        if (this.outstandingBalance != null) {
+            this.outstandingBalance = 
this.outstandingBalance.plus(outstandingBalance);
+        } else {
+            this.outstandingBalance = outstandingBalance;
+        }
     }
 
     public void reduceOutstandingBalance(Money outstandingBalance) {
-        this.outstandingBalance = 
this.outstandingBalance.minus(outstandingBalance);
-    }
-
-    public void setOutstandingBalanceAsPerRest(Money 
outstandingBalanceAsPerRest) {
-        this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
+        if (this.outstandingBalance != null) {
+            this.outstandingBalance = 
this.outstandingBalance.minus(outstandingBalance);
+        }
     }
 
     public void addOutstandingBalanceAsPerRest(Money 
outstandingBalanceAsPerRest) {
-        this.outstandingBalanceAsPerRest = 
this.outstandingBalanceAsPerRest.plus(outstandingBalanceAsPerRest);
+        if (this.outstandingBalanceAsPerRest != null) {
+            this.outstandingBalanceAsPerRest = 
this.outstandingBalanceAsPerRest.plus(outstandingBalanceAsPerRest);
+        } else {
+            this.outstandingBalanceAsPerRest = outstandingBalanceAsPerRest;
+        }
     }
 
     public void reduceOutstandingBalanceAsPerRest(Money 
outstandingBalanceAsPerRest) {
-        this.outstandingBalanceAsPerRest = 
this.outstandingBalanceAsPerRest.minus(outstandingBalanceAsPerRest);
+        if (this.outstandingBalanceAsPerRest != null) {
+            this.outstandingBalanceAsPerRest = 
this.outstandingBalanceAsPerRest.minus(outstandingBalanceAsPerRest);
+        }
     }
 
     public int getLoanTermInDays() {
@@ -466,16 +508,22 @@ public final class LoanScheduleParams {
         return this.unCompoundedAmount;
     }
 
-    public void addUnCompoundedAmount(Money unCompoundedAmount) {
-        this.unCompoundedAmount = 
this.unCompoundedAmount.plus(unCompoundedAmount);
+    public void setUnCompoundedAmount(Money unCompoundedAmount) {
+        this.unCompoundedAmount = unCompoundedAmount;
     }
 
-    public void minusUnCompoundedAmount(Money unCompoundedAmount) {
-        this.unCompoundedAmount = 
this.unCompoundedAmount.minus(unCompoundedAmount);
+    public void addUnCompoundedAmount(Money unCompoundedAmount) {
+        if (this.unCompoundedAmount != null) {
+            this.unCompoundedAmount = 
this.unCompoundedAmount.plus(unCompoundedAmount);
+        } else {
+            this.unCompoundedAmount = unCompoundedAmount;
+        }
     }
 
-    public void setUnCompoundedAmount(Money unCompoundedAmount) {
-        this.unCompoundedAmount = unCompoundedAmount;
+    public void minusUnCompoundedAmount(Money unCompoundedAmount) {
+        if (this.unCompoundedAmount != null) {
+            this.unCompoundedAmount = 
this.unCompoundedAmount.minus(unCompoundedAmount);
+        }
     }
 
     public boolean isFirstPeriod() {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
index 957ede516..d2acafeee 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
@@ -132,18 +132,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                 loanApplicationTerms.getLoanCalendar(), 
loanApplicationTerms.getHolidayDetailDTO(), loanApplicationTerms);
 
         if (!scheduleParams.isPartialUpdate()) {
-            Money downPaymentAmount = Money.zero(currency);
-            if (loanApplicationTerms.isDownPaymentEnabled()) {
-                downPaymentAmount = Money.of(currency, 
MathUtil.percentageOf(scheduleParams.getOutstandingBalance().getAmount(),
-                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
-                if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() 
!= null) {
-                    downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount,
-                            
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
-                }
-
-            }
-            Money calculatedAmortizableAmount = 
loanApplicationTerms.getPrincipal().minus(downPaymentAmount);
-            scheduleParams.reduceOutstandingBalance(downPaymentAmount);
+            Money calculatedAmortizableAmount = 
loanApplicationTerms.getPrincipal().minus(loanApplicationTerms.getDownPaymentAmount());
             // Set Fixed Principal Amount
             updateAmortization(mc, loanApplicationTerms, 
scheduleParams.getPeriodNumber(), calculatedAmortizableAmount);
 
@@ -161,9 +150,9 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                 }
                 Money remainingPrincipalAmt = 
disburseAmt.minus(downPaymentAmt);
                 
scheduleParams.setPrincipalToBeScheduled(remainingPrincipalAmt);
-                loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
                 scheduleParams.setOutstandingBalance(remainingPrincipalAmt);
                 
scheduleParams.setOutstandingBalanceAsPerRest(remainingPrincipalAmt);
+                loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
             }
         }
 
@@ -305,7 +294,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                     
scheduleParams.getTotalCumulativePrincipal().minus(scheduleParams.getReducePrincipal()),
                     scheduleParams.getTotalCumulativeInterest(), 
loanApplicationTerms.getTotalInterestDue(),
                     
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(), 
scheduleParams.getOutstandingBalanceAsPerRest(),
-                    loanApplicationTerms, scheduleParams.getPeriodNumber(), 
mc, mergeVariationsToMap(scheduleParams),
+                    loanApplicationTerms, scheduleParams.getPeriodNumber(), 
mc, mergeVariationsToMap(loanApplicationTerms, scheduleParams),
                     scheduleParams.getCompoundingMap(), 
periodStartDateApplicableForInterest, scheduledDueDate, interestRates);
 
             // will check for EMI amount greater than interest calculated
@@ -427,10 +416,11 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
         updateCompoundingDetails(periods, scheduleParams, 
loanApplicationTerms);
         return LoanScheduleModel.from(periods, applicationCurrency, 
scheduleParams.getLoanTermInDays(),
-                scheduleParams.getPrincipalToBeScheduled(), 
scheduleParams.getTotalCumulativePrincipal().getAmount(), totalPrincipalPaid,
-                scheduleParams.getTotalCumulativeInterest().getAmount(), 
scheduleParams.getTotalFeeChargesCharged().getAmount(),
-                scheduleParams.getTotalPenaltyChargesCharged().getAmount(), 
scheduleParams.getTotalRepaymentExpected().getAmount(),
-                totalOutstanding);
+                
scheduleParams.getPrincipalToBeScheduled().plus(loanApplicationTerms.getDownPaymentAmount()),
+                
scheduleParams.getTotalCumulativePrincipal().plus(loanApplicationTerms.getDownPaymentAmount()).getAmount(),
+                totalPrincipalPaid, 
scheduleParams.getTotalCumulativeInterest().getAmount(),
+                scheduleParams.getTotalFeeChargesCharged().getAmount(), 
scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
+                scheduleParams.getTotalRepaymentExpected().getAmount(), 
totalOutstanding);
     }
 
     private void updateCompoundingDetails(final 
Collection<LoanScheduleModelPeriod> periods, final LoanScheduleParams params,
@@ -510,7 +500,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
         updateCompoundingMap(loanApplicationTerms, holidayDetailDTO, 
scheduleParams, lastRestDate, scheduledDueDate);
 
         // update outstanding balance for interest calculation
-        updateOutstandingBalanceAsPerRest(scheduleParams, scheduledDueDate);
+        updateOutstandingBalanceAsPerRest(loanApplicationTerms, 
scheduleParams, scheduledDueDate);
     }
 
     private LoanScheduleModelPeriod handleRecalculationForTransactions(final 
MathContext mc,
@@ -630,8 +620,8 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                     interestCalculationGraceOnRepaymentPeriodFraction, 
scheduleParams.getTotalCumulativePrincipal(),
                     scheduleParams.getTotalCumulativeInterest(), 
totalInterestChargedForFullLoanTerm,
                     lastTotalOutstandingInterestPaymentDueToGrace, 
scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
-                    scheduleParams.getPeriodNumber(), mc, 
mergeVariationsToMap(scheduleParams), scheduleParams.getCompoundingMap(),
-                    periodStartDateApplicableForInterest, calculateTill, 
interestRates);
+                    scheduleParams.getPeriodNumber(), mc, 
mergeVariationsToMap(loanApplicationTerms, scheduleParams),
+                    scheduleParams.getCompoundingMap(), 
periodStartDateApplicableForInterest, calculateTill, interestRates);
             
loanApplicationTerms.updateAnnualNominalInterestRate(currentInterestRate);
 
             // applies charges for the period
@@ -767,7 +757,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                                         
scheduleParams.getTotalCumulativeInterest(), 
totalInterestChargedForFullLoanTerm,
                                         
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(),
                                         
scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
-                                        scheduleParams.getPeriodNumber(), mc, 
mergeVariationsToMap(scheduleParams),
+                                        scheduleParams.getPeriodNumber(), mc, 
mergeVariationsToMap(loanApplicationTerms, scheduleParams),
                                         scheduleParams.getCompoundingMap(), 
periodStartDateApplicableForInterest, transactionDate,
                                         interestRates);
                                 interestForCurrentInstallment = 
principalInterestForThisPeriod.interest();
@@ -805,7 +795,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
                             // update outstanding balance for interest
                             // calculation as per the rest
-                            updateOutstandingBalanceAsPerRest(scheduleParams, 
transactionDate);
+                            
updateOutstandingBalanceAsPerRest(loanApplicationTerms, scheduleParams, 
transactionDate);
 
                             // handle cumulative fields
                             scheduleParams.addLoanTermInDays(periodDays);
@@ -898,9 +888,9 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                                             
scheduleParams.getTotalCumulativeInterest(), 
totalInterestChargedForFullLoanTerm,
                                             
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(),
                                             
scheduleParams.getOutstandingBalanceAsPerRest(), loanApplicationTerms,
-                                            scheduleParams.getPeriodNumber(), 
mc, mergeVariationsToMap(scheduleParams),
-                                            
scheduleParams.getCompoundingMap(), periodStartDateApplicableForInterest, 
transactionDate,
-                                            interestRates);
+                                            scheduleParams.getPeriodNumber(), 
mc,
+                                            
mergeVariationsToMap(loanApplicationTerms, scheduleParams), 
scheduleParams.getCompoundingMap(),
+                                            
periodStartDateApplicableForInterest, transactionDate, interestRates);
                                     if 
(!principalInterestForThisPeriod.interest()
                                             
.plus(principalInterestForThisPeriod.interestPaymentDueToGrace())
                                             
.plus(scheduleParams.getOutstandingBalance()).isGreaterThan(unprocessed)) {
@@ -971,11 +961,37 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
         
scheduleParams.addTotalCumulativePrincipal(unprocessed.plus(addToPrincipal));
     }
 
-    private void updateOutstandingBalanceAsPerRest(final LoanScheduleParams 
scheduleParams, final LocalDate scheduledDueDate) {
+    private void updateOutstandingBalanceAsPerRest(LoanApplicationTerms 
loanApplicationTerms, final LoanScheduleParams scheduleParams,
+            final LocalDate scheduledDueDate) {
         
scheduleParams.setOutstandingBalanceAsPerRest(updateBalanceForInterestCalculation(scheduleParams.getPrincipalPortionMap(),
-                scheduledDueDate, 
scheduleParams.getOutstandingBalanceAsPerRest(), false));
-        
scheduleParams.setOutstandingBalanceAsPerRest(updateBalanceForInterestCalculation(scheduleParams.getDisburseDetailMap(),
-                scheduledDueDate, 
scheduleParams.getOutstandingBalanceAsPerRest(), true));
+                scheduledDueDate, 
scheduleParams.getOutstandingBalanceAsPerRest()));
+        
scheduleParams.setOutstandingBalanceAsPerRest(calculateOutstandingBalanceAsPerRest(loanApplicationTerms,
+                scheduleParams.getDisburseDetailMap(), scheduledDueDate, 
scheduleParams.getOutstandingBalanceAsPerRest()));
+    }
+
+    private Money calculateOutstandingBalanceAsPerRest(LoanApplicationTerms 
loanApplicationTerms, Map<LocalDate, Money> disburseDetailMap,
+            LocalDate scheduledDueDate, Money outstandingBalance) {
+        List<LocalDate> removeFromMap = new ArrayList<>();
+        for (Map.Entry<LocalDate, Money> entry : disburseDetailMap.entrySet()) 
{
+            if (!DateUtils.isAfter(entry.getKey(), scheduledDueDate)) {
+                Money downPaymentAmount = 
Money.zero(loanApplicationTerms.getCurrency());
+                if (loanApplicationTerms.isDownPaymentEnabled()) {
+                    downPaymentAmount = 
Money.of(loanApplicationTerms.getCurrency(), 
MathUtil.percentageOf(entry.getValue().getAmount(),
+                            
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
+                    if 
(loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
+                        downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount,
+                                
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+                    }
+                }
+                outstandingBalance = 
outstandingBalance.plus(entry.getValue()).minus(downPaymentAmount);
+
+                removeFromMap.add(entry.getKey());
+            }
+        }
+        for (LocalDate date : removeFromMap) {
+            disburseDetailMap.remove(date);
+        }
+        return outstandingBalance;
     }
 
     /**
@@ -1305,7 +1321,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
         } else {
             principalToBeScheduled = loanApplicationTerms.getPrincipal();
         }
-        return principalToBeScheduled;
+        return 
principalToBeScheduled.minus(loanApplicationTerms.getDownPaymentAmount());
     }
 
     private boolean updateFixedInstallmentAmount(final MathContext mc, final 
LoanApplicationTerms loanApplicationTerms, int periodNumber,
@@ -1389,8 +1405,8 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                     PrincipalInterest principalInterestForThisPeriod = 
calculatePrincipalInterestComponentsForPeriod(
                             getPaymentPeriodsInOneYearCalculator(), 
interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(),
                             totalInterest.zero(), totalInterest.zero(), 
totalInterest.zero(), outstanding, loanApplicationTerms,
-                            periodNumberTemp, mc, 
mergeVariationsToMap(params), params.getCompoundingMap(), 
params.getPeriodStartDate(),
-                            transactionDate, applicableVariations);
+                            periodNumberTemp, mc, 
mergeVariationsToMap(loanApplicationTerms, params), params.getCompoundingMap(),
+                            params.getPeriodStartDate(), transactionDate, 
applicableVariations);
 
                     Money interest = principalInterestForThisPeriod.interest();
                     totalInterest = totalInterest.plus(interest);
@@ -1421,7 +1437,7 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                     outstanding = outstanding.zero();
                 } else {
                     outstanding = 
updateBalanceForInterestCalculation(params.getPrincipalPortionMap(), 
params.getPeriodStartDate(),
-                            outstanding, false);
+                            outstanding);
                 }
                 if (params.getLatePaymentMap().isEmpty() && 
outstanding.isZero()) {
                     break;
@@ -1432,8 +1448,8 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                 PrincipalInterest principalInterestForThisPeriod = 
calculatePrincipalInterestComponentsForPeriod(
                         getPaymentPeriodsInOneYearCalculator(), 
interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(),
                         totalInterest.zero(), totalInterest.zero(), 
totalInterest.zero(), outstanding, loanApplicationTerms,
-                        periodNumberTemp, mc, mergeVariationsToMap(params), 
params.getCompoundingMap(), params.getPeriodStartDate(),
-                        params.getActualRepaymentDate(), applicableVariations);
+                        periodNumberTemp, mc, 
mergeVariationsToMap(loanApplicationTerms, params), params.getCompoundingMap(),
+                        params.getPeriodStartDate(), 
params.getActualRepaymentDate(), applicableVariations);
                 Money interest = principalInterestForThisPeriod.interest();
                 totalInterest = totalInterest.plus(interest);
 
@@ -1562,16 +1578,12 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
      * Identifies all the past date principal changes and apply them on 
outstanding balance for future calculations
      */
     private Money updateBalanceForInterestCalculation(final Map<LocalDate, 
Money> principalPortionMap, final LocalDate scheduledDueDate,
-            final Money outstandingBalanceAsPerRest, boolean addMapDetails) {
+            final Money outstandingBalanceAsPerRest) {
         List<LocalDate> removeFromPrincipalPortionMap = new ArrayList<>();
         Money outstandingBalance = outstandingBalanceAsPerRest;
         for (Map.Entry<LocalDate, Money> principal : 
principalPortionMap.entrySet()) {
             if (!DateUtils.isAfter(principal.getKey(), scheduledDueDate)) {
-                if (addMapDetails) {
-                    outstandingBalance = 
outstandingBalance.plus(principal.getValue());
-                } else {
-                    outstandingBalance = 
outstandingBalance.minus(principal.getValue());
-                }
+                outstandingBalance = 
outstandingBalance.minus(principal.getValue());
                 removeFromPrincipalPortionMap.add(principal.getKey());
             }
         }
@@ -1852,13 +1864,22 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
      * as per rest) changes to single map for interest calculation
      *
      */
-    private TreeMap<LocalDate, Money> mergeVariationsToMap(final 
LoanScheduleParams params) {
+    private TreeMap<LocalDate, Money> 
mergeVariationsToMap(LoanApplicationTerms loanApplicationTerms, final 
LoanScheduleParams params) {
         TreeMap<LocalDate, Money> map = new 
TreeMap<>(params.getLatePaymentMap());
         for (Map.Entry<LocalDate, Money> mapEntry : 
params.getDisburseDetailMap().entrySet()) {
             Money value = mapEntry.getValue();
             if (map.containsKey(mapEntry.getKey())) {
                 value = value.plus(map.get(mapEntry.getKey()));
             }
+            if (loanApplicationTerms.isDownPaymentEnabled()) {
+                Money downPaymentAmount = 
Money.of(loanApplicationTerms.getCurrency(),
+                        MathUtil.percentageOf(value.getAmount(), 
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
+                if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() 
!= null) {
+                    downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount,
+                            
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+                }
+                value = value.minus(downPaymentAmount);
+            }
             map.put(mapEntry.getKey(), value);
         }
 
@@ -2235,33 +2256,30 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
             LocalDate periodStartDate = 
RepaymentStartDateType.DISBURSEMENT_DATE.equals(loanApplicationTerms.getRepaymentStartDateType())
                     ? loanApplicationTerms.getExpectedDisbursementDate()
                     : loanApplicationTerms.getSubmittedOnDate();
-            Money downPaymentAmount = Money.zero(currency);
-            if (loanApplicationTerms.isDownPaymentEnabled()) {
-                downPaymentAmount = Money.of(currency, 
MathUtil.percentageOf(loanScheduleParams.getOutstandingBalance().getAmount(),
-                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
-                if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() 
!= null) {
-                    downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount,
-                            
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
-                }
-            }
-            Money calculatedAmortizableAmount = 
principalToBeScheduled.minus(downPaymentAmount);
-            
loanScheduleParams.setOutstandingBalance(calculatedAmortizableAmount);
             // Set fixed Amortization Amounts(either EMI or Principal )
-            updateAmortization(mc, loanApplicationTerms, periodNumber, 
calculatedAmortizableAmount);
+            updateAmortization(mc, loanApplicationTerms, periodNumber, 
outstandingBalance);
 
             // count periods without interest grace to exclude for flat loan
             // calculations
 
             final Map<LocalDate, Money> disburseDetailMap = new HashMap<>();
             if (loanApplicationTerms.isMultiDisburseLoan()) {
-                // fetches the first tranche amount and also updates other
-                // tranche
-                // details to map
-                BigDecimal disburseAmt = 
getDisbursementAmount(loanApplicationTerms, 
loanApplicationTerms.getExpectedDisbursementDate(),
-                        disburseDetailMap, true);
-                outstandingBalance = 
outstandingBalance.zero().plus(disburseAmt);
-                outstandingBalanceAsPerRest = outstandingBalance;
-                principalToBeScheduled = 
principalToBeScheduled.zero().plus(disburseAmt);
+                /* fetches the first tranche amount and also updates other 
tranche details to map */
+                Money disburseAmt = Money.of(currency,
+                        getDisbursementAmount(loanApplicationTerms, 
loanApplicationTerms.getExpectedDisbursementDate(), disburseDetailMap,
+                                
loanScheduleParams.applyInterestRecalculation()));
+                Money downPaymentAmt = Money.zero(currency);
+                if (loanApplicationTerms.isDownPaymentEnabled()) {
+                    downPaymentAmt = Money.of(currency, 
MathUtil.percentageOf(disburseAmt.getAmount(),
+                            
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
+                    if 
(loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
+                        downPaymentAmt = 
Money.roundToMultiplesOf(downPaymentAmt, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+                    }
+                }
+                Money remainingPrincipalAmt = 
disburseAmt.minus(downPaymentAmt);
+                outstandingBalance = remainingPrincipalAmt;
+                outstandingBalanceAsPerRest = remainingPrincipalAmt;
+                principalToBeScheduled = remainingPrincipalAmt;
             }
             int loanTermInDays = 0;
 
@@ -2279,6 +2297,12 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
             // This will create the recalculation details by applying the
             // transactions
             for (LoanRepaymentScheduleInstallment installment : 
processInstallmentsInstallments) {
+                if (installment.isDownPayment()) {
+                    instalmentNumber++;
+                    
periods.add(createLoanScheduleModelDownPaymentPeriod(installment, 
outstandingBalance));
+                    newRepaymentScheduleInstallments.add(installment);
+                    continue;
+                }
                 // this will generate the next schedule due date and allows to
                 // process the installment only if recalculate from date is
                 // greater than due date
@@ -2442,9 +2466,9 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
                     // update outstanding balance for interest calculation
                     outstandingBalanceAsPerRest = 
updateBalanceForInterestCalculation(principalPortionMap, 
installment.getDueDate(),
-                            outstandingBalanceAsPerRest, false);
-                    outstandingBalanceAsPerRest = 
updateBalanceForInterestCalculation(disburseDetailMap, installment.getDueDate(),
-                            outstandingBalanceAsPerRest, true);
+                            outstandingBalanceAsPerRest);
+                    outstandingBalanceAsPerRest = 
calculateOutstandingBalanceAsPerRest(loanApplicationTerms, disburseDetailMap,
+                            installment.getDueDate(), 
outstandingBalanceAsPerRest);
                     // updates the map with over due amounts
                     updateLatePaymentsToMap(loanApplicationTerms, 
holidayDetailDTO, currency, latePaymentMap, lastInstallmentDate,
                             newRepaymentScheduleInstallments, true, 
lastRestDate);
@@ -2692,6 +2716,13 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
         return installment;
     }
 
+    private LoanScheduleModelPeriod 
createLoanScheduleModelDownPaymentPeriod(final LoanRepaymentScheduleInstallment 
installment,
+            final Money outstandingPrincipal) {
+        final MonetaryCurrency currency = outstandingPrincipal.getCurrency();
+        return 
LoanScheduleModelDownPaymentPeriod.downPayment(installment.getInstallmentNumber(),
 installment.getDueDate(),
+                installment.getPrincipal(currency), outstandingPrincipal);
+    }
+
     private LoanScheduleModelPeriod createLoanScheduleModelPeriod(final 
LoanRepaymentScheduleInstallment installment,
             final Money outstandingPrincipal) {
         final MonetaryCurrency currency = outstandingPrincipal.getCurrency();
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
index 2399093a6..a5738aec0 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractProgressiveLoanScheduleGenerator.java
@@ -188,10 +188,11 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
         final BigDecimal totalOutstanding = BigDecimal.ZERO;
 
         return LoanScheduleModel.from(periods, applicationCurrency, 
scheduleParams.getLoanTermInDays(),
-                scheduleParams.getPrincipalToBeScheduled(), 
scheduleParams.getTotalCumulativePrincipal().getAmount(), totalPrincipalPaid,
-                scheduleParams.getTotalCumulativeInterest().getAmount(), 
scheduleParams.getTotalFeeChargesCharged().getAmount(),
-                scheduleParams.getTotalPenaltyChargesCharged().getAmount(), 
scheduleParams.getTotalRepaymentExpected().getAmount(),
-                totalOutstanding);
+                
scheduleParams.getPrincipalToBeScheduled().plus(loanApplicationTerms.getDownPaymentAmount()),
+                
scheduleParams.getTotalCumulativePrincipal().plus(loanApplicationTerms.getDownPaymentAmount()).getAmount(),
+                totalPrincipalPaid, 
scheduleParams.getTotalCumulativeInterest().getAmount(),
+                scheduleParams.getTotalFeeChargesCharged().getAmount(), 
scheduleParams.getTotalPenaltyChargesCharged().getAmount(),
+                scheduleParams.getTotalRepaymentExpected().getAmount(), 
totalOutstanding);
     }
 
     @Override
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index f34269cf7..b6c15d85f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -23,7 +23,6 @@ import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import java.math.BigDecimal;
 import java.math.MathContext;
-import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
@@ -675,8 +674,7 @@ public class LoanScheduleAssembler {
 
         final Set<LoanCharge> loanCharges = 
this.loanChargeAssembler.fromParsedJson(element, disbursementDetails);
 
-        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-        final MathContext mc = new MathContext(8, roundingMode);
+        final MathContext mc = MoneyHelper.getMathContext();
         HolidayDetailDTO detailDTO = new HolidayDetailDTO(isHolidayEnabled, 
holidays, workingDays);
 
         LoanScheduleGenerator loanScheduleGenerator = 
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
@@ -703,8 +701,8 @@ public class LoanScheduleAssembler {
     public LoanScheduleModel assembleForInterestRecalculation(final 
LoanApplicationTerms loanApplicationTerms, final Long officeId,
             Loan loan, final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor,
             final LocalDate rescheduleFrom) {
-        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-        final MathContext mc = new MathContext(8, roundingMode);
+
+        final MathContext mc = MoneyHelper.getMathContext();
         final boolean isHolidayEnabled = 
this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
 
         final List<Holiday> holidays = 
this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
@@ -723,8 +721,8 @@ public class LoanScheduleAssembler {
             final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor) {
         final LoanScheduleGenerator loanScheduleGenerator = 
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
                 loanApplicationTerms.getInterestMethod());
-        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-        final MathContext mc = new MathContext(8, roundingMode);
+
+        final MathContext mc = MoneyHelper.getMathContext();
 
         final boolean isHolidayEnabled = 
this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
         final List<Holiday> holidays = 
this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
index d326f5a7c..e8df96f89 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanReschedulePreviewPlatformServiceImpl.java
@@ -19,7 +19,6 @@
 package org.apache.fineract.portfolio.loanaccount.rescheduleloan.service;
 
 import java.math.MathContext;
-import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.List;
@@ -127,8 +126,8 @@ public class LoanReschedulePreviewPlatformServiceImpl 
implements LoanRescheduleP
         }
 
         
loanApplicationTerms.getLoanTermVariations().updateLoanTermVariationsData(loanTermVariationsData);
-        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-        final MathContext mathContext = new MathContext(8, roundingMode);
+
+        final MathContext mathContext = MoneyHelper.getMathContext();
         final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = 
this.loanRepaymentScheduleTransactionProcessorFactory
                 .determineProcessor(loan.transactionProcessingStrategy());
         final LoanScheduleGenerator loanScheduleGenerator = 
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
index 3c0d41236..05a98e07e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/service/LoanRescheduleRequestWritePlatformServiceImpl.java
@@ -20,7 +20,6 @@ package 
org.apache.fineract.portfolio.loanaccount.rescheduleloan.service;
 
 import java.math.BigDecimal;
 import java.math.MathContext;
-import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
@@ -432,8 +431,7 @@ public class LoanRescheduleRequestWritePlatformServiceImpl 
implements LoanResche
              * loanTermVariation.setApplicableFromDate(adjustedDate); } } }
              */
 
-            final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
-            final MathContext mathContext = new MathContext(8, roundingMode);
+            final MathContext mathContext = MoneyHelper.getMathContext();
             final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = 
this.loanRepaymentScheduleTransactionProcessorFactory
                     .determineProcessor(loan.transactionProcessingStrategy());
             final LoanScheduleGenerator loanScheduleGenerator = 
this.loanScheduleFactory.create(loanApplicationTerms.getLoanScheduleType(),
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
index e587e126d..e47ed1dcc 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
@@ -124,7 +124,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -192,7 +192,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -259,7 +259,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -327,7 +327,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -414,7 +414,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -498,7 +498,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -580,7 +580,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -666,7 +666,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -735,7 +735,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -818,7 +818,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -878,7 +878,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -947,7 +947,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1030,7 +1030,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1115,7 +1115,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1197,7 +1197,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1253,7 +1253,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1309,7 +1309,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("15 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1365,7 +1365,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("20 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1458,7 +1458,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("20 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1572,7 +1572,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
         runAt("20 February 2023", () -> {
 
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1645,7 +1645,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1724,7 +1724,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1815,7 +1815,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1881,7 +1881,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1960,7 +1960,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.VERTICAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 
January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2065,15 +2065,16 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             assertNotNull(localLoanProductId);
 
             CallFailedRuntimeException exception = 
assertThrows(CallFailedRuntimeException.class,
-                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
-                            "01 January 2023", "01 January 2023", 
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
-                            LoanScheduleType.PROGRESSIVE.name(), 
LoanScheduleProcessingType.VERTICAL.name()));
+                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
+                            BigDecimal.ZERO, "01 January 2023", "01 January 
2023",
+                            
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE, 
LoanScheduleType.PROGRESSIVE.name(),
+                            LoanScheduleProcessingType.VERTICAL.name()));
             assertEquals(400, exception.getResponse().code());
             
assertTrue(exception.getMessage().contains("supported.only.with.advanced.payment.allocation.strategy"));
 
             exception = assertThrows(CallFailedRuntimeException.class,
-                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
-                            "01 January 2023", "01 January 2023",
+                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
+                            BigDecimal.ZERO, "01 January 2023", "01 January 
2023",
                             
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
                             LoanScheduleType.PROGRESSIVE.name(), 
LoanScheduleProcessingType.HORIZONTAL.name()));
             assertEquals(400, exception.getResponse().code());
@@ -2099,7 +2100,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             assertNotNull(localLoanProductId);
 
             PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(1000), 45,
-                    15, 3, 0, "01 January 2023", "01 January 2023");
+                    15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 
2023");
 
             GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
             validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
@@ -2128,8 +2129,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
 
-            loanResponse = applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
-                    "01 January 2023", "01 January 2023");
+            loanResponse = applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
+                    BigDecimal.ZERO, "01 January 2023", "01 January 2023");
 
             loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
             validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
@@ -2187,7 +2188,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             assertNotNull(localLoanProductId);
 
             PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(1000), 45,
-                    15, 3, 0, "01 January 2023", "01 January 2023");
+                    15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 
2023");
 
             GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
             validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
@@ -2216,8 +2217,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
 
-            loanResponse = applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
-                    "01 January 2023", "01 January 2023");
+            loanResponse = applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
+                    BigDecimal.ZERO, "01 January 2023", "01 January 2023");
 
             loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
             validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
@@ -2275,7 +2276,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             assertNotNull(localLoanProductId);
 
             PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(40.50),
-                    45, 15, 3, 0, "01 January 2023", "01 January 2023");
+                    45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 
2023");
 
             GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
             validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
@@ -2326,7 +2327,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             assertNotNull(localLoanProductId);
 
             PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(40.50),
-                    45, 15, 3, 0, "01 January 2023", "01 January 2023");
+                    45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 
2023");
 
             GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
             validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
@@ -2380,7 +2381,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 
2023", "01 September 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 September 2023", "01 September 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2486,7 +2487,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.VERTICAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 
2023", "01 September 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 September 2023", "01 September 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2591,7 +2592,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 
2023", "01 September 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 September 2023", "01 September 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2696,7 +2697,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.VERTICAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 September 
2023", "01 September 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 September 2023", "01 September 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2795,7 +2796,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2881,7 +2882,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -2970,7 +2971,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
             Integer localLoanProductId = createLoanProduct("1000", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
             final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
-                    BigDecimal.valueOf(1000.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
+                    BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, 
"01 January 2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -3205,7 +3206,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
     }
 
     private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final BigDecimal principal,
-            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
+            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final BigDecimal interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate, String transactionProcessorCode, String loanScheduleType,
             String loanScheduleProcessingType) {
         LOG.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");
@@ -3220,7 +3221,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
     }
 
     private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final BigDecimal principal,
-            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
+            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final BigDecimal interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate) {
         LOG.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");
         return applyForLoanApplication(clientId, loanProductId, principal, 
loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index a510eaf23..12a7a81de 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -128,14 +128,14 @@ public abstract class BaseLoanIntegrationTest {
                 .useBorrowerCycle(false)//
                 .minPrincipal(100.0)//
                 .principal(1000.0)//
-                .maxPrincipal(10000.0)//
+                .maxPrincipal(100000.0)//
                 .minNumberOfRepayments(1)//
                 .numberOfRepayments(1)//
                 .maxNumberOfRepayments(30)//
                 .isLinkedToFloatingInterestRates(false)//
                 .minInterestRatePerPeriod((double) 0)//
                 .interestRatePerPeriod((double) 0)//
-                .maxInterestRatePerPeriod((double) 0)//
+                .maxInterestRatePerPeriod((double) 100)//
                 .interestRateFrequencyType(2)//
                 .repaymentEvery(30)//
                 .repaymentFrequencyType(0L)//
@@ -412,8 +412,8 @@ public abstract class BaseLoanIntegrationTest {
         PostLoansRequest postLoansRequest = new 
PostLoansRequest().clientId(clientId).productId(loanProductId)
                 
.expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
                 
.transactionProcessingStrategyCode(DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE_STRATEGY)
-                
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(0)
-                
.interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0)
+                
.locale("en").submittedOnDate(loanDisbursementDate).amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO)
+                
.interestCalculationPeriodType(1).interestType(0).repaymentEvery(30).repaymentFrequencyType(0)
                 
.numberOfRepayments(numberOfRepayments).loanTermFrequency(numberOfRepayments * 
30).loanTermFrequencyType(0)
                 
.maxOutstandingLoanBalance(BigDecimal.valueOf(amount)).principal(BigDecimal.valueOf(amount)).loanType("individual");
         if (customizer != null) {
@@ -422,9 +422,9 @@ public abstract class BaseLoanIntegrationTest {
         return postLoansRequest;
     }
 
-    protected PostLoansLoanIdRequest approveLoanRequest(Double amount) {
+    protected PostLoansLoanIdRequest approveLoanRequest(Double amount, String 
approvalDate) {
         return new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(amount)).dateFormat(DATETIME_PATTERN)
-                .approvedOnDate("01 January 2023").locale("en");
+                .approvedOnDate(approvalDate).locale("en");
     }
 
     protected Long applyAndApproveLoan(Long clientId, Long loanProductId, 
String loanDisbursementDate, Double amount,
@@ -438,7 +438,7 @@ public abstract class BaseLoanIntegrationTest {
                 .applyLoan(applyLoanRequest(clientId, loanProductId, 
loanDisbursementDate, amount, numberOfRepayments, customizer));
 
         PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
-                approveLoanRequest(amount));
+                approveLoanRequest(amount, loanDisbursementDate));
 
         return approvedLoanResult.getLoanId();
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
index 4ca9fedfa..b0287e94a 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java
@@ -8041,9 +8041,9 @@ public class ClientLoanIntegrationTest {
         return LOAN_TRANSACTION_HELPER.applyLoan(new 
PostLoansRequest().clientId(clientId.longValue()).productId(loanProductId)
                 
.expectedDisbursementDate(loanDisbursementDate).dateFormat(DATETIME_PATTERN)
                 
.transactionProcessingStrategyCode(repaymentStrategyCode).locale("en").submittedOnDate(loanDisbursementDate)
-                
.amortizationType(1).interestRatePerPeriod(0).interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0)
-                
.repaymentEvery(30).repaymentFrequencyType(0).numberOfRepayments(1).loanTermFrequency(30).loanTermFrequencyType(0)
-                .principal(BigDecimal.valueOf(1000.0)).loanType("individual"));
+                
.amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO).interestCalculationPeriodType(1).interestType(0)
+                
.repaymentFrequencyType(0).repaymentEvery(30).repaymentFrequencyType(0).numberOfRepayments(1).loanTermFrequency(30)
+                
.loanTermFrequencyType(0).principal(BigDecimal.valueOf(1000.0)).loanType("individual"));
     }
 
     private PostLoanProductsRequest 
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct() {
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
index d5824bdc6..2ca0a6611 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ExternalIdSupportIntegrationTest.java
@@ -935,10 +935,11 @@ public class ExternalIdSupportIntegrationTest extends 
IntegrationTest {
                     "modify",
                     new PutLoansLoanIdRequest().submittedOnDate("31 August 
2022").dateFormat("dd MMMM yyyy").locale("en")
                             
.loanType("individual").productId(loanProductID.longValue()).clientId(client.getClientId()).interestType(0)
-                            
.interestCalculationPeriodType(1).interestRatePerPeriod(0).isEqualAmortization(false).loanTermFrequency(30)
-                            
.loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1).principal(10000L)
-                            
.repaymentEvery(30).repaymentFrequencyType(0).transactionProcessingStrategyCode("mifos-standard-strategy")
-                            .expectedDisbursementDate("2 September 
2022").amortizationType(1));
+                            
.interestCalculationPeriodType(1).interestRatePerPeriod(BigDecimal.ZERO).isEqualAmortization(false)
+                            
.loanTermFrequency(30).loanTermFrequencyType(0).maxOutstandingLoanBalance(10000L).numberOfRepayments(1)
+                            
.principal(10000L).repaymentEvery(30).repaymentFrequencyType(0)
+                            
.transactionProcessingStrategyCode("mifos-standard-strategy").expectedDisbursementDate("2
 September 2022")
+                            .amortizationType(1));
 
             assertEquals(loanExternalIdStr2, 
modifyLoanApplicationResult.getResourceExternalId());
             DeleteLoansLoanIdResponse deleteLoanApplicationResult = 
this.loanTransactionHelper.deleteLoanApplication(loanExternalIdStr2);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
index 33601c650..737d6c55c 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargePaymentWithAdvancedPaymentAllocationTest.java
@@ -163,8 +163,8 @@ public class 
LoanChargePaymentWithAdvancedPaymentAllocationTest {
 
             savingsAccountHelper.depositToSavingsAccount(savingsId, "10000", 
startDate, CommonConstants.RESPONSE_RESOURCE_ID);
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 45, 
15, 3,
+                    BigDecimal.ZERO, "01 January 2023", "01 January 2023");
 
             int loanId = loanResponse.getLoanId().intValue();
 
@@ -266,7 +266,7 @@ public class 
LoanChargePaymentWithAdvancedPaymentAllocationTest {
     }
 
     private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final Long principal,
-            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
+            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final BigDecimal interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate) {
         log.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");
         return loanTransactionHelper.applyLoan(new 
PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
index b7cd5c5d1..9d72e8a61 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInstallmentMultiplesOfTest.java
@@ -71,7 +71,7 @@ public class LoanInstallmentMultiplesOfTest extends 
BaseLoanIntegrationTest {
             PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
 
             PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
-                    approveLoanRequest(amount));
+                    approveLoanRequest(amount, "01 January 2023"));
 
             Long loanId = approvedLoanResult.getLoanId();
 
@@ -130,12 +130,12 @@ public class LoanInstallmentMultiplesOfTest extends 
BaseLoanIntegrationTest {
                     .interestType(interestType)//
                     .amortizationType(amortizationType)//
                     .interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
-                    .interestRatePerPeriod(12);
+                    .interestRatePerPeriod(BigDecimal.valueOf(12));
 
             PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
 
             PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
-                    approveLoanRequest(amount));
+                    approveLoanRequest(amount, "01 January 2023"));
 
             Long loanId = approvedLoanResult.getLoanId();
 
@@ -193,12 +193,12 @@ public class LoanInstallmentMultiplesOfTest extends 
BaseLoanIntegrationTest {
                     .interestType(interestType)//
                     .amortizationType(amortizationType)//
                     .interestCalculationPeriodType(SAME_AS_REPAYMENT_PERIOD)//
-                    .interestRatePerPeriod(12);
+                    .interestRatePerPeriod(BigDecimal.valueOf(12));
 
             PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
 
             PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
-                    approveLoanRequest(amount));
+                    approveLoanRequest(amount, "01 January 2023"));
 
             Long loanId = approvedLoanResult.getLoanId();
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
index a17929c17..d54a60d20 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
@@ -36,13 +36,15 @@ import org.junit.jupiter.api.extension.ExtendWith;
 @ExtendWith(LoanTestLifecycleExtension.class)
 public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest 
{
 
-    public static final BigDecimal DOWN_PAYMENT_PERCENTAGE = new 
BigDecimal(25);
+    public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_20 = new 
BigDecimal(20);
+    public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_25 = new 
BigDecimal(25);
+    public static final BigDecimal DOWN_PAYMENT_PERCENTAGE_33 = new 
BigDecimal(33);
 
     private final LoanRescheduleRequestHelper loanRescheduleRequestHelper = 
new LoanRescheduleRequestHelper(this.requestSpec,
             this.responseSpec);
 
     @Test
-    public void testRescheduleWithDownpayment() {
+    public void testRescheduleWithDownPayment() {
         runAt("01 January 2023", () -> {
             // Create Client
             Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
@@ -105,6 +107,342 @@ public class LoanRescheduleTestWithDownpayment extends 
BaseLoanIntegrationTest {
         });
     }
 
+    @Test
+    public void testRescheduleAddExtraInstallmentsWithDownPayment() {
+        runAt("01 November 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            Long loanProductId = createLoanProductWith33PctDownPayment(true, 
true);
+
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, "02 
October 2023", 1000.0, 3);
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, false, "02 October 2023"), //
+                    installment(223.33, false, "01 November 2023"), //
+                    installment(223.33, false, "01 December 2023"), //
+                    installment(223.34, false, "31 December 2023") //
+            );
+
+            // 1st Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(1000.00), "02 October 
2023");
+
+            // verify transactions
+            verifyTransactions(loanId, //
+                    transaction(330.0, "Down Payment", "02 October 2023"), //
+                    transaction(1000.0, "Disbursement", "02 October 2023") //
+            );
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, true, "02 October 2023"), //
+                    installment(223.33, false, "01 November 2023"), //
+                    installment(223.33, false, "01 December 2023"), //
+                    installment(223.34, false, "31 December 2023") //
+            );
+
+            String requestJSON = new 
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+                    
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01 
November 2023")
+                    .updateAdjustedDueDate(null).updateSubmittedOnDate("01 
November 2023").updateRescheduleReasonId("1")
+                    .build(loanId.toString());
+
+            Integer loanRescheduleRequest = 
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+            requestJSON = new 
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 November 2023")
+                    .getApproveLoanRescheduleRequestJSON();
+            Integer approveLoanRescheduleRequest = 
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+                    requestJSON);
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, true, "02 October 2023"), //
+                    installment(134.0, false, "01 November 2023"), //
+                    installment(134.0, false, "01 December 2023"), //
+                    installment(134.0, false, "31 December 2023"), //
+                    installment(134.0, false, "30 January 2024"), //
+                    installment(134.0, false, "29 February 2024") //
+            );
+        });
+    }
+
+    @Test
+    public void 
testRescheduleAddExtraInstallmentsMultipleDisbursementWithDownPayment() {
+        runAt("31 December 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            Long loanProductId = createLoanProductWith33PctDownPayment(true, 
true);
+
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, "02 
October 2023", 1000.0, 3);
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, false, "02 October 2023"), //
+                    installment(223.33, false, "01 November 2023"), //
+                    installment(223.33, false, "01 December 2023"), //
+                    installment(223.34, false, "31 December 2023") //
+            );
+
+            // 1st Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(1000.00), "02 October 
2023");
+
+            // verify transactions
+            verifyTransactions(loanId, //
+                    transaction(330.0, "Down Payment", "02 October 2023"), //
+                    transaction(1000.0, "Disbursement", "02 October 2023") //
+            );
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, true, "02 October 2023"), //
+                    installment(223.33, false, "01 November 2023"), //
+                    installment(223.33, false, "01 December 2023"), //
+                    installment(223.34, false, "31 December 2023") //
+            );
+
+            // 2nd Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(200.00), "02 December 
2023");
+
+            // verify transactions
+            verifyTransactions(loanId, //
+                    transaction(330.0, "Down Payment", "02 October 2023"), //
+                    transaction(1000.0, "Disbursement", "02 October 2023"), //
+                    transaction(200.0, "Disbursement", "02 December 2023"), //
+                    transaction(66.0, "Down Payment", "02 December 2023") //
+            );
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, true, "02 October 2023"), //
+                    installment(268.0, false, "01 November 2023"), //
+                    installment(268.0, false, "01 December 2023"), //
+                    installment(200.0, null, "02 December 2023"), //
+                    installment(66.0, false, "02 December 2023"), //
+                    installment(268.0, false, "31 December 2023") //
+            );
+
+            String requestJSON = new 
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+                    
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("31 
December 2023")
+                    .updateAdjustedDueDate(null).updateSubmittedOnDate("31 
December 2023").updateRescheduleReasonId("1")
+                    .build(loanId.toString());
+
+            Integer loanRescheduleRequest = 
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+            requestJSON = new 
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("31 December 2023")
+                    .getApproveLoanRescheduleRequestJSON();
+            Integer approveLoanRescheduleRequest = 
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+                    requestJSON);
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(1000.0, null, "02 October 2023"), //
+                    installment(330.0, true, "02 October 2023"), //
+                    installment(268, false, "01 November 2023"), //
+                    installment(268, false, "01 December 2023"), //
+                    installment(200.0, null, "02 December 2023"), //
+                    installment(66.0, false, "02 December 2023"), //
+                    installment(89.33, false, "31 December 2023"), //
+                    installment(89.33, false, "30 January 2024"), //
+                    installment(89.34, false, "29 February 2024") //
+            );
+        });
+    }
+
+    @Test
+    public void 
testRescheduleAddExtraInstallmentsDisbursementWithDownPaymentWithInterest() {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            Long loanProductId = 
createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(true, true, 
5.0);
+
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, "01 
January 2023", 15000.0, 6, postLoansRequest -> {
+                postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+                postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+                postLoansRequest.repaymentEvery(1);
+                
postLoansRequest.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
+                
postLoansRequest.repaymentFrequencyType(RepaymentFrequencyType.MONTHS);
+                postLoansRequest.loanTermFrequency(6);
+            });
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(3000.00, false, "01 January 2023"), //
+                    installment(1764.21, false, "01 February 2023"), //
+                    installment(1852.42, false, "01 March 2023"), //
+                    installment(1945.04, false, "01 April 2023"), //
+                    installment(2042.29, false, "01 May 2023"), //
+                    installment(2144.41, false, "01 June 2023"), //
+                    installment(2251.63, false, "01 July 2023") //
+            );
+
+            // 1st Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(12000.00), "01 January 
2023");
+
+            // verify transactions
+            verifyTransactions(loanId, //
+                    transaction(2400.0, "Down Payment", "01 January 2023"), //
+                    transaction(12000.0, "Disbursement", "01 January 2023") //
+            );
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(2400.00, true, "01 January 2023"), //
+                    installment(1411.37, false, "01 February 2023"), //
+                    installment(1481.94, false, "01 March 2023"), //
+                    installment(1556.04, false, "01 April 2023"), //
+                    installment(1633.84, false, "01 May 2023"), //
+                    installment(1715.53, false, "01 June 2023"), //
+                    installment(1801.28, false, "01 July 2023") //
+            );
+
+            updateBusinessDate("01 June 2023");
+            String requestJSON = new 
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+                    
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01 
June 2023").updateAdjustedDueDate(null)
+                    .updateSubmittedOnDate("01 June 
2023").updateRescheduleReasonId("1").build(loanId.toString());
+
+            Integer loanRescheduleRequest = 
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+            requestJSON = new 
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 June 2023")
+                    .getApproveLoanRescheduleRequestJSON();
+            Integer approveLoanRescheduleRequest = 
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+                    requestJSON);
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(2400.00, true, "01 January 2023"), //
+                    installment(1411.37, false, "01 February 2023"), //
+                    installment(1481.94, false, "01 March 2023"), //
+                    installment(1556.04, false, "01 April 2023"), //
+                    installment(1633.84, false, "01 May 2023"), //
+                    installment(815.94, false, "01 June 2023"), //
+                    installment(856.74, false, "01 July 2023"), //
+                    installment(899.57, false, "01 August 2023"), //
+                    installment(944.56, false, "01 September 2023") //
+            );
+        });
+    }
+
+    @Test
+    public void 
testRescheduleAddExtraInstallmentsMultipleDisbursementWithDownPaymentWithInterest()
 {
+        runAt("01 January 2023", () -> {
+            // Create Client
+            Long clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+
+            // Create Loan Product
+            Long loanProductId = 
createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(true, true, 
5.0);
+
+            // Apply and Approve Loan
+            Long loanId = applyAndApproveLoan(clientId, loanProductId, "01 
January 2023", 15000.0, 6, postLoansRequest -> {
+                postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+                postLoansRequest.interestRatePerPeriod(BigDecimal.valueOf(5));
+                postLoansRequest.repaymentEvery(1);
+                
postLoansRequest.loanTermFrequencyType(RepaymentFrequencyType.MONTHS);
+                
postLoansRequest.repaymentFrequencyType(RepaymentFrequencyType.MONTHS);
+                postLoansRequest.loanTermFrequency(6);
+            });
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(3000.00, false, "01 January 2023"), //
+                    installment(1764.21, false, "01 February 2023"), //
+                    installment(1852.42, false, "01 March 2023"), //
+                    installment(1945.04, false, "01 April 2023"), //
+                    installment(2042.29, false, "01 May 2023"), //
+                    installment(2144.41, false, "01 June 2023"), //
+                    installment(2251.63, false, "01 July 2023") //
+            );
+
+            // 1st Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(12000.00), "01 January 
2023");
+
+            // verify transactions
+            verifyTransactions(loanId, //
+                    transaction(2400.0, "Down Payment", "01 January 2023"), //
+                    transaction(12000.0, "Disbursement", "01 January 2023") //
+            );
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(2400.00, true, "01 January 2023"), //
+                    installment(1411.37, false, "01 February 2023"), //
+                    installment(1481.94, false, "01 March 2023"), //
+                    installment(1556.04, false, "01 April 2023"), //
+                    installment(1633.84, false, "01 May 2023"), //
+                    installment(1715.53, false, "01 June 2023"), //
+                    installment(1801.28, false, "01 July 2023") //
+            );
+
+            updateBusinessDate("02 May 2023");
+            // 2nd Disburse Loan
+            disburseLoan(loanId, BigDecimal.valueOf(3000.00), "02 May 2023");
+
+            // verify transactions
+            verifyTransactions(loanId, //
+                    transaction(2400.0, "Down Payment", "01 January 2023"), //
+                    transaction(12000.0, "Disbursement", "01 January 2023"), //
+                    transaction(3000.00, "Disbursement", "02 May 2023"), //
+                    transaction(600.0, "Down Payment", "02 May 2023") //
+            );
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(2400.00, true, "01 January 2023"), //
+                    installment(1884.21, false, "01 February 2023"), //
+                    installment(1978.42, false, "01 March 2023"), //
+                    installment(2077.34, false, "01 April 2023"), //
+                    installment(2181.21, false, "01 May 2023"), //
+                    installment(3000.0, null, "02 May 2023"), //
+                    installment(600.0, false, "02 May 2023"), //
+                    installment(2174.14, false, "01 June 2023"), //
+                    installment(1704.68, false, "01 July 2023") //
+            );
+
+            updateBusinessDate("01 June 2023");
+            String requestJSON = new 
LoanRescheduleRequestTestBuilder().updateGraceOnInterest(null).updateGraceOnPrincipal(null)
+                    
.updateExtraTerms("2").updateNewInterestRate(null).updateRescheduleFromDate("01 
June 2023").updateAdjustedDueDate(null)
+                    .updateSubmittedOnDate("01 June 
2023").updateRescheduleReasonId("1").build(loanId.toString());
+
+            Integer loanRescheduleRequest = 
loanRescheduleRequestHelper.createLoanRescheduleRequest(requestJSON);
+            requestJSON = new 
LoanRescheduleRequestTestBuilder().updateSubmittedOnDate("01 June 2023")
+                    .getApproveLoanRescheduleRequestJSON();
+            Integer approveLoanRescheduleRequest = 
loanRescheduleRequestHelper.approveLoanRescheduleRequest(loanRescheduleRequest,
+                    requestJSON);
+
+            // Verify Repayment Schedule
+            verifyRepaymentSchedule(loanId, //
+                    installment(12000.0, null, "01 January 2023"), //
+                    installment(2400.00, true, "01 January 2023"), //
+                    installment(1884.21, false, "01 February 2023"), //
+                    installment(1978.42, false, "01 March 2023"), //
+                    installment(2077.34, false, "01 April 2023"), //
+                    installment(2181.21, false, "01 May 2023"), //
+                    installment(3000.0, null, "02 May 2023"), //
+                    installment(600.0, false, "02 May 2023"), //
+                    installment(903.80, false, "01 June 2023"), //
+                    installment(945.12, false, "01 July 2023"), //
+                    installment(992.37, false, "01 August 2023"), //
+                    installment(1037.53, false, "01 September 2023")//
+            );
+        });
+    }
+
     private Long createLoanProductWith25PctDownPayment(boolean 
autoDownPaymentEnabled, boolean multiDisburseEnabled) {
         PostLoanProductsRequest product = 
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
         product.setMultiDisburseLoan(multiDisburseEnabled);
@@ -117,7 +455,75 @@ public class LoanRescheduleTestWithDownpayment extends 
BaseLoanIntegrationTest {
         }
 
         product.setEnableDownPayment(true);
-        
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE);
+        
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_25);
+        product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
+
+        PostLoanProductsResponse loanProductResponse = 
loanProductHelper.createLoanProduct(product);
+        GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = 
loanProductHelper
+                .retrieveLoanProductById(loanProductResponse.getResourceId());
+
+        Long loanProductId = loanProductResponse.getResourceId();
+
+        assertEquals(TRUE, 
getLoanProductsProductIdResponse.getEnableDownPayment());
+        
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
+        assertEquals(0,
+                
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_25));
+        assertEquals(autoDownPaymentEnabled, 
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
+        assertEquals(multiDisburseEnabled, 
getLoanProductsProductIdResponse.getMultiDisburseLoan());
+        return loanProductId;
+    }
+
+    private Long createLoanProductWith33PctDownPayment(boolean 
autoDownPaymentEnabled, boolean multiDisburseEnabled) {
+        PostLoanProductsRequest product = 
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
+        product.setMultiDisburseLoan(multiDisburseEnabled);
+        product.repaymentEvery(1);
+        
product.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue());
+        product.installmentAmountInMultiplesOf(null);
+
+        if (!multiDisburseEnabled) {
+            product.disallowExpectedDisbursements(null);
+            product.setAllowApprovedDisbursedAmountsOverApplied(null);
+            product.overAppliedCalculationType(null);
+            product.overAppliedNumber(null);
+        }
+
+        product.setEnableDownPayment(true);
+        
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_33);
+        product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
+
+        PostLoanProductsResponse loanProductResponse = 
loanProductHelper.createLoanProduct(product);
+        GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = 
loanProductHelper
+                .retrieveLoanProductById(loanProductResponse.getResourceId());
+
+        Long loanProductId = loanProductResponse.getResourceId();
+
+        assertEquals(TRUE, 
getLoanProductsProductIdResponse.getEnableDownPayment());
+        
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
+        assertEquals(0,
+                
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_33));
+        assertEquals(autoDownPaymentEnabled, 
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
+        assertEquals(multiDisburseEnabled, 
getLoanProductsProductIdResponse.getMultiDisburseLoan());
+        return loanProductId;
+    }
+
+    private Long 
createLoanProductWith20PctDownPaymentWithDecliningBalanceInterest(boolean 
autoDownPaymentEnabled,
+            boolean multiDisburseEnabled, double interestRate) {
+        PostLoanProductsRequest product = 
createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
+        product.setMultiDisburseLoan(multiDisburseEnabled);
+        product.repaymentEvery(1);
+        
product.repaymentFrequencyType(RepaymentFrequencyType.MONTHS.longValue());
+        product.installmentAmountInMultiplesOf(null);
+        product.interestRatePerPeriod(interestRate);
+
+        if (!multiDisburseEnabled) {
+            product.disallowExpectedDisbursements(null);
+            product.setAllowApprovedDisbursedAmountsOverApplied(null);
+            product.overAppliedCalculationType(null);
+            product.overAppliedNumber(null);
+        }
+
+        product.setEnableDownPayment(true);
+        
product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE_20);
         product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);
 
         PostLoanProductsResponse loanProductResponse = 
loanProductHelper.createLoanProduct(product);
@@ -128,7 +534,8 @@ public class LoanRescheduleTestWithDownpayment extends 
BaseLoanIntegrationTest {
 
         assertEquals(TRUE, 
getLoanProductsProductIdResponse.getEnableDownPayment());
         
assertNotNull(getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment());
-        assertEquals(0, 
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE));
+        assertEquals(0,
+                
getLoanProductsProductIdResponse.getDisbursedAmountPercentageForDownPayment().compareTo(DOWN_PAYMENT_PERCENTAGE_20));
         assertEquals(autoDownPaymentEnabled, 
getLoanProductsProductIdResponse.getEnableAutoRepaymentForDownPayment());
         assertEquals(multiDisburseEnabled, 
getLoanProductsProductIdResponse.getMultiDisburseLoan());
         return loanProductId;
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
index 7efe0be71..660f7e19b 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanSpecificDueDateChargeAfterMaturityTest.java
@@ -446,8 +446,8 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
                     
.currencyCode("USD").name(Utils.randomStringGenerator("PENALTY_" + 
Calendar.getInstance().getTimeInMillis(), 5))
                     .chargeAppliesTo(1).locale("en").active(true));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 30, 
30, 1, 0,
-                    "01 September 2023", "01 September 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 1000L, 30, 
30, 1,
+                    BigDecimal.ZERO, "01 September 2023", "01 September 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
@@ -548,7 +548,7 @@ public class LoanSpecificDueDateChargeAfterMaturityTest {
     }
 
     private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final Long principal,
-            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
+            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final BigDecimal interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate) {
         LOG.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");
         return loanTransactionHelper.applyLoan(new 
PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
index 12377c465..9d631d87f 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanWaiveChargeTest.java
@@ -80,7 +80,7 @@ public class LoanWaiveChargeTest extends 
BaseLoanIntegrationTest {
             PostLoansResponse postLoansResponse = 
loanTransactionHelper.applyLoan(applicationRequest);
 
             PostLoansLoanIdResponse approvedLoanResult = 
loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
-                    approveLoanRequest(amount));
+                    approveLoanRequest(amount, "01 January 2023"));
 
             Long loanId = approvedLoanResult.getLoanId();
             appliedLoanId.set(loanId);
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
index 58c884679..29c9817fd 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/RefundForActiveLoansWithAdvancedPaymentAllocationTest.java
@@ -104,8 +104,8 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest {
             Integer loanProductId = createLoanProduct("1000", "30", "4", 
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount,
                     expenseAccount, overpaymentAccount);
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3, 
0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
+                    BigDecimal.ZERO, "01 January 2023", "01 January 2023");
 
             int loanId = loanResponse.getLoanId().intValue();
 
@@ -303,8 +303,8 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest {
             Integer loanProductId = createLoanProduct("1000", "30", "4", 
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount,
                     expenseAccount, overpaymentAccount);
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3, 
0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), loanProductId, 1000L, 90, 30, 3,
+                    BigDecimal.ZERO, "01 January 2023", "01 January 2023");
 
             int loanId = loanResponse.getLoanId().intValue();
 
@@ -529,7 +529,7 @@ public class 
RefundForActiveLoansWithAdvancedPaymentAllocationTest {
     }
 
     private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final Long principal,
-            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
+            final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final BigDecimal interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate) {
         log.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");
         return loanTransactionHelper.applyLoan(new 
PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())

Reply via email to