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 d0341e69c FINERACT-1968: Fix rounding issue
d0341e69c is described below

commit d0341e69cb101da995fd8e34f5e05ce43274ca09
Author: Adam Saghy <[email protected]>
AuthorDate: Thu Nov 16 18:55:23 2023 +0100

    FINERACT-1968: Fix rounding issue
---
 ...dvancedPaymentScheduleTransactionProcessor.java |   4 +-
 .../AbstractCumulativeLoanScheduleGenerator.java   |  47 ++-
 .../AbstractProgressiveLoanScheduleGenerator.java  |  28 +-
 ...PaymentAllocationLoanRepaymentScheduleTest.java | 437 +++++++++++++++++----
 4 files changed, 407 insertions(+), 109 deletions(-)

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 071d2f73e..cedbadfe5 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
@@ -313,8 +313,8 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
         if (installmentAmountInMultiplesOf != null) {
             increasePrincipalBy = 
Money.roundToMultiplesOf(increasePrincipalBy, installmentAmountInMultiplesOf);
         }
-        Money remainingAmount = 
increasePrincipalBy.multiplyRetainScale(noCandidateRepaymentInstallments, 
mc.getRoundingMode())
-                .minus(amortizableAmount);
+        Money remainingAmount = amortizableAmount
+                
.minus(increasePrincipalBy.multiplyRetainScale(noCandidateRepaymentInstallments,
 mc.getRoundingMode()));
 
         Money finalIncreasePrincipalBy = increasePrincipalBy;
         candidateRepaymentInstallments
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
index fd3bf5bf6..957ede516 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java
@@ -132,10 +132,10 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
                 loanApplicationTerms.getLoanCalendar(), 
loanApplicationTerms.getHolidayDetailDTO(), loanApplicationTerms);
 
         if (!scheduleParams.isPartialUpdate()) {
-            BigDecimal downPaymentAmount = BigDecimal.ZERO;
+            Money downPaymentAmount = Money.zero(currency);
             if (loanApplicationTerms.isDownPaymentEnabled()) {
-                downPaymentAmount = 
MathUtil.percentageOf(scheduleParams.getOutstandingBalance().getAmount(),
-                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19);
+                downPaymentAmount = Money.of(currency, 
MathUtil.percentageOf(scheduleParams.getOutstandingBalance().getAmount(),
+                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
                 if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() 
!= null) {
                     downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount,
                             
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
@@ -143,27 +143,27 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
             }
             Money calculatedAmortizableAmount = 
loanApplicationTerms.getPrincipal().minus(downPaymentAmount);
-            scheduleParams.reduceOutstandingBalance(Money.of(currency, 
downPaymentAmount));
+            scheduleParams.reduceOutstandingBalance(downPaymentAmount);
             // Set Fixed Principal Amount
             updateAmortization(mc, loanApplicationTerms, 
scheduleParams.getPeriodNumber(), calculatedAmortizableAmount);
 
             if (loanApplicationTerms.isMultiDisburseLoan()) {
                 /* fetches the first tranche amount and also updates other 
tranche details to map */
-                BigDecimal disburseAmt = 
getDisbursementAmount(loanApplicationTerms, scheduleParams.getPeriodStartDate(),
-                        scheduleParams.getDisburseDetailMap(), 
scheduleParams.applyInterestRecalculation());
-                BigDecimal downPaymentAmt = BigDecimal.ZERO;
+                Money disburseAmt = Money.of(currency, 
getDisbursementAmount(loanApplicationTerms, scheduleParams.getPeriodStartDate(),
+                        scheduleParams.getDisburseDetailMap(), 
scheduleParams.applyInterestRecalculation()));
+                Money downPaymentAmt = Money.zero(currency);
                 if (loanApplicationTerms.isDownPaymentEnabled()) {
-                    downPaymentAmt = MathUtil.percentageOf(disburseAmt, 
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(),
-                            19);
+                    downPaymentAmt = Money.of(currency, 
MathUtil.percentageOf(disburseAmt.getAmount(),
+                            
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
                     if 
(loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
                         downPaymentAmt = 
Money.roundToMultiplesOf(downPaymentAmt, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
                     }
                 }
-                BigDecimal remainingPrincipalAmt = 
disburseAmt.subtract(downPaymentAmt);
-                scheduleParams.setPrincipalToBeScheduled(Money.of(currency, 
remainingPrincipalAmt));
-                
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().zero().plus(remainingPrincipalAmt));
-                scheduleParams.setOutstandingBalance(Money.of(currency, 
remainingPrincipalAmt));
-                
scheduleParams.setOutstandingBalanceAsPerRest(Money.of(currency, 
remainingPrincipalAmt));
+                Money remainingPrincipalAmt = 
disburseAmt.minus(downPaymentAmt);
+                
scheduleParams.setPrincipalToBeScheduled(remainingPrincipalAmt);
+                loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
+                scheduleParams.setOutstandingBalance(remainingPrincipalAmt);
+                
scheduleParams.setOutstandingBalanceAsPerRest(remainingPrincipalAmt);
             }
         }
 
@@ -2013,19 +2013,18 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
 
     private LoanScheduleModelDownPaymentPeriod 
createDownPaymentPeriod(LoanApplicationTerms loanApplicationTerms,
             LoanScheduleParams scheduleParams, LocalDate date, BigDecimal 
periodBaseAmount) {
-        BigDecimal downPaymentAmount = MathUtil.percentageOf(periodBaseAmount,
-                
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19);
+        Money downPaymentAmount = Money.of(loanApplicationTerms.getCurrency(),
+                MathUtil.percentageOf(periodBaseAmount, 
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
         if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
             downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
         }
-        Money downPayment = Money.of(loanApplicationTerms.getCurrency(), 
downPaymentAmount);
         LoanScheduleModelDownPaymentPeriod installment = 
LoanScheduleModelDownPaymentPeriod
-                .downPayment(scheduleParams.getInstalmentNumber(), date, 
downPayment, scheduleParams.getOutstandingBalance());
+                .downPayment(scheduleParams.getInstalmentNumber(), date, 
downPaymentAmount, scheduleParams.getOutstandingBalance());
 
         addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), 
installment);
 
         scheduleParams.incrementInstalmentNumber();
-        scheduleParams.addTotalRepaymentExpected(downPayment);
+        scheduleParams.addTotalRepaymentExpected(downPaymentAmount);
 
         return installment;
     }
@@ -2236,14 +2235,14 @@ public abstract class 
AbstractCumulativeLoanScheduleGenerator implements LoanSch
             LocalDate periodStartDate = 
RepaymentStartDateType.DISBURSEMENT_DATE.equals(loanApplicationTerms.getRepaymentStartDateType())
                     ? loanApplicationTerms.getExpectedDisbursementDate()
                     : loanApplicationTerms.getSubmittedOnDate();
-            BigDecimal downPaymentAmount = BigDecimal.ZERO;
+            Money downPaymentAmount = Money.zero(currency);
             if (loanApplicationTerms.isDownPaymentEnabled()) {
-                double downPaymentAmt = 
MathUtil.percentageOf(loanScheduleParams.getOutstandingBalance().getAmount(),
-                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 
19).doubleValue();
+                downPaymentAmount = Money.of(currency, 
MathUtil.percentageOf(loanScheduleParams.getOutstandingBalance().getAmount(),
+                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
                 if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() 
!= null) {
-                    downPaymentAmt = Money.roundToMultiplesOf(downPaymentAmt, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
+                    downPaymentAmount = 
Money.roundToMultiplesOf(downPaymentAmount,
+                            
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
                 }
-                downPaymentAmount = BigDecimal.valueOf(downPaymentAmt);
             }
             Money calculatedAmortizableAmount = 
principalToBeScheduled.minus(downPaymentAmount);
             
loanScheduleParams.setOutstandingBalance(calculatedAmortizableAmount);
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 aa0645378..d0c1ba0cb 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
@@ -87,20 +87,21 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
 
         if (loanApplicationTerms.isMultiDisburseLoan()) {
             /* fetches the first tranche amount and also updates other tranche 
details to map */
-            BigDecimal disburseAmt = 
getDisbursementAmount(loanApplicationTerms, scheduleParams.getPeriodStartDate(),
-                    scheduleParams.getDisburseDetailMap(), 
scheduleParams.applyInterestRecalculation());
-            BigDecimal downPaymentAmt = BigDecimal.ZERO;
+            Money disburseAmt = Money.of(currency, 
getDisbursementAmount(loanApplicationTerms, scheduleParams.getPeriodStartDate(),
+                    scheduleParams.getDisburseDetailMap(), 
scheduleParams.applyInterestRecalculation()));
+            Money downPaymentAmt = Money.zero(currency);
             if (loanApplicationTerms.isDownPaymentEnabled()) {
-                downPaymentAmt = MathUtil.percentageOf(disburseAmt, 
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19);
+                downPaymentAmt = Money.of(currency, 
MathUtil.percentageOf(disburseAmt.getAmount(),
+                        
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
                 if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() 
!= null) {
                     downPaymentAmt = Money.roundToMultiplesOf(downPaymentAmt, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
                 }
             }
-            BigDecimal remainingPrincipalAmt = 
disburseAmt.subtract(downPaymentAmt);
-            scheduleParams.setPrincipalToBeScheduled(Money.of(currency, 
remainingPrincipalAmt));
-            
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().zero().plus(remainingPrincipalAmt));
-            scheduleParams.setOutstandingBalance(Money.of(currency, 
remainingPrincipalAmt));
-            scheduleParams.setOutstandingBalanceAsPerRest(Money.of(currency, 
remainingPrincipalAmt));
+            Money remainingPrincipalAmt = disburseAmt.minus(downPaymentAmt);
+            scheduleParams.setPrincipalToBeScheduled(remainingPrincipalAmt);
+            loanApplicationTerms.setPrincipal(remainingPrincipalAmt);
+            scheduleParams.setOutstandingBalance(remainingPrincipalAmt);
+            
scheduleParams.setOutstandingBalanceAsPerRest(remainingPrincipalAmt);
             loanApplicationTerms.resetFixedEmiAmount();
         }
 
@@ -307,19 +308,18 @@ public abstract class 
AbstractProgressiveLoanScheduleGenerator implements LoanSc
 
     private LoanScheduleModelDownPaymentPeriod 
createDownPaymentPeriod(LoanApplicationTerms loanApplicationTerms,
             LoanScheduleParams scheduleParams, LocalDate date, BigDecimal 
periodBaseAmount) {
-        BigDecimal downPaymentAmount = MathUtil.percentageOf(periodBaseAmount,
-                
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19);
+        Money downPaymentAmount = Money.of(loanApplicationTerms.getCurrency(),
+                MathUtil.percentageOf(periodBaseAmount, 
loanApplicationTerms.getDisbursedAmountPercentageForDownPayment(), 19));
         if (loanApplicationTerms.getInstallmentAmountInMultiplesOf() != null) {
             downPaymentAmount = Money.roundToMultiplesOf(downPaymentAmount, 
loanApplicationTerms.getInstallmentAmountInMultiplesOf());
         }
-        Money downPayment = Money.of(loanApplicationTerms.getCurrency(), 
downPaymentAmount);
         LoanScheduleModelDownPaymentPeriod installment = 
LoanScheduleModelDownPaymentPeriod
-                .downPayment(scheduleParams.getInstalmentNumber(), date, 
downPayment, scheduleParams.getOutstandingBalance());
+                .downPayment(scheduleParams.getInstalmentNumber(), date, 
downPaymentAmount, scheduleParams.getOutstandingBalance());
 
         addLoanRepaymentScheduleInstallment(scheduleParams.getInstallments(), 
installment);
 
         scheduleParams.incrementInstalmentNumber();
-        scheduleParams.addTotalRepaymentExpected(downPayment);
+        scheduleParams.addTotalRepaymentExpected(downPaymentAmount);
 
         return installment;
     }
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 b6ca9e83c..baa5bf31b 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
@@ -108,8 +108,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         final Account expenseAccount = accountHelper.createExpenseAccount();
         final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
 
-        commonLoanProductId = createLoanProduct("500", "15", "4", true, 
LoanScheduleType.PROGRESSIVE, LoanScheduleProcessingType.HORIZONTAL,
-                assetAccount, incomeAccount, expenseAccount, 
overpaymentAccount);
+        commonLoanProductId = createLoanProduct("500", "15", "4", true, "25", 
true, LoanScheduleType.PROGRESSIVE,
+                LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
         client = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
     }
 
@@ -126,8 +126,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -199,8 +199,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -271,8 +271,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -344,8 +344,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -436,8 +436,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -525,8 +525,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -612,8 +612,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -703,8 +703,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -777,8 +777,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -865,8 +865,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -930,8 +930,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1004,8 +1004,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1092,8 +1092,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1182,8 +1182,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1269,8 +1269,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1330,8 +1330,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1391,8 +1391,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.15").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1452,8 +1452,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1550,8 +1550,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1669,8 +1669,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             businessDateHelper.updateBusinessDate(new 
BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
                     .date("2023.02.20").dateFormat("yyyy.MM.dd").locale("en"));
 
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId, 500L, 45, 
15, 3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), commonLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1746,10 +1746,10 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             final Account incomeAccount = accountHelper.createIncomeAccount();
             final Account expenseAccount = 
accountHelper.createExpenseAccount();
             final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
-            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
false, LoanScheduleType.PROGRESSIVE,
+            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 500L, 45, 15, 
3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1831,10 +1831,10 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             final Account incomeAccount = accountHelper.createIncomeAccount();
             final Account expenseAccount = 
accountHelper.createExpenseAccount();
             final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
-            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
false, LoanScheduleType.PROGRESSIVE,
+            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 500L, 45, 15, 
3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -1928,10 +1928,10 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             final Account incomeAccount = accountHelper.createIncomeAccount();
             final Account expenseAccount = 
accountHelper.createExpenseAccount();
             final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
-            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
false, LoanScheduleType.PROGRESSIVE,
+            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 500L, 45, 15, 
3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2000,10 +2000,10 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             final Account incomeAccount = accountHelper.createIncomeAccount();
             final Account expenseAccount = 
accountHelper.createExpenseAccount();
             final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
-            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
false, LoanScheduleType.PROGRESSIVE,
+            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 500L, 45, 15, 
3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2085,10 +2085,10 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             final Account incomeAccount = accountHelper.createIncomeAccount();
             final Account expenseAccount = 
accountHelper.createExpenseAccount();
             final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
-            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
false, LoanScheduleType.PROGRESSIVE,
+            Integer localLoanProductId = createLoanProduct("500", "15", "4", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
                     LoanScheduleProcessingType.VERTICAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
-            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 500L, 45, 15, 
3, 0,
-                    "01 January 2023", "01 January 2023");
+            final PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId,
+                    BigDecimal.valueOf(500.0), 45, 15, 3, 0, "01 January 
2023", "01 January 2023");
 
             loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
                     new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
@@ -2205,15 +2205,16 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
             assertNotNull(localLoanProductId);
 
             CallFailedRuntimeException exception = 
assertThrows(CallFailedRuntimeException.class,
-                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, 500L, 45, 15, 3, 0, "01 January 2023",
-                            "01 January 2023", 
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
+                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
+                            "01 January 2023", "01 January 2023", 
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
                             LoanScheduleType.PROGRESSIVE.name(), 
LoanScheduleProcessingType.VERTICAL.name()));
             assertEquals(400, exception.getResponse().code());
             
assertTrue(exception.getMessage().contains("supported.only.with.advanced.payment.allocation.strategy"));
 
             exception = assertThrows(CallFailedRuntimeException.class,
-                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, 500L, 45, 15, 3, 0, "01 January 2023",
-                            "01 January 2023", 
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
+                    () -> applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3, 0,
+                            "01 January 2023", "01 January 2023",
+                            
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
                             LoanScheduleType.PROGRESSIVE.name(), 
LoanScheduleProcessingType.HORIZONTAL.name()));
             assertEquals(400, exception.getResponse().code());
             assertTrue(exception.getMessage()
@@ -2223,6 +2224,304 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         }
     }
 
+    // UC108: Advanced payment allocation, progressive loan schedule handling, 
rounding test
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Create a Loan product, 1000 principal, across 3 installment
+    // 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"));
+
+            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", 
false, null, false, LoanScheduleType.PROGRESSIVE,
+                    LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
+            assertNotNull(localLoanProductId);
+
+            PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(1000), 45,
+                    15, 3, 0, "01 January 2023", "01 January 2023");
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getPendingApproval());
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanResponse = applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
+                    "01 January 2023", "01 January 2023");
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 
166.65, 0.0, 166.65, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getPendingApproval());
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 
166.65, 0.0, 166.65, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            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
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Create a Loan product, 1000 principal, across 3 installment
+    // 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"));
+
+            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", 
false, null, false, LoanScheduleType.CUMULATIVE,
+                    LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
+            assertNotNull(localLoanProductId);
+
+            PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(1000), 45,
+                    15, 3, 0, "01 January 2023", "01 January 2023");
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getPendingApproval());
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
333.33, 0.0, 333.33, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
333.34, 0.0, 333.34, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getActive());
+
+            loanResponse = applyForLoanApplication(client.getClientId(), 
localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6, 0,
+                    "01 January 2023", "01 January 2023");
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 
166.65, 0.0, 166.65, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getPendingApproval());
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 
166.65, 0.0, 166.65, 0.0, 0.0);
+            assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 
166.67, 0.0, 166.67, 0.0, 0.0);
+            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
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Create a Loan product, 40.50 principal, across 4 installment (1 down 
payment, 3 normal installment)
+    // 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"));
+
+            final Account assetAccount = accountHelper.createAssetAccount();
+            final Account incomeAccount = accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+            Integer localLoanProductId = createLoanProduct("40.50", "15", "3", 
true, "25", false, LoanScheduleType.PROGRESSIVE,
+                    LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
+            assertNotNull(localLoanProductId);
+
+            PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(40.50),
+                    45, 15, 3, 0, "01 January 2023", "01 January 2023");
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
10.13, 0.0, 10.13, 0.0, 0.0);
+            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().getPendingApproval());
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(40.5)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
10.13, 0.0, 10.13, 0.0, 0.0);
+            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().getWaitingForDisbursal());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(40.5)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 40.5, 0.0, 40.5, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
10.13, 0.0, 10.13, 0.0, 0.0);
+            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
+    // ADVANCED_PAYMENT_ALLOCATION_STRATEGY
+    // 1. Create a Loan product, 40.50 principal, across 4 installment (1 down 
payment, 3 normal installment)
+    // 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"));
+
+            final Account assetAccount = accountHelper.createAssetAccount();
+            final Account incomeAccount = accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
+            Integer localLoanProductId = createLoanProduct("40.50", "15", "3", 
true, "25", false, LoanScheduleType.CUMULATIVE,
+                    LoanScheduleProcessingType.HORIZONTAL, assetAccount, 
incomeAccount, expenseAccount, overpaymentAccount);
+            assertNotNull(localLoanProductId);
+
+            PostLoansResponse loanResponse = 
applyForLoanApplication(client.getClientId(), localLoanProductId, 
BigDecimal.valueOf(40.50),
+                    45, 15, 3, 0, "01 January 2023", "01 January 2023");
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
10.13, 0.0, 10.13, 0.0, 0.0);
+            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().getPendingApproval());
+
+            loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
+                    new 
PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(40.5)).dateFormat(DATETIME_PATTERN)
+                            .approvedOnDate("01 January 2023").locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
10.13, 0.0, 10.13, 0.0, 0.0);
+            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().getWaitingForDisbursal());
+
+            loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
+                    new PostLoansLoanIdRequest().actualDisbursementDate("01 
January 2023").dateFormat(DATETIME_PATTERN)
+                            
.transactionAmount(BigDecimal.valueOf(40.5)).locale("en"));
+
+            loanDetails = 
loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
+            validateLoanSummaryBalances(loanDetails, 40.5, 0.0, 40.5, 0.0, 
null);
+            validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 
10.12, 0.0, 10.12, 0.0, 0.0);
+            validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 
10.13, 0.0, 10.13, 0.0, 0.0);
+            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);
+        }
+    }
+
     private static void validateLoanSummaryBalances(GetLoansLoanIdResponse 
loanDetails, Double totalOutstanding, Double totalRepayment,
             Double principalOutstanding, Double principalPaid, Double 
totalOverpaid) {
         assertEquals(totalOutstanding, 
loanDetails.getSummary().getTotalOutstanding());
@@ -2324,8 +2623,8 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
     }
 
     private static Integer createLoanProduct(final String principal, final 
String repaymentAfterEvery, final String numberOfRepayments,
-            boolean autoPayForDownPayment, LoanScheduleType loanScheduleType, 
LoanScheduleProcessingType loanScheduleProcessingType,
-            final Account... accounts) {
+            boolean downPaymentEnabled, String downPaymentPercentage, boolean 
autoPayForDownPayment, LoanScheduleType loanScheduleType,
+            LoanScheduleProcessingType loanScheduleProcessingType, final 
Account... accounts) {
         AdvancedPaymentData defaultAllocation = 
createDefaultPaymentAllocation();
         AdvancedPaymentData goodwillCreditAllocation = 
createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT");
         AdvancedPaymentData merchantIssuedRefundAllocation = 
createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION");
@@ -2333,7 +2632,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         LOG.info("------------------------------CREATING NEW LOAN PRODUCT 
---------------------------------------");
         final String loanProductJSON = new 
LoanProductTestBuilder().withMinPrincipal(principal).withPrincipal(principal)
                 
.withRepaymentTypeAsDays().withRepaymentAfterEvery(repaymentAfterEvery).withNumberOfRepayments(numberOfRepayments)
-                .withEnableDownPayment(true, "25", 
autoPayForDownPayment).withinterestRatePerPeriod("0")
+                .withEnableDownPayment(downPaymentEnabled, 
downPaymentPercentage, autoPayForDownPayment).withinterestRatePerPeriod("0")
                 .withInterestRateFrequencyTypeAsMonths()
                 
.withRepaymentStrategy(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
                 
.withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts)
@@ -2392,7 +2691,7 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
         assertEquals(paidLate, period.getTotalPaidLateForPeriod());
     }
 
-    private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final Long principal,
+    private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final BigDecimal principal,
             final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate, String transactionProcessorCode, String loanScheduleType,
             String loanScheduleProcessingType) {
@@ -2402,12 +2701,12 @@ public class 
AdvancedPaymentAllocationLoanRepaymentScheduleTest {
                 
.transactionProcessingStrategyCode(transactionProcessorCode).locale("en").submittedOnDate(submittedOnDate)
                 
.amortizationType(1).interestRatePerPeriod(interestRate).interestCalculationPeriodType(1).interestType(0)
                 
.repaymentFrequencyType(0).repaymentEvery(repaymentAfterEvery).repaymentFrequencyType(0)
-                
.numberOfRepayments(numberOfRepayments).loanTermFrequency(loanTermFrequency).loanTermFrequencyType(0)
-                
.principal(BigDecimal.valueOf(principal)).loanType("individual").loanScheduleProcessingType(loanScheduleProcessingType)
-                
.loanScheduleType(loanScheduleType).maxOutstandingLoanBalance(BigDecimal.valueOf(35000)));
+                
.numberOfRepayments(numberOfRepayments).loanTermFrequency(loanTermFrequency).loanTermFrequencyType(0).principal(principal)
+                
.loanType("individual").loanScheduleProcessingType(loanScheduleProcessingType).loanScheduleType(loanScheduleType)
+                .maxOutstandingLoanBalance(BigDecimal.valueOf(35000)));
     }
 
-    private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final Long principal,
+    private static PostLoansResponse applyForLoanApplication(final Long 
clientId, final Integer loanProductId, final BigDecimal principal,
             final int loanTermFrequency, final int repaymentAfterEvery, final 
int numberOfRepayments, final int interestRate,
             final String expectedDisbursementDate, final String 
submittedOnDate) {
         LOG.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");

Reply via email to