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 f452ce2ca FINERACT-1968  - integration tests added for validating 
chargeback support.
f452ce2ca is described below

commit f452ce2cadeeb4d93a24786c2ec217a81a76e5c3
Author: Peter Bagrij <peter.bag...@dpc.hu>
AuthorDate: Sun Sep 24 13:51:35 2023 +0200

    FINERACT-1968
     - integration tests added for validating chargeback support.
---
 build.gradle                                       |   1 +
 .../DelinquencyAndChargebackIntegrationTest.java   |  78 +++++++++--
 ...backOnPaymentTypeRepaymentTransactionsTest.java |  80 ++++++++++--
 .../LoanTransactionChargebackTest.java             | 142 +++++++++++++++------
 ...ionFullAmountChargebackForOverpaidLoanTest.java |  73 ++++++++++-
 5 files changed, 314 insertions(+), 60 deletions(-)

diff --git a/build.gradle b/build.gradle
index 6beb37499..147783d38 100644
--- a/build.gradle
+++ b/build.gradle
@@ -569,6 +569,7 @@ configure(project.fineractJavaProjects) {
                 'org.mockito:mockito-junit-jupiter',
                 'org.junit.jupiter:junit-jupiter-api',
                 'org.junit.jupiter:junit-jupiter-engine',
+                'org.junit.jupiter:junit-jupiter-params',
                 'org.junit.platform:junit-platform-runner', // required to be 
able to run tests directly under Eclipse, see FINERACT-943 & FINERACT-1021
                 'org.bouncycastle:bcpkix-jdk15to18',
                 'org.bouncycastle:bcprov-jdk15to18',
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
index 9160503ce..057996650 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
+import static 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -29,15 +31,20 @@ import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.time.LocalDate;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
 import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
 import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
+import org.apache.fineract.client.models.PaymentAllocationOrder;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.infrastructure.core.service.DateUtils;
@@ -52,9 +59,13 @@ import 
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtens
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
 import 
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Named;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 @Slf4j
 @ExtendWith(LoanTestLifecycleExtension.class)
@@ -77,8 +88,9 @@ public class DelinquencyAndChargebackIntegrationTest {
         loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, 
this.responseSpec);
     }
 
-    @Test
-    public void testLoanClassificationStepAsPartOfCOB() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void testLoanClassificationStepAsPartOfCOB(LoanProductTestBuilder 
loanProductTestBuilder) {
         try {
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
 
@@ -96,7 +108,7 @@ public class DelinquencyAndChargebackIntegrationTest {
             // Client and Loan account creation
             final Integer clientId = 
ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 
2012");
             final GetLoanProductsProductIdResponse 
getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
-                    delinquencyBucket.getId());
+                    delinquencyBucket.getId(), loanProductTestBuilder);
             assertNotNull(getLoanProductsProductResponse);
 
             // Older date to have more than one overdue installment
@@ -195,8 +207,9 @@ public class DelinquencyAndChargebackIntegrationTest {
         }
     }
 
-    @Test
-    public void testLoanClassificationStepAsPartOfCOBRepeated() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
testLoanClassificationStepAsPartOfCOBRepeated(LoanProductTestBuilder 
loanProductTestBuilder) {
         try {
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
 
@@ -215,7 +228,7 @@ public class DelinquencyAndChargebackIntegrationTest {
             // Client and Loan account creation
             final Integer clientId = 
ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 
2012");
             final GetLoanProductsProductIdResponse 
getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
-                    delinquencyBucket.getId());
+                    delinquencyBucket.getId(), loanProductTestBuilder);
             assertNotNull(getLoanProductsProductResponse);
 
             // Older date to have more than one overdue installment
@@ -325,8 +338,8 @@ public class DelinquencyAndChargebackIntegrationTest {
     }
 
     private GetLoanProductsProductIdResponse createLoanProduct(final 
LoanTransactionHelper loanTransactionHelper,
-            final Integer delinquencyBucketId) {
-        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucketId);
+            final Integer delinquencyBucketId, LoanProductTestBuilder 
loanProductTestBuilder) {
+        final HashMap<String, Object> loanProductMap = 
loanProductTestBuilder.build(null, delinquencyBucketId);
         final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
         return loanTransactionHelper.getLoanProduct(loanProductId);
     }
@@ -365,4 +378,51 @@ public class DelinquencyAndChargebackIntegrationTest {
         return delinquencyRange;
     }
 
+    private static AdvancedPaymentData createRepaymentPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("REPAYMENT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_INTEREST, 
PaymentAllocationType.PAST_DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_INTEREST,
+                PaymentAllocationType.DUE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static AdvancedPaymentData createDefaultPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("DEFAULT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_PRINCIPAL, 
PaymentAllocationType.PAST_DUE_INTEREST,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_INTEREST, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static List<PaymentAllocationOrder> 
getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+        AtomicInteger integer = new AtomicInteger(1);
+        return Arrays.stream(paymentAllocationTypes).map(pat -> {
+            PaymentAllocationOrder paymentAllocationOrder = new 
PaymentAllocationOrder();
+            paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+            paymentAllocationOrder.setOrder(integer.getAndIncrement());
+            return paymentAllocationOrder;
+        }).toList();
+    }
+
+    private static Stream<Arguments> loanProductFactory() {
+        return Stream.of(Arguments.of(Named.of("DEFAULT_STRATEGY", new 
LoanProductTestBuilder().withRepaymentStrategy(DEFAULT_STRATEGY))),
+                Arguments.of(Named.of("ADVANCED_PAYMENT_ALLOCATION_STRATEGY",
+                        new 
LoanProductTestBuilder().withRepaymentStrategy(ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
+                                
.addAdvancedPaymentAllocation(createDefaultPaymentAllocation(), 
createRepaymentPaymentAllocation()))));
+    }
+
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackOnPaymentTypeRepaymentTransactionsTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackOnPaymentTypeRepaymentTransactionsTest.java
index c6e2962b7..3fc6d2e34 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackOnPaymentTypeRepaymentTransactionsTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackOnPaymentTypeRepaymentTransactionsTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
+import static 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -27,12 +29,18 @@ import io.restassured.builder.ResponseSpecBuilder;
 import io.restassured.http.ContentType;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
+import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
 import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import 
org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
+import org.apache.fineract.client.models.PaymentAllocationOrder;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import 
org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
@@ -43,9 +51,13 @@ import 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
 import 
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
 import 
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Named;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 @ExtendWith(LoanTestLifecycleExtension.class)
 public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
@@ -69,8 +81,9 @@ public class 
LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
         this.clientHelper = new ClientHelper(this.requestSpec, 
this.responseSpec);
     }
 
-    @Test
-    public void 
loanTransactionChargebackForPaymentTypeRepaymentTransactionTest() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
loanTransactionChargebackForPaymentTypeRepaymentTransactionTest(LoanProductTestBuilder
 loanProductTestBuilder) {
         // Loan ExternalId
         String loanExternalIdStr = UUID.randomUUID().toString();
 
@@ -83,7 +96,7 @@ public class 
LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
 
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= createLoanProduct(loanTransactionHelper,
-                delinquencyBucketId);
+                delinquencyBucketId, loanProductTestBuilder);
         assertNotNull(getLoanProductsProductResponse);
 
         final Integer loanId = createLoanAccount(clientId, 
getLoanProductsProductResponse.getId(), loanExternalIdStr);
@@ -203,8 +216,9 @@ public class 
LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
 
     }
 
-    @Test
-    public void loanChargebackNotAllowedForReversedPaymentTypeRepaymentTest() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
loanChargebackNotAllowedForReversedPaymentTypeRepaymentTest(LoanProductTestBuilder
 loanProductTestBuilder) {
         // Loan ExternalId
         String loanExternalIdStr = UUID.randomUUID().toString();
 
@@ -217,7 +231,7 @@ public class 
LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
 
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= createLoanProduct(loanTransactionHelper,
-                delinquencyBucketId);
+                delinquencyBucketId, loanProductTestBuilder);
         assertNotNull(getLoanProductsProductResponse);
 
         final Integer loanId = createLoanAccount(clientId, 
getLoanProductsProductResponse.getId(), loanExternalIdStr);
@@ -237,8 +251,8 @@ public class 
LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
     }
 
     private GetLoanProductsProductIdResponse createLoanProduct(final 
LoanTransactionHelper loanTransactionHelper,
-            final Integer delinquencyBucketId) {
-        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucketId);
+            final Integer delinquencyBucketId, LoanProductTestBuilder 
loanProductTestBuilder) {
+        final HashMap<String, Object> loanProductMap = 
loanProductTestBuilder.build(null, delinquencyBucketId);
         final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
         return loanTransactionHelper.getLoanProduct(loanProductId);
     }
@@ -269,4 +283,52 @@ public class 
LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
         // Outstanding amount
         assertEquals(outstandingBalance, 
getLoansTransactionResponse.getOutstandingLoanBalance());
     }
+
+    private static AdvancedPaymentData createRepaymentPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("REPAYMENT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_INTEREST, 
PaymentAllocationType.PAST_DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_INTEREST,
+                PaymentAllocationType.DUE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static AdvancedPaymentData createDefaultPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("DEFAULT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_PRINCIPAL, 
PaymentAllocationType.PAST_DUE_INTEREST,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_INTEREST, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static List<PaymentAllocationOrder> 
getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+        AtomicInteger integer = new AtomicInteger(1);
+        return Arrays.stream(paymentAllocationTypes).map(pat -> {
+            PaymentAllocationOrder paymentAllocationOrder = new 
PaymentAllocationOrder();
+            paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+            paymentAllocationOrder.setOrder(integer.getAndIncrement());
+            return paymentAllocationOrder;
+        }).toList();
+    }
+
+    private static Stream<Arguments> loanProductFactory() {
+        return Stream.of(Arguments.of(Named.of("DEFAULT_STRATEGY", new 
LoanProductTestBuilder().withRepaymentStrategy(DEFAULT_STRATEGY))),
+                Arguments.of(Named.of("ADVANCED_PAYMENT_ALLOCATION_STRATEGY",
+                        new 
LoanProductTestBuilder().withRepaymentStrategy(ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
+                                
.addAdvancedPaymentAllocation(createDefaultPaymentAllocation(), 
createRepaymentPaymentAllocation()))));
+    }
+
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
index 9d1f0fc39..5377690b3 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
+import static 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
@@ -28,9 +30,13 @@ import io.restassured.http.ContentType;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.time.LocalDate;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
 import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
 import 
org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
@@ -40,6 +46,7 @@ import 
org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
 import 
org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
+import org.apache.fineract.client.models.PaymentAllocationOrder;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
@@ -54,9 +61,13 @@ import 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
 import 
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
 import 
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Named;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 @Slf4j
 @ExtendWith(LoanTestLifecycleExtension.class)
@@ -91,10 +102,11 @@ public class LoanTransactionChargebackTest {
         this.operationDate = Utils.dateFormatter.format(this.todaysDate);
     }
 
-    @Test
-    public void applyLoanTransactionChargeback() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void applyLoanTransactionChargeback(LoanProductTestBuilder 
loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, true);
+        final Integer loanId = createAccounts(15, 1, true, 
loanProductTestBuilder);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -106,6 +118,7 @@ public class LoanTransactionChargebackTest {
                 loanId);
         assertNotNull(loanIdTransactionsResponse);
         final Long transactionId = loanIdTransactionsResponse.getResourceId();
+        assertNotNull(transactionId);
 
         getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -142,10 +155,11 @@ public class LoanTransactionChargebackTest {
         reverseTransactionResponse = 
loanTransactionHelper.reverseLoanTransaction(loanId, transactionId, 
operationDate, responseSpecErr503);
     }
 
-    @Test
-    public void applyAndAdjustLoanTransactionChargeback() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void applyAndAdjustLoanTransactionChargeback(LoanProductTestBuilder 
loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, false);
+        final Integer loanId = createAccounts(15, 1, false, 
loanProductTestBuilder);
 
         Float amount = Float.valueOf(amountVal);
         PostLoansLoanIdTransactionsResponse loanTransactionResponse = 
loanTransactionHelper.makeLoanRepayment(operationDate, amount,
@@ -160,10 +174,11 @@ public class LoanTransactionChargebackTest {
         loanTransactionHelper.adjustLoanTransaction(loanId, 
chargebackTransactionId, operationDate, responseSpecErr403);
     }
 
-    @Test
-    public void applyLoanTransactionChargebackWithAmountZero() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackWithAmountZero(LoanProductTestBuilder 
loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, false);
+        final Integer loanId = createAccounts(15, 1, false, 
loanProductTestBuilder);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -183,8 +198,9 @@ public class LoanTransactionChargebackTest {
         loanTransactionHelper.applyChargebackTransaction(loanId, 
transactionId, "0.00", 0, responseSpecErr400);
     }
 
-    @Test
-    public void applyLoanTransactionChargebackInLongTermLoan() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackInLongTermLoan(LoanProductTestBuilder 
loanProductTestBuilder) {
         try {
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
             LocalDate businessDate = LocalDate.of(2023, 1, 20);
@@ -193,7 +209,7 @@ public class LoanTransactionChargebackTest {
             // Client and Loan account creation
             final Integer daysToSubtract = 1;
             final Integer numberOfRepayments = 3;
-            final Integer loanId = createAccounts(daysToSubtract, 
numberOfRepayments, false);
+            final Integer loanId = createAccounts(daysToSubtract, 
numberOfRepayments, false, loanProductTestBuilder);
 
             GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
             assertNotNull(getLoansLoanIdResponse);
@@ -243,10 +259,11 @@ public class LoanTransactionChargebackTest {
         }
     }
 
-    @Test
-    public void applyLoanTransactionChargebackOverNoRepaymentType() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackOverNoRepaymentType(LoanProductTestBuilder 
loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, false);
+        final Integer loanId = createAccounts(15, 1, false, 
loanProductTestBuilder);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -262,8 +279,9 @@ public class LoanTransactionChargebackTest {
         loanTransactionHelper.applyChargebackTransaction(loanId, 
loanTransaction.getId(), amountVal, 0, responseSpecErr503);
     }
 
-    @Test
-    public void applyLoanTransactionChargebackAfterMature() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackAfterMature(LoanProductTestBuilder 
loanProductTestBuilder) {
         try {
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
 
@@ -272,7 +290,7 @@ public class LoanTransactionChargebackTest {
             log.info("Current Business date {}", todaysDate);
 
             // Client and Loan account creation
-            final Integer loanId = createAccounts(45, 1, false);
+            final Integer loanId = createAccounts(45, 1, false, 
loanProductTestBuilder);
 
             GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
             assertNotNull(getLoansLoanIdResponse);
@@ -373,10 +391,11 @@ public class LoanTransactionChargebackTest {
         }
     }
 
-    @Test
-    public void applyLoanTransactionChargebackWithLoanOverpaidToLoanActive() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackWithLoanOverpaidToLoanActive(LoanProductTestBuilder
 loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, true);
+        final Integer loanId = createAccounts(15, 1, true, 
loanProductTestBuilder);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -428,10 +447,11 @@ public class LoanTransactionChargebackTest {
         log.info("Loan Delinquency Range is null {}", (delinquencyRange == 
null));
     }
 
-    @Test
-    public void applyLoanTransactionChargebackWithLoanOverpaidToLoanClose() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackWithLoanOverpaidToLoanClose(LoanProductTestBuilder
 loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, false);
+        final Integer loanId = createAccounts(15, 1, false, 
loanProductTestBuilder);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -463,10 +483,11 @@ public class LoanTransactionChargebackTest {
         
loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse,
 Double.valueOf("0.00"));
     }
 
-    @Test
-    public void 
applyLoanTransactionChargebackWithLoanOverpaidToKeepAsLoanOverpaid() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
applyLoanTransactionChargebackWithLoanOverpaidToKeepAsLoanOverpaid(LoanProductTestBuilder
 loanProductTestBuilder) {
         // Client and Loan account creation
-        final Integer loanId = createAccounts(15, 1, true);
+        final Integer loanId = createAccounts(15, 1, true, 
loanProductTestBuilder);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -513,8 +534,9 @@ public class LoanTransactionChargebackTest {
         assertEquals("DEBIT", 
journalEntries.getPageItems().get(1).getEntryType().getValue());
     }
 
-    @Test
-    public void applyMultipleLoanTransactionChargeback() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void applyMultipleLoanTransactionChargeback(LoanProductTestBuilder 
loanProductTestBuilder) {
         try {
             GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
             final LocalDate todaysDate = Utils.getLocalDateOfTenant();
@@ -522,7 +544,7 @@ public class LoanTransactionChargebackTest {
             log.info("Current Business date {}", todaysDate);
 
             // Client and Loan account creation
-            final Integer loanId = createAccounts(15, 1, false);
+            final Integer loanId = createAccounts(15, 1, false, 
loanProductTestBuilder);
 
             GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
             assertNotNull(getLoansLoanIdResponse);
@@ -582,7 +604,8 @@ public class LoanTransactionChargebackTest {
         }
     }
 
-    private Integer createAccounts(final Integer daysToSubtract, final Integer 
numberOfRepayments, final boolean withJournalEntries) {
+    private Integer createAccounts(final Integer daysToSubtract, final Integer 
numberOfRepayments, final boolean withJournalEntries,
+            LoanProductTestBuilder loanProductTestBuilder) {
         // Delinquency Bucket
         final Integer delinquencyBucketId = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
         final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
@@ -591,7 +614,7 @@ public class LoanTransactionChargebackTest {
         // Client and Loan account creation
         final Integer clientId = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2012");
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= createLoanProduct(loanTransactionHelper,
-                delinquencyBucketId, withJournalEntries);
+                delinquencyBucketId, withJournalEntries, 
loanProductTestBuilder);
         assertNotNull(getLoanProductsProductResponse);
         log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
         
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
@@ -605,18 +628,18 @@ public class LoanTransactionChargebackTest {
     }
 
     private GetLoanProductsProductIdResponse createLoanProduct(final 
LoanTransactionHelper loanTransactionHelper,
-            final Integer delinquencyBucketId, final boolean 
withJournalEntries) {
+            final Integer delinquencyBucketId, final boolean 
withJournalEntries, LoanProductTestBuilder loanProductTestBuilder) {
         final HashMap<String, Object> loanProductMap;
         if (withJournalEntries) {
             final Account assetAccount = accountHelper.createAssetAccount();
             final Account expenseAccount = 
accountHelper.createExpenseAccount();
             final Account incomeAccount = accountHelper.createIncomeAccount();
             final Account overpaymentAccount = 
accountHelper.createLiabilityAccount();
-            loanProductMap = new LoanProductTestBuilder()
+            loanProductMap = loanProductTestBuilder
                     .withAccountingRulePeriodicAccrual(new Account[] { 
assetAccount, expenseAccount, incomeAccount, overpaymentAccount })
                     .build(null, delinquencyBucketId);
         } else {
-            loanProductMap = new LoanProductTestBuilder().build(null, 
delinquencyBucketId);
+            loanProductMap = loanProductTestBuilder.build(null, 
delinquencyBucketId);
         }
         final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
         return loanTransactionHelper.getLoanProduct(loanProductId);
@@ -653,4 +676,51 @@ public class LoanTransactionChargebackTest {
         assertEquals(outstandingBalance, 
getLoansTransactionResponse.getOutstandingLoanBalance());
     }
 
+    private static AdvancedPaymentData createRepaymentPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("REPAYMENT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_INTEREST, 
PaymentAllocationType.PAST_DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_INTEREST,
+                PaymentAllocationType.DUE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static AdvancedPaymentData createDefaultPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("DEFAULT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_PRINCIPAL, 
PaymentAllocationType.PAST_DUE_INTEREST,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_INTEREST, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static List<PaymentAllocationOrder> 
getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+        AtomicInteger integer = new AtomicInteger(1);
+        return Arrays.stream(paymentAllocationTypes).map(pat -> {
+            PaymentAllocationOrder paymentAllocationOrder = new 
PaymentAllocationOrder();
+            paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+            paymentAllocationOrder.setOrder(integer.getAndIncrement());
+            return paymentAllocationOrder;
+        }).toList();
+    }
+
+    private static Stream<Arguments> loanProductFactory() {
+        return Stream.of(Arguments.of(Named.of("DEFAULT_STRATEGY", new 
LoanProductTestBuilder().withRepaymentStrategy(DEFAULT_STRATEGY))),
+                Arguments.of(Named.of("ADVANCED_PAYMENT_ALLOCATION_STRATEGY",
+                        new 
LoanProductTestBuilder().withRepaymentStrategy(ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
+                                
.addAdvancedPaymentAllocation(createDefaultPaymentAllocation(), 
createRepaymentPaymentAllocation()))));
+    }
+
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionFullAmountChargebackForOverpaidLoanTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionFullAmountChargebackForOverpaidLoanTest.java
index dcff15282..13762113c 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionFullAmountChargebackForOverpaidLoanTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionFullAmountChargebackForOverpaidLoanTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
+import static 
org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -27,12 +29,18 @@ import io.restassured.builder.ResponseSpecBuilder;
 import io.restassured.http.ContentType;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Stream;
+import org.apache.fineract.client.models.AdvancedPaymentData;
 import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
 import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import 
org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
+import org.apache.fineract.client.models.PaymentAllocationOrder;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import 
org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
@@ -43,9 +51,13 @@ import 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
 import 
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
 import 
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Named;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 @ExtendWith(LoanTestLifecycleExtension.class)
 public class LoanTransactionFullAmountChargebackForOverpaidLoanTest {
@@ -69,8 +81,9 @@ public class 
LoanTransactionFullAmountChargebackForOverpaidLoanTest {
         this.clientHelper = new ClientHelper(this.requestSpec, 
this.responseSpec);
     }
 
-    @Test
-    public void loanTransactionChargebackOfFullAmountForOverpaidLoanTest() {
+    @ParameterizedTest
+    @MethodSource("loanProductFactory")
+    public void 
loanTransactionChargebackOfFullAmountForOverpaidLoanTest(LoanProductTestBuilder 
loanProductTestBuilder) {
         // Loan ExternalId
         String loanExternalIdStr = UUID.randomUUID().toString();
 
@@ -83,7 +96,7 @@ public class 
LoanTransactionFullAmountChargebackForOverpaidLoanTest {
 
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= createLoanProduct(loanTransactionHelper,
-                delinquencyBucketId);
+                delinquencyBucketId, loanProductTestBuilder);
         assertNotNull(getLoanProductsProductResponse);
 
         final Integer loanId = createLoanAccount(clientId, 
getLoanProductsProductResponse.getId(), loanExternalIdStr);
@@ -148,8 +161,8 @@ public class 
LoanTransactionFullAmountChargebackForOverpaidLoanTest {
     }
 
     private GetLoanProductsProductIdResponse createLoanProduct(final 
LoanTransactionHelper loanTransactionHelper,
-            final Integer delinquencyBucketId) {
-        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().build(null, delinquencyBucketId);
+            final Integer delinquencyBucketId, LoanProductTestBuilder 
loanProductTestBuilder) {
+        final HashMap<String, Object> loanProductMap = 
loanProductTestBuilder.build(null, delinquencyBucketId);
         final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
         return loanTransactionHelper.getLoanProduct(loanProductId);
     }
@@ -168,4 +181,52 @@ public class 
LoanTransactionFullAmountChargebackForOverpaidLoanTest {
         loanTransactionHelper.disburseLoanWithNetDisbursalAmount("03 September 
2022", loanId, "1000");
         return loanId;
     }
+
+    private static AdvancedPaymentData createRepaymentPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("REPAYMENT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_INTEREST, 
PaymentAllocationType.PAST_DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_INTEREST,
+                PaymentAllocationType.DUE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static AdvancedPaymentData createDefaultPaymentAllocation() {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("DEFAULT");
+        
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
+
+        List<PaymentAllocationOrder> paymentAllocationOrders = 
getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+                PaymentAllocationType.PAST_DUE_FEE, 
PaymentAllocationType.PAST_DUE_PRINCIPAL, 
PaymentAllocationType.PAST_DUE_INTEREST,
+                PaymentAllocationType.DUE_PENALTY, 
PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
+                PaymentAllocationType.DUE_INTEREST, 
PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+                PaymentAllocationType.IN_ADVANCE_PRINCIPAL, 
PaymentAllocationType.IN_ADVANCE_INTEREST);
+
+        advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+        return advancedPaymentData;
+    }
+
+    private static List<PaymentAllocationOrder> 
getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+        AtomicInteger integer = new AtomicInteger(1);
+        return Arrays.stream(paymentAllocationTypes).map(pat -> {
+            PaymentAllocationOrder paymentAllocationOrder = new 
PaymentAllocationOrder();
+            paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+            paymentAllocationOrder.setOrder(integer.getAndIncrement());
+            return paymentAllocationOrder;
+        }).toList();
+    }
+
+    private static Stream<Arguments> loanProductFactory() {
+        return Stream.of(Arguments.of(Named.of("DEFAULT_STRATEGY", new 
LoanProductTestBuilder().withRepaymentStrategy(DEFAULT_STRATEGY))),
+                Arguments.of(Named.of("ADVANCED_PAYMENT_ALLOCATION_STRATEGY",
+                        new 
LoanProductTestBuilder().withRepaymentStrategy(ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
+                                
.addAdvancedPaymentAllocation(createDefaultPaymentAllocation(), 
createRepaymentPaymentAllocation()))));
+    }
+
 }


Reply via email to