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 ea68edce2 FINERACT-1981: Order disbursements and repayment periods 
properly
ea68edce2 is described below

commit ea68edce2db1b9c638c60e52218eecf6ed187a4e
Author: Adam Saghy <[email protected]>
AuthorDate: Tue Nov 28 18:07:04 2023 +0100

    FINERACT-1981: Order disbursements and repayment periods properly
---
 .../loanaccount/data/DisbursementData.java         |  14 +-
 ...dvancedPaymentScheduleTransactionProcessor.java |   2 +-
 .../loanschedule/domain/LoanScheduleType.java      |   7 +
 .../loanaccount/api/LoansApiResource.java          |   8 +-
 .../AbstractProgressiveLoanScheduleGenerator.java  | 106 +---
 .../domain/ProgressiveLoanScheduleGenerator.java   |  39 +-
 .../LoanScheduleHistoryReadPlatformService.java    |   3 +-
 ...LoanScheduleHistoryReadPlatformServiceImpl.java |  12 +-
 .../service/LoanReadPlatformService.java           |   4 +-
 .../service/LoanReadPlatformServiceImpl.java       | 106 ++--
 ...PaymentAllocationLoanRepaymentScheduleTest.java | 581 ++++++++++++---------
 .../integrationtests/BaseLoanIntegrationTest.java  |   5 +
 ...ChargeOffWithAdvancedPaymentAllocationTest.java |  26 +-
 ...nWithOverlappingDownPaymentInstallmentTest.java |  54 +-
 ...ProductRepaymentStartDateConfigurationTest.java |  84 +--
 15 files changed, 532 insertions(+), 519 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java
index 243426ddd..53e318fff 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/DisbursementData.java
@@ -23,6 +23,7 @@ import java.time.LocalDate;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
 
 /**
  * Immutable data object representing disbursement information.
@@ -89,9 +90,12 @@ public final class DisbursementData implements 
Comparable<DisbursementData> {
         return DateUtils.compare(obj.expectedDisbursementDate, 
this.expectedDisbursementDate);
     }
 
-    public boolean isDueForDisbursement(final LocalDate fromNotInclusive, 
final LocalDate upToAndInclusive) {
+    public boolean isDueForDisbursement(LoanScheduleType loanScheduleType, 
final LocalDate fromDate, final LocalDate toDate) {
         final LocalDate dueDate = disbursementDate();
-        return occursOnDayFromAndUpToAndIncluding(fromNotInclusive, 
upToAndInclusive, dueDate);
+        return switch (loanScheduleType) {
+            case CUMULATIVE -> occursOnDayFromAndUpToAndIncluding(fromDate, 
toDate, dueDate);
+            case PROGRESSIVE -> occursOnDayFromAndIncludingAndUpTo(fromDate, 
toDate, dueDate);
+        };
     }
 
     private boolean occursOnDayFromAndUpToAndIncluding(final LocalDate 
fromNotInclusive, final LocalDate upToAndInclusive,
@@ -99,6 +103,12 @@ public final class DisbursementData implements 
Comparable<DisbursementData> {
         return DateUtils.isAfter(target, fromNotInclusive) && 
!DateUtils.isAfter(target, upToAndInclusive);
     }
 
+    private boolean occursOnDayFromAndIncludingAndUpTo(final LocalDate 
fromInclusive, final LocalDate upToNotInclusive,
+            final LocalDate target) {
+        return (DateUtils.isEqual(target, fromInclusive) || 
DateUtils.isAfter(target, fromInclusive))
+                && DateUtils.isBefore(target, upToNotInclusive);
+    }
+
     public BigDecimal getWaivedChargeAmount() {
         return this.waivedChargeAmount == null ? BigDecimal.ZERO : 
this.waivedChargeAmount;
     }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index 9994201e7..fefbd022c 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -282,7 +282,7 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
             List<LoanRepaymentScheduleInstallment> installments) {
         final MathContext mc = MoneyHelper.getMathContext();
         List<LoanRepaymentScheduleInstallment> candidateRepaymentInstallments 
= installments.stream().filter(
-                i -> 
!i.getDueDate().isBefore(disbursementTransaction.getTransactionDate()) && 
!i.isDownPayment() && !i.isAdditional())
+                i -> 
i.getDueDate().isAfter(disbursementTransaction.getTransactionDate()) && 
!i.isDownPayment() && !i.isAdditional())
                 .toList();
         int noCandidateRepaymentInstallments = 
candidateRepaymentInstallments.size();
         LoanProductRelatedDetail loanProductRelatedDetail = 
disbursementTransaction.getLoan().getLoanRepaymentScheduleDetail();
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleType.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleType.java
index f56173377..d9a704684 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleType.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanScheduleType.java
@@ -39,4 +39,11 @@ public enum LoanScheduleType {
     public EnumOptionData asEnumOptionData() {
         return new EnumOptionData((long) this.ordinal(), this.name(), 
this.humanReadableName);
     }
+
+    public static LoanScheduleType fromEnumOptionData(EnumOptionData 
enumOptionData) {
+        if (enumOptionData == null) {
+            return null;
+        }
+        return valueOf(enumOptionData.getCode());
+    }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
index e379e841b..7f6da6f65 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResource.java
@@ -47,7 +47,6 @@ import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.core.Response;
 import jakarta.ws.rs.core.UriInfo;
 import java.io.InputStream;
-import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -953,7 +952,7 @@ public class LoansApiResource {
                                 
loanBasicDetails.getFeeChargesAtDisbursementCharged());
                 repaymentSchedule = 
this.loanReadPlatformService.retrieveRepaymentSchedule(resolvedLoanId, 
repaymentScheduleRelatedData,
                         disbursementData, 
loanBasicDetails.isInterestRecalculationEnabled(),
-                        loanBasicDetails.getSummary() != null ? 
loanBasicDetails.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
+                        
LoanScheduleType.fromEnumOptionData(loanBasicDetails.getLoanScheduleType()));
 
                 if 
(associationParameters.contains(DataTableApiConstant.futureScheduleAssociateParamName)
                         && loanBasicDetails.isInterestRecalculationEnabled()) {
@@ -965,8 +964,9 @@ public class LoansApiResource {
                         && loanBasicDetails.isInterestRecalculationEnabled()
                         && 
LoanStatus.fromInt(loanBasicDetails.getStatus().getId().intValue()).isActive()) 
{
                     
mandatoryResponseParameters.add(DataTableApiConstant.originalScheduleAssociateParamName);
-                    LoanScheduleData loanScheduleData = 
this.loanScheduleHistoryReadPlatformService
-                            .retrieveRepaymentArchiveSchedule(resolvedLoanId, 
repaymentScheduleRelatedData, disbursementData);
+                    LoanScheduleData loanScheduleData = 
this.loanScheduleHistoryReadPlatformService.retrieveRepaymentArchiveSchedule(
+                            resolvedLoanId, repaymentScheduleRelatedData, 
disbursementData,
+                            
LoanScheduleType.fromEnumOptionData(loanBasicDetails.getLoanScheduleType()));
                     loanBasicDetails = 
LoanAccountData.withOriginalSchedule(loanBasicDetails, loanScheduleData);
                 }
             }
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 d0c1ba0cb..2399093a6 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
@@ -28,7 +28,6 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TreeMap;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.infrastructure.core.service.MathUtil;
 import org.apache.fineract.organisation.monetary.domain.ApplicationCurrency;
@@ -85,26 +84,6 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
 
         boolean isFirstRepayment = true;
 
-        if (loanApplicationTerms.isMultiDisburseLoan()) {
-            /* fetches the first tranche amount and also updates other tranche 
details to map */
-            Money disburseAmt = Money.of(currency, 
getDisbursementAmount(loanApplicationTerms, scheduleParams.getPeriodStartDate(),
-                    scheduleParams.getDisburseDetailMap(), 
scheduleParams.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);
-            scheduleParams.setPrincipalToBeScheduled(remainingPrincipalAmt);
-            loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
-            scheduleParams.setOutstandingBalance(remainingPrincipalAmt);
-            
scheduleParams.setOutstandingBalanceAsPerRest(remainingPrincipalAmt);
-            loanApplicationTerms.resetFixedEmiAmount();
-        }
-
         // charges which depends on total loan interest will be added to this
         // set and handled separately after all installments generated
         final Set<LoanCharge> nonCompoundingCharges = 
separateTotalCompoundingPercentageCharges(loanCharges);
@@ -134,13 +113,8 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
             }
 
             // 5 determine principal,interest of repayment period
-            PrincipalInterest principalInterestForThisPeriod = 
calculatePrincipalInterestComponentsForPeriod(
-                    getPaymentPeriodsInOneYearCalculator(), 
currentPeriodParams.getInterestCalculationGraceOnRepaymentPeriodFraction(),
-                    
scheduleParams.getTotalCumulativePrincipal().minus(scheduleParams.getReducePrincipal()),
-                    scheduleParams.getTotalCumulativeInterest(), 
loanApplicationTerms.getTotalInterestDue(),
-                    
scheduleParams.getTotalOutstandingInterestPaymentDueToGrace(), 
scheduleParams.getOutstandingBalanceAsPerRest(),
-                    loanApplicationTerms, scheduleParams.getPeriodNumber(), 
mc, null, scheduleParams.getCompoundingMap(), null,
-                    scheduledDueDate, null);
+            PrincipalInterest principalInterestForThisPeriod = 
calculatePrincipalInterestComponentsForPeriod(loanApplicationTerms,
+                    scheduleParams, mc);
 
             // update cumulative fields for principal
             
currentPeriodParams.setPrincipalForThisPeriod(principalInterestForThisPeriod.principal());
@@ -241,12 +215,8 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
 
     public abstract PaymentPeriodsInOneYearCalculator 
getPaymentPeriodsInOneYearCalculator();
 
-    public abstract PrincipalInterest 
calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator 
calculator,
-            BigDecimal interestCalculationGraceOnRepaymentPeriodFraction, 
Money totalCumulativePrincipal, Money totalCumulativeInterest,
-            Money totalInterestDueForLoan, Money 
cumulatingInterestPaymentDueToGrace, Money outstandingBalance,
-            LoanApplicationTerms loanApplicationTerms, int periodNumber, 
MathContext mc, TreeMap<LocalDate, Money> principalVariation,
-            Map<LocalDate, Money> compoundingMap, LocalDate periodStartDate, 
LocalDate periodEndDate,
-            Collection<LoanTermVariationsData> termVariations);
+    public abstract PrincipalInterest 
calculatePrincipalInterestComponentsForPeriod(LoanApplicationTerms 
loanApplicationTerms,
+            LoanScheduleParams loanScheduleParams, MathContext mc);
 
     // Private, internal methods
     private BigDecimal deriveTotalChargesDueAtTimeOfDisbursement(final 
Set<LoanCharge> loanCharges) {
@@ -266,7 +236,8 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
         Money principalToBeScheduled;
         if (loanApplicationTerms.isMultiDisburseLoan()) {
             if 
(loanApplicationTerms.getTotalDisbursedAmount().isGreaterThanZero()) {
-                principalToBeScheduled = 
loanApplicationTerms.getTotalMultiDisbursedAmount();
+                principalToBeScheduled = 
Money.of(loanApplicationTerms.getCurrency(),
+                        
loanApplicationTerms.getDisbursementDatas().get(0).getPrincipal());
             } else if 
(loanApplicationTerms.getApprovedPrincipal().isGreaterThanZero()) {
                 principalToBeScheduled = 
loanApplicationTerms.getApprovedPrincipal();
             } else {
@@ -300,6 +271,9 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
                             loanScheduleParams, 
loanApplicationTerms.getExpectedDisbursementDate(), 
disbursementData.getPrincipal());
                     periods.add(downPaymentPeriod);
                 }
+            } else {
+                
loanScheduleParams.getDisburseDetailMap().put(disbursementData.disbursementDate(),
+                        Money.of(loanApplicationTerms.getCurrency(), 
disbursementData.getPrincipal()));
             }
         }
 
@@ -313,14 +287,19 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
         if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
             downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
         }
-        LoanScheduleModelDownPaymentPeriod installment = 
LoanScheduleModelDownPaymentPeriod
-                .downPayment(scheduleParams.getInstalmentNumber(), date, 
downPaymentAmount, scheduleParams.getOutstandingBalance());
+        LoanScheduleModelDownPaymentPeriod installment = 
LoanScheduleModelDownPaymentPeriod.downPayment(
+                scheduleParams.getInstalmentNumber(), date, downPaymentAmount,
+                
scheduleParams.getOutstandingBalance().minus(downPaymentAmount));
 
         addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), 
installment);
 
         scheduleParams.incrementInstalmentNumber();
         scheduleParams.addTotalRepaymentExpected(downPaymentAmount);
-
+        scheduleParams.reduceOutstandingBalance(downPaymentAmount);
+        scheduleParams.reduceOutstandingBalanceAsPerRest(downPaymentAmount);
+        
scheduleParams.setPrincipalToBeScheduled(scheduleParams.getPrincipalToBeScheduled().minus(downPaymentAmount));
+        
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().minus(downPaymentAmount));
+        loanApplicationTerms.resetFixedEmiAmount();
         return installment;
     }
 
@@ -345,8 +324,9 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
     private void processDisbursements(final LoanApplicationTerms 
loanApplicationTerms, final BigDecimal chargesDueAtTimeOfDisbursement,
             LoanScheduleParams scheduleParams, final 
Collection<LoanScheduleModelPeriod> periods, final LocalDate scheduledDueDate) {
         for (Map.Entry<LocalDate, Money> disburseDetail : 
scheduleParams.getDisburseDetailMap().entrySet()) {
-            if 
(disburseDetail.getKey().isAfter(scheduleParams.getPeriodStartDate())
-                    && !disburseDetail.getKey().isAfter(scheduledDueDate)) {
+            if 
((disburseDetail.getKey().isEqual(scheduleParams.getPeriodStartDate())
+                    || 
disburseDetail.getKey().isAfter(scheduleParams.getPeriodStartDate()))
+                    && disburseDetail.getKey().isBefore(scheduledDueDate)) {
                 // validation check for amount not exceeds specified max
                 // amount as per the configuration
                 loanApplicationTerms.getMaxOutstandingBalance();
@@ -378,11 +358,10 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
                 }
                 // updates actual outstanding balance with new
                 // disbursement detail
-                Money remainingPrincipal = 
disburseDetail.getValue().minus(downPaymentAmt);
-                scheduleParams.addOutstandingBalance(remainingPrincipal);
-                
scheduleParams.addOutstandingBalanceAsPerRest(remainingPrincipal);
-                scheduleParams.addPrincipalToBeScheduled(remainingPrincipal);
-                
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().plus(remainingPrincipal));
+                
scheduleParams.addOutstandingBalance(disburseDetail.getValue());
+                
scheduleParams.addOutstandingBalanceAsPerRest(disburseDetail.getValue());
+                
scheduleParams.addPrincipalToBeScheduled(disburseDetail.getValue());
+                
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().plus(disburseDetail.getValue()));
                 loanApplicationTerms.resetFixedEmiAmount();
             }
         }
@@ -585,43 +564,6 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
         return interestCharges;
     }
 
-    private BigDecimal getDisbursementAmount(final LoanApplicationTerms 
loanApplicationTerms, LocalDate disbursementDate,
-            final Map<LocalDate, Money> disburseDetails, final boolean 
excludePastUnDisbursed) {
-
-        // this method relates to multi-disbursement loans
-        BigDecimal principal = BigDecimal.ZERO;
-        if (loanApplicationTerms.getDisbursementDatas().size() == 0) {
-            // non tranche loans have no disbursement data entries in 
submitted and approved status
-            // the appropriate approved amount or applied for amount is used 
to show a proposed schedule
-            if 
(loanApplicationTerms.getApprovedPrincipal().getAmount().compareTo(BigDecimal.ZERO)
 > 0) {
-                principal = 
loanApplicationTerms.getApprovedPrincipal().getAmount();
-            } else {
-                principal = loanApplicationTerms.getPrincipal().getAmount();
-            }
-        } else {
-            MonetaryCurrency currency = 
loanApplicationTerms.getPrincipal().getCurrency();
-            for (DisbursementData disbursementData : 
loanApplicationTerms.getDisbursementDatas()) {
-                if 
(disbursementData.disbursementDate().equals(disbursementDate)) {
-                    principal = principal.add(disbursementData.getPrincipal());
-                } else if (!excludePastUnDisbursed || 
disbursementData.isDisbursed()
-                        || 
!disbursementData.disbursementDate().isBefore(DateUtils.getBusinessLocalDate()))
 {
-                    /*
-                     * JW: sums up amounts by disbursal date in case of 
side-effect issues. Original assumed that there
-                     * were no duplicate disbursal dates and 'put' each amount 
into the map keyed by date
-                     */
-                    Money previousSum = 
disburseDetails.get(disbursementData.disbursementDate());
-                    BigDecimal sumToNow = BigDecimal.ZERO;
-                    if (previousSum != null) {
-                        sumToNow = previousSum.getAmount();
-                    }
-                    sumToNow = sumToNow.add(disbursementData.getPrincipal());
-                    disburseDetails.put(disbursementData.disbursementDate(), 
Money.of(currency, sumToNow));
-                }
-            }
-        }
-        return principal;
-    }
-
     private void updateOutstandingBalance(LoanScheduleParams scheduleParams, 
ScheduleCurrentPeriodParams currentPeriodParams) {
         // update outstandingLoanBlance using current period
         // 'principalDue'
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
index 99a106e2d..f05675e3c 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/ProgressiveLoanScheduleGenerator.java
@@ -20,13 +20,9 @@ package 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain;
 
 import java.math.BigDecimal;
 import java.math.MathContext;
-import java.time.LocalDate;
-import java.util.Collection;
-import java.util.Map;
-import java.util.TreeMap;
 import lombok.RequiredArgsConstructor;
 import org.apache.fineract.organisation.monetary.domain.Money;
-import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleParams;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -47,21 +43,30 @@ public class ProgressiveLoanScheduleGenerator extends 
AbstractProgressiveLoanSch
     }
 
     @Override
-    public PrincipalInterest 
calculatePrincipalInterestComponentsForPeriod(PaymentPeriodsInOneYearCalculator 
calculator,
-            BigDecimal interestCalculationGraceOnRepaymentPeriodFraction, 
Money totalCumulativePrincipal, Money totalCumulativeInterest,
-            Money totalInterestDueForLoan, Money 
cumulatingInterestPaymentDueToGrace, Money outstandingBalance,
-            LoanApplicationTerms loanApplicationTerms, int periodNumber, 
MathContext mc, TreeMap<LocalDate, Money> principalVariation,
-            Map<LocalDate, Money> compoundingMap, LocalDate periodStartDate, 
LocalDate periodEndDate,
-            Collection<LoanTermVariationsData> termVariations) {
+    public PrincipalInterest 
calculatePrincipalInterestComponentsForPeriod(LoanApplicationTerms 
loanApplicationTerms,
+            LoanScheduleParams loanScheduleParams, MathContext mc) {
         // TODO: handle interest calculation
-        Money principalForThisInstallment = 
loanApplicationTerms.calculateTotalPrincipalForPeriod(calculator, 
outstandingBalance,
-                periodNumber, mc, 
Money.zero(loanApplicationTerms.getCurrency()));
-        final Money totalCumulativePrincipalToDate = 
totalCumulativePrincipal.plus(principalForThisInstallment);
+        int periodNumber = loanScheduleParams.getPeriodNumber();
+        BigDecimal fixedEMIAmount = loanApplicationTerms.getFixedEmiAmount();
+        Money calculatedPrincipal;
+        if (fixedEMIAmount == null) {
+            int noRemainingPeriod = 
loanApplicationTerms.getActualNoOfRepaymnets() - periodNumber + 1;
+            calculatedPrincipal = 
loanScheduleParams.getOutstandingBalance().dividedBy(noRemainingPeriod, 
mc.getRoundingMode());
+            if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != 
null) {
+                calculatedPrincipal = 
Money.roundToMultiplesOf(calculatedPrincipal,
+                        
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+            }
+            
loanApplicationTerms.setFixedEmiAmount(calculatedPrincipal.getAmount());
+        } else {
+            calculatedPrincipal = Money.of(loanApplicationTerms.getCurrency(), 
fixedEMIAmount);
+        }
         // adjust if needed
-        principalForThisInstallment = 
loanApplicationTerms.adjustPrincipalIfLastRepaymentPeriod(principalForThisInstallment,
-                totalCumulativePrincipalToDate, periodNumber);
+        if (periodNumber == loanApplicationTerms.getActualNoOfRepaymnets()) {
+            Money remainingAmount = 
loanScheduleParams.getOutstandingBalance().minus(calculatedPrincipal);
+            calculatedPrincipal = calculatedPrincipal.plus(remainingAmount);
+        }
 
-        return new PrincipalInterest(principalForThisInstallment, 
Money.zero(loanApplicationTerms.getCurrency()),
+        return new PrincipalInterest(calculatedPrincipal, 
Money.zero(loanApplicationTerms.getCurrency()),
                 Money.zero(loanApplicationTerms.getCurrency()));
     }
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java
index 22270a17b..3b25c5027 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformService.java
@@ -23,13 +23,14 @@ import java.util.Map;
 import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
 import 
org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLoanData;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
 
 public interface LoanScheduleHistoryReadPlatformService {
 
     Integer fetchCurrentVersionNumber(Long loanId);
 
     LoanScheduleData retrieveRepaymentArchiveSchedule(Long loanId, 
RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
-            Collection<DisbursementData> disbursementData);
+            Collection<DisbursementData> disbursementData, LoanScheduleType 
loanScheduleType);
 
     Map<String, Object> fetchOldAuditDates(Long id);
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java
index d098c63d8..8b35fef47 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleHistoryReadPlatformServiceImpl.java
@@ -37,6 +37,7 @@ import 
org.apache.fineract.portfolio.loanaccount.data.RepaymentScheduleRelatedLo
 import 
org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataAccessException;
 import org.springframework.dao.EmptyResultDataAccessException;
@@ -68,7 +69,8 @@ public class LoanScheduleHistoryReadPlatformServiceImpl 
implements LoanScheduleH
 
     @Override
     public LoanScheduleData retrieveRepaymentArchiveSchedule(final Long loanId,
-            final RepaymentScheduleRelatedLoanData 
repaymentScheduleRelatedLoanData, Collection<DisbursementData> 
disbursementData) {
+            final RepaymentScheduleRelatedLoanData 
repaymentScheduleRelatedLoanData, Collection<DisbursementData> disbursementData,
+            LoanScheduleType loanScheduleType) {
 
         try {
             this.context.authenticatedUser();
@@ -77,7 +79,7 @@ public class LoanScheduleHistoryReadPlatformServiceImpl 
implements LoanScheduleH
                 return null;
             }
             final LoanScheduleArchiveResultSetExtractor fullResultsetExtractor 
= new LoanScheduleArchiveResultSetExtractor(
-                    repaymentScheduleRelatedLoanData, disbursementData);
+                    repaymentScheduleRelatedLoanData, disbursementData, 
loanScheduleType);
             final String sql = "select " + fullResultsetExtractor.schema()
                     + " where ls.loan_id = ? and ls.version = ? order by 
ls.loan_id, ls.installment";
 
@@ -99,17 +101,19 @@ public class LoanScheduleHistoryReadPlatformServiceImpl 
implements LoanScheduleH
         private final DisbursementData disbursement;
         private final BigDecimal totalFeeChargesDueAtDisbursement;
         private final Collection<DisbursementData> disbursementData;
+        private final LoanScheduleType loanScheduleType;
         private LocalDate lastDueDate;
         private BigDecimal outstandingLoanPrincipalBalance;
 
         LoanScheduleArchiveResultSetExtractor(final 
RepaymentScheduleRelatedLoanData repaymentScheduleRelatedLoanData,
-                Collection<DisbursementData> disbursementData) {
+                Collection<DisbursementData> disbursementData, 
LoanScheduleType loanScheduleType) {
             this.currency = repaymentScheduleRelatedLoanData.getCurrency();
             this.disbursement = 
repaymentScheduleRelatedLoanData.disbursementData();
             this.totalFeeChargesDueAtDisbursement = 
repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement();
             this.lastDueDate = this.disbursement.disbursementDate();
             this.outstandingLoanPrincipalBalance = 
this.disbursement.getPrincipal();
             this.disbursementData = disbursementData;
+            this.loanScheduleType = loanScheduleType;
         }
 
         public String schema() {
@@ -163,7 +167,7 @@ public class LoanScheduleHistoryReadPlatformServiceImpl 
implements LoanScheduleH
                                     data.getPrincipal(), 
this.totalFeeChargesDueAtDisbursement, data.isDisbursed());
                             periods.add(periodData);
                             this.outstandingLoanPrincipalBalance = 
this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
-                        } else if (data.isDueForDisbursement(fromDate, dueDate)
+                        } else if (data.isDueForDisbursement(loanScheduleType, 
fromDate, dueDate)
                                 && 
this.outstandingLoanPrincipalBalance.compareTo(BigDecimal.ZERO) > 0) {
                             principal = principal.add(data.getPrincipal());
                             final LoanSchedulePeriodData periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(),
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
index 235b6b87f..1b0c64e4d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java
@@ -18,7 +18,6 @@
  */
 package org.apache.fineract.portfolio.loanaccount.service;
 
-import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.Collection;
 import java.util.List;
@@ -43,6 +42,7 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.LoanSchedulePeriodData;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.data.OverdueLoanScheduleData;
+import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
 
 public interface LoanReadPlatformService {
 
@@ -51,7 +51,7 @@ public interface LoanReadPlatformService {
     LoanAccountData fetchRepaymentScheduleData(LoanAccountData accountData);
 
     LoanScheduleData retrieveRepaymentSchedule(Long loanId, 
RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData,
-            Collection<DisbursementData> disbursementData, boolean 
isInterestRecalculationEnabled, BigDecimal totalPaidFeeCharges);
+            Collection<DisbursementData> disbursementData, boolean 
isInterestRecalculationEnabled, LoanScheduleType loanScheduleType);
 
     Collection<LoanTransactionData> retrieveLoanTransactions(Long loanId);
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
index f0d024031..6adaa9975 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java
@@ -245,7 +245,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
         final Collection<DisbursementData> disbursementData = 
retrieveLoanDisbursementDetails(accountData.getId());
         final LoanScheduleData repaymentSchedule = 
retrieveRepaymentSchedule(accountData.getId(), repaymentScheduleRelatedData,
                 disbursementData, accountData.isInterestRecalculationEnabled(),
-                accountData.getSummary() != null ? 
accountData.getSummary().getFeeChargesPaid() : BigDecimal.ZERO);
+                
LoanScheduleType.fromEnumOptionData(accountData.getLoanScheduleType()));
         accountData.setRepaymentSchedule(repaymentSchedule);
         return accountData;
     }
@@ -253,13 +253,13 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
     @Override
     public LoanScheduleData retrieveRepaymentSchedule(final Long loanId,
             final RepaymentScheduleRelatedLoanData 
repaymentScheduleRelatedLoanData, Collection<DisbursementData> disbursementData,
-            boolean isInterestRecalculationEnabled, BigDecimal 
totalPaidFeeCharges) {
+            boolean isInterestRecalculationEnabled, LoanScheduleType 
loanScheduleType) {
 
         try {
             this.context.authenticatedUser();
 
             final LoanScheduleResultSetExtractor fullResultsetExtractor = new 
LoanScheduleResultSetExtractor(
-                    repaymentScheduleRelatedLoanData, disbursementData, 
isInterestRecalculationEnabled);
+                    repaymentScheduleRelatedLoanData, disbursementData, 
isInterestRecalculationEnabled, loanScheduleType);
             final String sql = "select " + fullResultsetExtractor.schema() + " 
where ls.loan_id = ? order by ls.loan_id, ls.installment";
 
             return this.jdbcTemplate.query(sql, fullResultsetExtractor, 
loanId); // NOSONAR
@@ -1123,19 +1123,21 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
         private final DisbursementData disbursement;
         private final BigDecimal totalFeeChargesDueAtDisbursement;
         private final Collection<DisbursementData> disbursementData;
+        private final LoanScheduleType loanScheduleType;
         private LocalDate lastDueDate;
         private BigDecimal outstandingLoanPrincipalBalance;
-        private boolean excludePastUndisbursed;
+        private boolean excludePastUnDisbursed;
 
         LoanScheduleResultSetExtractor(final RepaymentScheduleRelatedLoanData 
repaymentScheduleRelatedLoanData,
-                Collection<DisbursementData> disbursementData, boolean 
isInterestRecalculationEnabled) {
+                Collection<DisbursementData> disbursementData, boolean 
isInterestRecalculationEnabled, LoanScheduleType loanScheduleType) {
             this.currency = repaymentScheduleRelatedLoanData.getCurrency();
             this.disbursement = 
repaymentScheduleRelatedLoanData.disbursementData();
             this.totalFeeChargesDueAtDisbursement = 
repaymentScheduleRelatedLoanData.getTotalFeeChargesAtDisbursement();
             this.lastDueDate = this.disbursement.disbursementDate();
             this.outstandingLoanPrincipalBalance = 
this.disbursement.getPrincipal();
             this.disbursementData = disbursementData;
-            this.excludePastUndisbursed = isInterestRecalculationEnabled;
+            this.excludePastUnDisbursed = isInterestRecalculationEnabled;
+            this.loanScheduleType = loanScheduleType;
         }
 
         public String schema() {
@@ -1160,7 +1162,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                     this.disbursement.disbursementDate(), 
this.disbursement.getPrincipal(), this.totalFeeChargesDueAtDisbursement,
                     this.disbursement.isDisbursed());
 
-            final Collection<LoanSchedulePeriodData> periods = new 
ArrayList<>();
+            final List<LoanSchedulePeriodData> periods = new ArrayList<>();
             final MonetaryCurrency monCurrency = new 
MonetaryCurrency(this.currency.getCode(), this.currency.getDecimalPlaces(),
                     this.currency.getInMultiplesOf());
             BigDecimal totalPrincipalDisbursed = BigDecimal.ZERO;
@@ -1170,7 +1172,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                 totalPrincipalDisbursed = Money.of(monCurrency, 
this.disbursement.getPrincipal()).getAmount();
             } else {
                 if (!this.disbursement.isDisbursed()) {
-                    excludePastUndisbursed = false;
+                    excludePastUnDisbursed = false;
                 }
                 for (DisbursementData data : disbursementData) {
                     if (data.getChargeAmount() != null) {
@@ -1211,56 +1213,11 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                 final LocalDate obligationsMetOnDate = 
JdbcSupport.getLocalDate(rs, "obligationsMetOnDate");
                 final boolean complete = rs.getBoolean("complete");
                 final boolean isAdditional = rs.getBoolean("isAdditional");
-                BigDecimal principal = BigDecimal.ZERO;
+                BigDecimal disbursedAmount = BigDecimal.ZERO;
                 if (!isAdditional) {
-                    for (final DisbursementData data : disbursementData) {
-                        if 
(fromDate.equals(this.disbursement.disbursementDate()) && 
data.disbursementDate().equals(fromDate)
-                                && 
!disbursementPeriodIds.contains(data.getId())) {
-                            principal = principal.add(data.getPrincipal());
-                            LoanSchedulePeriodData periodData = null;
-                            if (data.getChargeAmount() == null) {
-                                periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(),
-                                        disbursementChargeAmount, 
data.isDisbursed());
-                            } else {
-                                periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(),
-                                        
disbursementChargeAmount.add(data.getChargeAmount()).subtract(waivedChargeAmount),
-                                        data.isDisbursed());
-                            }
-                            periods.add(periodData);
-                            this.outstandingLoanPrincipalBalance = 
this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
-                            disbursementPeriodIds.add(data.getId());
-                        } else if (data.isDueForDisbursement(fromDate, 
dueDate) && !disbursementPeriodIds.contains(data.getId())) {
-                            if (!excludePastUndisbursed || data.isDisbursed() 
|| !DateUtils.isBeforeBusinessDate(data.disbursementDate())) {
-                                principal = principal.add(data.getPrincipal());
-                                LoanSchedulePeriodData periodData;
-                                if (data.getChargeAmount() == null) {
-                                    periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(),
-                                            BigDecimal.ZERO, 
data.isDisbursed());
-                                } else {
-                                    periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(),
-                                            data.getChargeAmount(), 
data.isDisbursed());
-                                }
-                                periods.add(periodData);
-                                this.outstandingLoanPrincipalBalance = 
this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
-                                disbursementPeriodIds.add(data.getId());
-                            }
-                        } else if (fromDate.equals(dueDate) && 
data.disbursementDate().equals(fromDate)
-                                && 
!disbursementPeriodIds.contains(data.getId())) {
-                            principal = principal.add(data.getPrincipal());
-                            LoanSchedulePeriodData periodData = null;
-                            if (data.getChargeAmount() == null) {
-                                periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(),
-                                        disbursementChargeAmount, 
data.isDisbursed());
-                            } else {
-                                periodData = 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(),
-                                        
disbursementChargeAmount.add(data.getChargeAmount()).subtract(waivedChargeAmount),
-                                        data.isDisbursed());
-                            }
-                            periods.add(periodData);
-                            this.outstandingLoanPrincipalBalance = 
this.outstandingLoanPrincipalBalance.add(data.getPrincipal());
-                            disbursementPeriodIds.add(data.getId());
-                        }
-                    }
+                    disbursedAmount = 
processDisbursementData(loanScheduleType, disbursementData, fromDate, dueDate, 
disbursementPeriodIds,
+                            disbursementChargeAmount, waivedChargeAmount, 
periods);
+
                 }
                 // Add the Charge back or Credits to the initial amount to 
avoid negative balance
                 final BigDecimal credits = 
JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalCredits");
@@ -1268,7 +1225,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                     this.outstandingLoanPrincipalBalance = 
this.outstandingLoanPrincipalBalance.add(credits);
                 }
 
-                totalPrincipalDisbursed = 
totalPrincipalDisbursed.add(principal);
+                totalPrincipalDisbursed = 
totalPrincipalDisbursed.add(disbursedAmount);
 
                 Integer daysInPeriod = 0;
                 if (fromDate != null) {
@@ -1379,6 +1336,39 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                     totalPaidLate.getAmount(), totalOutstanding.getAmount(), 
totalCredits.getAmount());
         }
 
+        private BigDecimal processDisbursementData(LoanScheduleType 
loanScheduleType, Collection<DisbursementData> disbursementData,
+                LocalDate fromDate, LocalDate dueDate, Set<Long> 
disbursementPeriodIds, BigDecimal disbursementChargeAmount,
+                BigDecimal waivedChargeAmount, List<LoanSchedulePeriodData> 
periods) {
+            BigDecimal disbursedAmount = BigDecimal.ZERO;
+            for (final DisbursementData data : disbursementData) {
+                boolean isDueForDisbursement = 
data.isDueForDisbursement(loanScheduleType, fromDate, dueDate);
+                if (((fromDate.equals(this.disbursement.disbursementDate()) && 
data.disbursementDate().equals(fromDate))
+                        || (fromDate.equals(dueDate) && 
data.disbursementDate().equals(fromDate))
+                        || canAddDisbursementData(data, isDueForDisbursement, 
excludePastUnDisbursed))
+                        && !disbursementPeriodIds.contains(data.getId())) {
+                    disbursedAmount = disbursedAmount.add(data.getPrincipal());
+                    LoanSchedulePeriodData periodData = 
createLoanSchedulePeriodData(data, disbursementChargeAmount, 
waivedChargeAmount);
+                    periods.add(periodData);
+                    this.outstandingLoanPrincipalBalance = 
this.outstandingLoanPrincipalBalance.add(periodData.getPrincipalDisbursed());
+                    disbursementPeriodIds.add(data.getId());
+                }
+            }
+            return disbursedAmount;
+        }
+
+        private LoanSchedulePeriodData createLoanSchedulePeriodData(final 
DisbursementData data, BigDecimal disbursementChargeAmount,
+                BigDecimal waivedChargeAmount) {
+            BigDecimal chargeAmount = data.getChargeAmount() == null ? 
disbursementChargeAmount
+                    : 
disbursementChargeAmount.add(data.getChargeAmount()).subtract(waivedChargeAmount);
+            return 
LoanSchedulePeriodData.disbursementOnlyPeriod(data.disbursementDate(), 
data.getPrincipal(), chargeAmount,
+                    data.isDisbursed());
+        }
+
+        private boolean canAddDisbursementData(DisbursementData data, boolean 
isDueForDisbursement, boolean excludePastUnDisbursed) {
+            return (!excludePastUnDisbursed || data.isDisbursed() || 
!DateUtils.isBeforeBusinessDate(data.disbursementDate()))
+                    && isDueForDisbursement;
+        }
+
     }
 
     private static final class LoanTransactionsMapper implements 
RowMapper<LoanTransactionData> {
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 64c51a6c0..e587e126d 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
@@ -57,7 +57,6 @@ import 
org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.CommonConstants;
-import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
 import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
 import org.apache.fineract.integrationtests.common.Utils;
 import org.apache.fineract.integrationtests.common.accounting.Account;
@@ -78,7 +77,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @ExtendWith(LoanTestLifecycleExtension.class)
-public class AdvancedPaymentAllocationLoanRepaymentScheduleTest {
+public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends 
BaseLoanIntegrationTest {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(AdvancedPaymentAllocationLoanRepaymentScheduleTest.class);
     private static final String DATETIME_PATTERN = "dd MMMM yyyy";
@@ -122,10 +121,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
 
     @Test
     public void uc1() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -182,9 +178,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
     // UC2: Overpayment1
     // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@@ -195,10 +189,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
 
     @Test
     public void uc2() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -255,9 +246,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 
0.0);
             validateLoanTransaction(loanDetails, 4, 125.0, 100.0, 25.0, 0.0);
             assertTrue(loanDetails.getStatus().getOverpaid());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
     // UC3: Overpayment2
     // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@@ -267,10 +256,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
 
     @Test
     public void uc3() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -327,9 +313,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 
0.0);
             validateLoanTransaction(loanDetails, 4, 125.0, 100.0, 25.0, 0.0);
             assertTrue(loanDetails.getStatus().getOverpaid());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
     // UC4: Delinquent balance
     // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@@ -340,10 +324,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
 
     @Test
     public void uc4() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -419,9 +400,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 360.0, 360.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC5: Refund past due
@@ -432,10 +411,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc5() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -507,9 +483,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 58.34, 
0.0);
             validateLoanTransaction(loanDetails, 5, 66.66, 66.66, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC7: Refund & due reamortization
@@ -521,10 +495,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc7() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -594,9 +565,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 100.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 25.0, 25.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC8: Refund after due & past due
@@ -608,10 +577,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc8() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -686,9 +652,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 100.0, 100.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC9: Refund next installment
@@ -699,10 +663,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc9() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -759,9 +720,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC10: Refund PD and next installment
@@ -773,10 +732,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc10() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -848,9 +804,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 125.0, 125.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC11: Refund Past, pay in advance installments
@@ -861,10 +815,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc11() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -913,9 +864,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 
0.0);
             validateLoanTransaction(loanDetails, 3, 100.0, 100.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC12: Refund last installment
@@ -926,10 +875,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay rest on time
     @Test
     public void uc12() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -986,9 +932,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 
0.0);
             validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 50.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC13: Due apply last installment
@@ -1000,10 +944,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. Pay rest on time
     @Test
     public void uc13() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1074,9 +1015,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 75.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 50.0, 50.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC14: Refund PD
@@ -1088,10 +1027,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. Pay rest on time
     @Test
     public void uc14() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1164,9 +1100,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 175.0, 175.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC15: Goodwill credit PD
@@ -1178,10 +1112,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. Pay rest on time
     @Test
     public void uc15() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1251,9 +1182,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 75.0, 
0.0);
             validateLoanTransaction(loanDetails, 5, 50.0, 50.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC17a: Full refund with CBR
@@ -1265,10 +1194,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. CBR
     @Test
     public void uc17a() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1312,9 +1238,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 
0.0);
             validateLoanTransaction(loanDetails, 3, 125.0, 0.0, 125.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC17b: Full refund with CBR
@@ -1326,10 +1250,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. CBR
     @Test
     public void uc17b() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1373,9 +1294,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 
0.0);
             validateLoanTransaction(loanDetails, 3, 125.0, 0.0, 125.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC17c: Full refund with CBR
@@ -1387,10 +1306,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. CBR
     @Test
     public void uc17c() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1434,9 +1350,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 
0.0);
             validateLoanTransaction(loanDetails, 3, 125.0, 0.0, 125.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC18: Full refund with CBR (N+1)
@@ -1448,10 +1362,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. CBR
     @Test
     public void uc18() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1530,9 +1441,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 6, 500.0, 0.0, 500.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC24: Merchant issued credit reverse-replay
@@ -1546,10 +1455,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 7. Payments
     @Test
     public void uc24() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1651,9 +1557,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 
0.0);
             validateLoanTransaction(loanDetails, 7, 125.0, 125.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC25: Merchant issued credit reverse-replay with uneven balances
@@ -1665,10 +1569,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 5. Merchant issued credit
     @Test
     public void uc25() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
+        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");
@@ -1725,9 +1626,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, 125.0, 115.0, 10.0, 115.0, 
0.0);
             validateLoanTransaction(loanDetails, 4, 40.0, 40.0, 0.0, 10.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC101: Multiple disbursement test
@@ -1737,11 +1636,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 3. Disburse again
     @Test
     public void uc101() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("20 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -1808,9 +1703,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 2, 22), 
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 0.0, 100.0, 0.0, 0.0,
                     0.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC102: Multiple disbursement & reschedule test
@@ -1822,11 +1715,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Reschedule the 3rd period to be later than the 2nd disbursement
     @Test
     public void uc102() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("20 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -1907,9 +1796,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 25), 
218.75, 100.0, 118.75, 100.0, 0.0);
             validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 12), 
218.75, 0.0, 218.75, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC103: Advanced payment allocation, add charge after maturity -> N+1 
installment, repay the loan
@@ -1919,11 +1806,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 3. Fully repay the loan
     @Test
     public void uc103() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -1978,9 +1861,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 2, 22), 
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 0.0, 0.0,
                     0.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getClosedObligationsMet());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC104: Advanced payment allocation, horizontal repayment processing
@@ -1991,11 +1872,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay little more than the principal of 1st installment and charge of 
2nd installment
     @Test
     public void uc104() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2063,9 +1940,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
                     0.0, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC105: Advanced payment allocation, vertical repayment processing
@@ -2076,11 +1951,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 4. Pay little more than the charges
     @Test
     public void uc105() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2148,9 +2019,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 25.0, 0.0, 0.0, 0.0,
                     0.0, 0.0, 25.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC106: Advanced payment allocation, horizontal repayment processing, 
mixed grouping of allocation rules
@@ -2158,11 +2027,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 1. Create a Loan product, but the allocation rules are mixed -> expect 
validation error
     @Test
     public void uc106() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2176,9 +2041,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             assertNotNull(loanProductErrorData);
             
assertEquals("mixed.due.type.allocation.rules.are.not.supported.with.horizontal.installment.processing",
                     
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC107: Advanced payment allocation, vertical repayment processing, 
mixed grouping of allocation rules
@@ -2188,11 +2051,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 3. Change to HORIZONTAL loan schedule processing and allocation rules 
are mixed - > expect validation error
     @Test
     public void uc107() {
-        try {
-
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2220,9 +2079,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             assertEquals(400, exception.getResponse().code());
             assertTrue(exception.getMessage()
                     
.contains("mixed.due.type.allocation.rules.are.not.supported.with.horizontal.installment.processing"));
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC108: Advanced payment allocation, progressive loan schedule handling, 
rounding test
@@ -2231,10 +2088,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 2. Submit the loan, and check the generated repayment schedule
     @Test
     public void uc108() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2313,9 +2167,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 
166.65, 0.0, 166.65, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
 
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC109: Advanced payment allocation, cumulative loan schedule handling, 
rounding test
@@ -2324,10 +2176,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 2. Submit the loan, and check the generated repayment schedule
     @Test
     public void uc109() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2406,9 +2255,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 
166.65, 0.0, 166.65, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
 
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC110: Advanced payment allocation, progressive loan schedule handling, 
rounding test
@@ -2417,10 +2264,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 2. Submit the loan, and check the generated repayment schedule
     @Test
     public void uc110() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2462,9 +2306,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
10.13, 0.0, 10.13, 0.0, 0.0);
             validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
10.12, 0.0, 10.12, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC111: Advanced payment allocation, cumulative loan schedule handling, 
rounding test
@@ -2473,10 +2315,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 2. Submit the loan, and check the generated repayment schedule
     @Test
     public void uc111() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.02.22").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("22 February 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2518,9 +2357,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
10.13, 0.0, 10.13, 0.0, 0.0);
             validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
10.12, 0.0, 10.12, 0.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC112: Advanced payment allocation, horizontal repayment processing
@@ -2534,10 +2371,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 7. Do goodwill credit (in advance payment)
     @Test
     public void uc112() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.09.01").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("01 September 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2629,9 +2463,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 
20.0, 20.0, 0.0);
             validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 
20.0, 20.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC113: Advanced payment allocation, vertical repayment processing
@@ -2645,10 +2477,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 7. Do goodwill credit (in advance payment)
     @Test
     public void uc113() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.09.01").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("01 September 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2739,9 +2568,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 
20.0, 20.0, 0.0);
             validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 
20.0, 20.0, 0.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC114: Advanced payment allocation, horizontal repayment processing
@@ -2755,10 +2582,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 7. Do merchant issued refund (in advance payment)
     @Test
     public void uc114() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.09.01").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("01 September 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2849,9 +2673,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 
20.0, 10.0, 10.0);
             validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 
20.0, 10.0, 10.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
     }
 
     // UC115: Advanced payment allocation, vertical repayment processing
@@ -2865,10 +2687,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     // 7. Do merchant issued refund (in advance payment)
     @Test
     public void uc115() {
-        try {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
-            businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
-                    .date("2023.09.01").dateFormat("yyyy.MM.dd").locale("en"));
+        runAt("01 September 2023", () -> {
 
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
@@ -2957,9 +2776,239 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 
20.0, 10.0, 10.0);
             validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 
20.0, 10.0, 10.0);
             assertTrue(loanDetails.getStatus().getActive());
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
-        }
+        });
+    }
+
+    // UC116: Advanced payment allocation, horizontal repayment processing, 
disbursement on due date of an installment
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Disburse the loan (1000)
+    // 2. Add charge on disbursement date(50)
+    // 3. Repay down payment fully on disbursement date (250)
+    // 4. Disburse on 1st installment due date (400)
+    @Test
+    public void uc116() {
+        runAt("01 January 2023", () -> {
+            final Account assetAccount = accountHelper.createAssetAccount();
+            final Account incomeAccount = accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+            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");
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            // Add Charge Fee
+            Integer fee = ChargesHelper.createCharges(requestSpec, 
responseSpec,
+                    
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "50", false));
+            
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
+                    
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee),
 "01 January 2023", "50"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1050.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), 
new PostLoansLoanIdTransactionsRequest()
+                    .dateFormat(DATETIME_PATTERN).transactionDate("01 January 
2023").locale("en").transactionAmount(250.0));
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 800.0, 250.0, 750.0, 
250.0, null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 250.0, 0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            updateBusinessDate("16 January 2023");
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("16 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(400.0)).locale("en"));
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1200.0, 250.0, 1150.0, 
250.0, null);
+            validatePeriod(loanDetails, 0, LocalDate.of(2023, 1, 1), null, 
1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
LocalDate.of(2023, 1, 1), 750.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), null, 
500.0, 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 3, LocalDate.of(2023, 1, 16), null, 
400.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 4, LocalDate.of(2023, 1, 16), null, 
800.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 5, LocalDate.of(2023, 1, 31), null, 
400.0, 400.0, 0.0, 400.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 6, LocalDate.of(2023, 2, 15), null, 
0.0, 400.0, 0.0, 400.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+        });
+    }
+
+    // UC117: Advanced payment allocation, horizontal repayment processing, 
multi disbursement on due date of an
+    // installment
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Disburse the loan (1000)
+    // 2. Add charge on disbursement date(50)
+    // 3. Repay down payment fully on disbursement date (250)
+    // 4. Disburse on 1st installment due date (400)
+    // 4. Disburse on 1st installment due date (80)
+    @Test
+    public void uc117() {
+        runAt("01 January 2023", () -> {
+            final Account assetAccount = accountHelper.createAssetAccount();
+            final Account incomeAccount = accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+            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");
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            // Add Charge Fee
+            Integer fee = ChargesHelper.createCharges(requestSpec, 
responseSpec,
+                    
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
 "50", false));
+            
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
+                    
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee),
 "01 January 2023", "50"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1050.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), 
new PostLoansLoanIdTransactionsRequest()
+                    .dateFormat(DATETIME_PATTERN).transactionDate("01 January 
2023").locale("en").transactionAmount(250.0));
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 800.0, 250.0, 750.0, 
250.0, null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 250.0, 0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            updateBusinessDate("16 January 2023");
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("16 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(400.0)).locale("en"));
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("16 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(80.0)).locale("en"));
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1280.0, 250.0, 1230.0, 
250.0, null);
+            validatePeriod(loanDetails, 0, LocalDate.of(2023, 1, 1), null, 
1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
LocalDate.of(2023, 1, 1), 750.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), null, 
500.0, 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 3, LocalDate.of(2023, 1, 16), null, 
400.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 4, LocalDate.of(2023, 1, 16), null, 
80.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 5, LocalDate.of(2023, 1, 16), null, 
880.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 6, LocalDate.of(2023, 1, 16), null, 
860.0, 20.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 7, LocalDate.of(2023, 1, 31), null, 
430.0, 430.0, 0.0, 430.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 8, LocalDate.of(2023, 2, 15), null, 
0.0, 430.0, 0.0, 430.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+        });
+    }
+
+    // UC118: Advanced payment allocation, horizontal repayment processing, 
multi disbursement on disbursement date
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Disburse the loan (1000)
+    // 2. Disburse on disbursement date (400)
+    @Test
+    public void uc118() {
+        runAt("01 January 2023", () -> {
+            final Account assetAccount = accountHelper.createAssetAccount();
+            final Account incomeAccount = accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+            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");
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 
250.0, 0.0, 250.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(400.0)).locale("en"));
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1400.0, 0.0, 1400.0, 0.0, 
null);
+            validatePeriod(loanDetails, 0, LocalDate.of(2023, 1, 1), null, 
1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), null, 
400.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
+                    null, null, null, null);
+            validatePeriod(loanDetails, 2, LocalDate.of(2023, 1, 1), null, 
1150.0, 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 3, LocalDate.of(2023, 1, 1), null, 
1050.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 4, LocalDate.of(2023, 1, 16), null, 
700.0, 350.0, 0.0, 350.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 5, LocalDate.of(2023, 1, 31), null, 
350.0, 350.0, 0.0, 350.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0, 0.0);
+            validatePeriod(loanDetails, 6, LocalDate.of(2023, 2, 15), null, 
0.0, 350.0, 0.0, 350.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                    0.0, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+        });
     }
 
     private static void validateLoanSummaryBalances(GetLoansLoanIdResponse 
loanDetails, Double totalOutstanding, Double totalRepayment,
@@ -3085,6 +3134,30 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         return loanTransactionHelper.getLoanProductId(loanProductJSON);
     }
 
+    private static void validatePeriod(GetLoansLoanIdResponse loanDetails, 
Integer index, LocalDate dueDate, LocalDate paidDate,
+            Double balanceOfLoan, Double principalDue, Double principalPaid, 
Double principalOutstanding, Double feeDue, Double feePaid,
+            Double feeOutstanding, Double penaltyDue, Double penaltyPaid, 
Double penaltyOutstanding, Double interestDue,
+            Double interestPaid, Double interestOutstanding, Double 
paidInAdvance, Double paidLate) {
+        GetLoansLoanIdRepaymentPeriod period = 
loanDetails.getRepaymentSchedule().getPeriods().get(index);
+        assertEquals(dueDate, period.getDueDate());
+        assertEquals(paidDate, period.getObligationsMetOnDate());
+        assertEquals(balanceOfLoan, 
period.getPrincipalLoanBalanceOutstanding());
+        assertEquals(principalDue, period.getPrincipalDue());
+        assertEquals(principalPaid, period.getPrincipalPaid());
+        assertEquals(principalOutstanding, period.getPrincipalOutstanding());
+        assertEquals(feeDue, period.getFeeChargesDue());
+        assertEquals(feePaid, period.getFeeChargesPaid());
+        assertEquals(feeOutstanding, period.getFeeChargesOutstanding());
+        assertEquals(penaltyDue, period.getPenaltyChargesDue());
+        assertEquals(penaltyPaid, period.getPenaltyChargesPaid());
+        assertEquals(penaltyOutstanding, 
period.getPenaltyChargesOutstanding());
+        assertEquals(interestDue, period.getInterestDue());
+        assertEquals(interestPaid, period.getInterestPaid());
+        assertEquals(interestOutstanding, period.getInterestOutstanding());
+        assertEquals(paidInAdvance, period.getTotalPaidInAdvanceForPeriod());
+        assertEquals(paidLate, period.getTotalPaidLateForPeriod());
+    }
+
     private static void validateRepaymentPeriod(GetLoansLoanIdResponse 
loanDetails, Integer index, LocalDate dueDate, double principalDue,
             double principalPaid, double principalOutstanding, double 
paidInAdvance, double paidLate) {
         GetLoansLoanIdRepaymentPeriod period = 
loanDetails.getRepaymentSchedule().getPeriods().stream()
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 6d8ec7b7c..469f3f339 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
@@ -498,4 +498,9 @@ public abstract class BaseLoanIntegrationTest {
         public static final Integer MONTHS = 2;
         public static final Integer YEARS = 3;
     }
+
+    public void updateBusinessDate(String date) {
+        businessDateHelper.updateBusinessDate(
+                new 
BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
+    }
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountChargeOffWithAdvancedPaymentAllocationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountChargeOffWithAdvancedPaymentAllocationTest.java
index 06275fb93..ecbc6970e 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountChargeOffWithAdvancedPaymentAllocationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountChargeOffWithAdvancedPaymentAllocationTest.java
@@ -18,9 +18,6 @@
  */
 package org.apache.fineract.integrationtests;
 
-import static java.lang.Boolean.FALSE;
-import static java.lang.Boolean.TRUE;
-import static 
org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType.BUSINESS_DATE;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -42,7 +39,6 @@ import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.AllowAttributeOverrides;
-import org.apache.fineract.client.models.BusinessDateRequest;
 import org.apache.fineract.client.models.ChargeData;
 import org.apache.fineract.client.models.ChargeToGLAccountMapper;
 import 
org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
@@ -61,7 +57,6 @@ import 
org.apache.fineract.client.models.PostPaymentTypesRequest;
 import org.apache.fineract.client.models.PostPaymentTypesResponse;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
-import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
 import org.apache.fineract.integrationtests.common.PaymentTypeHelper;
 import org.apache.fineract.integrationtests.common.Utils;
 import org.apache.fineract.integrationtests.common.accounting.Account;
@@ -83,7 +78,7 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
 @ExtendWith(LoanTestLifecycleExtension.class)
-public class LoanAccountChargeOffWithAdvancedPaymentAllocationTest {
+public class LoanAccountChargeOffWithAdvancedPaymentAllocationTest extends 
BaseLoanIntegrationTest {
 
     private static final DateTimeFormatter DATE_FORMATTER = new 
DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
     private ResponseSpecification responseSpec;
@@ -777,23 +772,4 @@ public class 
LoanAccountChargeOffWithAdvancedPaymentAllocationTest {
             return paymentAllocationOrder;
         }).toList();
     }
-
-    private void runAt(String date, Runnable runnable) {
-        try {
-            
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, 
responseSpec, 42, true);
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, TRUE);
-            businessDateHelper.updateBusinessDate(
-                    new 
BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
-            runnable.run();
-        } finally {
-            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, FALSE);
-            
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(requestSpec, 
responseSpec, 42, false);
-        }
-    }
-
-    private void updateBusinessDate(String date) {
-        businessDateHelper.updateBusinessDate(
-                new 
BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
-    }
-
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java
index 9a9ec44a6..34f17cf22 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTest.java
@@ -724,16 +724,16 @@ public class 
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
             // down payment period [1]
             
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
                     LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
-            // disbursement period [2]
-            
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2),
 LocalDate.of(2023, 4, 3), 200.0);
-            // down payment period [3]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(3), 2, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
-                    LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
-            // regular installment [4]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 
150.0, 0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0,
+            // regular installment [2]
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 
75.0, 50.0, 50.0, 25.0, 0.0, 0.0, 0.0, 0.0,
                     false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
+            // disbursement period [3]
+            
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3),
 LocalDate.of(2023, 4, 3), 200.0);
+            // down payment period [4]
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 3, 
50.0, 0.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, false,
+                    LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
             // regular installment [5]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 
150.0, 0.0, 0.0, 150.0, 0.0, 0.0, 0.0, 0.0,
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 4, 
225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
                     false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
 
             // same day third disbursement with overlapping installment i.e 
same due date as regular repayment due date
@@ -758,21 +758,21 @@ public class 
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
             // down payment period [1]
             
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
                     LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
-            // disbursement period [2]
-            
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2),
 LocalDate.of(2023, 4, 3), 200.0);
+            // regular installment [2]
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 
75.0, 75.0, 75.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
+                    LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
             // disbursement period [3]
             
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3),
 LocalDate.of(2023, 4, 3), 200.0);
-            // down payment period [4]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
-                    LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
+            // disbursement period [4]
+            
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(4),
 LocalDate.of(2023, 4, 3), 200.0);
             // down payment period [5]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 
50.0, 25.0, 25.0, 25.0, 0.0, 0.0, 0.0, 0.0,
+                    false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
+            // down payment period [6]
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 
50.0, 0.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, false,
                     LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
-            // regular installment [6]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 
225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
-                    false, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
             // regular installment [7]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 
225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 
375.0, 0.0, 0.0, 375.0, 0.0, 0.0, 0.0, 0.0,
                     false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
 
             // make repayment for fully paying and verify that regular 
installment gets fully paid on 3rd april
@@ -791,21 +791,21 @@ public class 
LoanAccountPaymentAllocationWithOverlappingDownPaymentInstallmentTe
             // down payment period [1]
             
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(1), 1, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
                     LocalDate.of(2023, 3, 3), LocalDate.of(2023, 3, 3));
-            // disbursement period [2]
-            
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(2),
 LocalDate.of(2023, 4, 3), 200.0);
+            // regular installment [2]
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(2), 2, 
75.0, 75.0, 75.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
+                    LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
             // disbursement period [3]
             
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(3),
 LocalDate.of(2023, 4, 3), 200.0);
-            // down payment period [4]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(4), 2, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
-                    LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
+            // disbursement period [4]
+            
verifyDisbursementPeriod(loanDetails.getRepaymentSchedule().getPeriods().get(4),
 LocalDate.of(2023, 4, 3), 200.0);
             // down payment period [5]
             
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(5), 3, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
                     LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
-            // regular installment [6]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 
225.0, 225.0, 225.0, 0.0, 0.0, 0.0, 0.0, 0.0,
-                    true, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3));
+            // down payment period [6]
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(6), 4, 
50.0, 50.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, true,
+                    LocalDate.of(2023, 4, 3), LocalDate.of(2023, 4, 3));
             // regular installment [7]
-            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 
225.0, 0.0, 0.0, 225.0, 0.0, 0.0, 0.0, 0.0,
+            
verifyPeriodDetails(loanDetails.getRepaymentSchedule().getPeriods().get(7), 5, 
375.0, 150.0, 150.0, 225.0, 0.0, 0.0, 0.0, 0.0,
                     false, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3));
 
         } finally {
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java
index c13939f80..5cbf0e594 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java
@@ -124,7 +124,7 @@ public class LoanProductRepaymentStartDateConfigurationTest 
{
         try {
 
             // Set business date
-            LocalDate businessDate = LocalDate.of(2023, 03, 3);
+            LocalDate businessDate = LocalDate.of(2023, 3, 3);
 
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, businessDate);
@@ -169,25 +169,25 @@ public class 
LoanProductRepaymentStartDateConfigurationTest {
 
             // first period [2023-03-03 to 2023-04-03]
             assertEquals(1, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
-            assertEquals(LocalDate.of(2023, 03, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
-            assertEquals(LocalDate.of(2023, 04, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
+            assertEquals(LocalDate.of(2023, 3, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
+            assertEquals(LocalDate.of(2023, 4, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
 
             // second period [2023-04-03 to 2023-05-03]
             assertEquals(2, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
-            assertEquals(LocalDate.of(2023, 04, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
-            assertEquals(LocalDate.of(2023, 05, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
+            assertEquals(LocalDate.of(2023, 4, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
+            assertEquals(LocalDate.of(2023, 5, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
 
             // third period [2023-05-03 to 2023-06-03]
             assertEquals(3, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
-            assertEquals(LocalDate.of(2023, 05, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
-            assertEquals(LocalDate.of(2023, 06, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
+            assertEquals(LocalDate.of(2023, 5, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
+            assertEquals(LocalDate.of(2023, 6, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
             assertEquals(333.34, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
 
             // first disbursement on a future date (7 March 2023)
 
-            LocalDate disbursementDate = LocalDate.of(2023, 03, 7);
+            LocalDate disbursementDate = LocalDate.of(2023, 3, 7);
 
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
 
@@ -208,25 +208,25 @@ public class 
LoanProductRepaymentStartDateConfigurationTest {
 
             // first period [2023-03-03 to 2023-04-03]
             assertEquals(1, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
-            assertEquals(LocalDate.of(2023, 03, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
-            assertEquals(LocalDate.of(2023, 04, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
+            assertEquals(LocalDate.of(2023, 3, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
+            assertEquals(LocalDate.of(2023, 4, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
             assertEquals(166.67, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
 
             // second period [2023-04-03 to 2023-05-03]
             assertEquals(2, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
-            assertEquals(LocalDate.of(2023, 04, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
-            assertEquals(LocalDate.of(2023, 05, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
+            assertEquals(LocalDate.of(2023, 4, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
+            assertEquals(LocalDate.of(2023, 5, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
             assertEquals(166.67, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
 
             // third period [2023-05-03 to 2023-06-03]
             assertEquals(3, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
-            assertEquals(LocalDate.of(2023, 05, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
-            assertEquals(LocalDate.of(2023, 06, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
+            assertEquals(LocalDate.of(2023, 5, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
+            assertEquals(LocalDate.of(2023, 6, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
             assertEquals(166.66, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
 
             // second disbursement next month (7 April 2023)
 
-            disbursementDate = LocalDate.of(2023, 04, 7);
+            disbursementDate = LocalDate.of(2023, 4, 7);
 
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
 
@@ -248,20 +248,20 @@ public class 
LoanProductRepaymentStartDateConfigurationTest {
 
             // first period [2023-03-03 to 2023-04-03]
             assertEquals(1, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
-            assertEquals(LocalDate.of(2023, 03, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
-            assertEquals(LocalDate.of(2023, 04, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
+            assertEquals(LocalDate.of(2023, 3, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
+            assertEquals(LocalDate.of(2023, 4, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
             assertEquals(166.67, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
 
             // second period [2023-04-03 to 2023-05-03]
             assertEquals(2, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
-            assertEquals(LocalDate.of(2023, 04, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
-            assertEquals(LocalDate.of(2023, 05, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
+            assertEquals(LocalDate.of(2023, 4, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
+            assertEquals(LocalDate.of(2023, 5, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
 
             // third period [2023-05-03 to 2023-06-03]
             assertEquals(3, 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod());
-            assertEquals(LocalDate.of(2023, 05, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
-            assertEquals(LocalDate.of(2023, 06, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
+            assertEquals(LocalDate.of(2023, 5, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
+            assertEquals(LocalDate.of(2023, 6, 3), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
             assertEquals(500.00, 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod());
 
         } finally {
@@ -278,7 +278,7 @@ public class LoanProductRepaymentStartDateConfigurationTest 
{
         try {
 
             // Set business date
-            LocalDate businessDate = LocalDate.of(2023, 03, 3);
+            LocalDate businessDate = LocalDate.of(2023, 3, 3);
 
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, businessDate);
@@ -324,25 +324,25 @@ public class 
LoanProductRepaymentStartDateConfigurationTest {
 
             // first period [2023-03-07 to 2023-04-07]
             assertEquals(1, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
-            assertEquals(LocalDate.of(2023, 03, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
-            assertEquals(LocalDate.of(2023, 04, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
+            assertEquals(LocalDate.of(2023, 3, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
+            assertEquals(LocalDate.of(2023, 4, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
 
             // second period [2023-04-07 to 2023-05-07]
             assertEquals(2, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
-            assertEquals(LocalDate.of(2023, 04, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
-            assertEquals(LocalDate.of(2023, 05, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
+            assertEquals(LocalDate.of(2023, 4, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
+            assertEquals(LocalDate.of(2023, 5, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
 
             // third period [2023-05-07 to 2023-06-07]
             assertEquals(3, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
-            assertEquals(LocalDate.of(2023, 05, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
-            assertEquals(LocalDate.of(2023, 06, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
+            assertEquals(LocalDate.of(2023, 5, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
+            assertEquals(LocalDate.of(2023, 6, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
             assertEquals(333.34, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
 
             // first disbursement (7 March 2023)
 
-            LocalDate disbursementDate = LocalDate.of(2023, 03, 7);
+            LocalDate disbursementDate = LocalDate.of(2023, 3, 7);
 
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
 
@@ -364,25 +364,25 @@ public class 
LoanProductRepaymentStartDateConfigurationTest {
 
             // first period [2023-03-07 to 2023-04-07]
             assertEquals(1, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod());
-            assertEquals(LocalDate.of(2023, 03, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
-            assertEquals(LocalDate.of(2023, 04, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
+            assertEquals(LocalDate.of(2023, 3, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate());
+            assertEquals(LocalDate.of(2023, 4, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate());
             assertEquals(166.67, 
loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod());
 
             // second period [2023-04-07 to 2023-05-07]
             assertEquals(2, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
-            assertEquals(LocalDate.of(2023, 04, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
-            assertEquals(LocalDate.of(2023, 05, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
+            assertEquals(LocalDate.of(2023, 4, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
+            assertEquals(LocalDate.of(2023, 5, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
             assertEquals(166.67, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
 
             // third period [2023-05-07 to 2023-06-07]
             assertEquals(3, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
-            assertEquals(LocalDate.of(2023, 05, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
-            assertEquals(LocalDate.of(2023, 06, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
+            assertEquals(LocalDate.of(2023, 5, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
+            assertEquals(LocalDate.of(2023, 6, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
             assertEquals(166.66, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
 
             // second disbursement next month (7 April 2023)
 
-            disbursementDate = LocalDate.of(2023, 04, 7);
+            disbursementDate = LocalDate.of(2023, 4, 7);
 
             BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
 
@@ -405,20 +405,20 @@ public class 
LoanProductRepaymentStartDateConfigurationTest {
 
             // first period [2023-03-07 to 2023-04-07]
             assertEquals(1, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod());
-            assertEquals(LocalDate.of(2023, 03, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
-            assertEquals(LocalDate.of(2023, 04, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
+            assertEquals(LocalDate.of(2023, 3, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate());
+            assertEquals(LocalDate.of(2023, 4, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod());
 
             // second period [2023-04-07 to 2023-05-07]
             assertEquals(2, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod());
-            assertEquals(LocalDate.of(2023, 04, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
-            assertEquals(LocalDate.of(2023, 05, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
+            assertEquals(LocalDate.of(2023, 4, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate());
+            assertEquals(LocalDate.of(2023, 5, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate());
             assertEquals(333.33, 
loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod());
 
             // third period [2023-05-07 to 2023-06-07]
             assertEquals(3, 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod());
-            assertEquals(LocalDate.of(2023, 05, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
-            assertEquals(LocalDate.of(2023, 06, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
+            assertEquals(LocalDate.of(2023, 5, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate());
+            assertEquals(LocalDate.of(2023, 6, 7), 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate());
             assertEquals(333.34, 
loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod());
 
         } finally {


Reply via email to