FINERACT-1968

- integration tests added for validating chargeback support.
This commit is contained in:
Peter Bagrij
2023-09-26 11:05:54 +02:00
committed by Adam Saghy
parent fecc3913a8
commit f452ce2cad
5 changed files with 314 additions and 60 deletions
+1
View File
@@ -569,6 +569,7 @@ configure(project.fineractJavaProjects) {
'org.mockito:mockito-junit-jupiter', 'org.mockito:mockito-junit-jupiter',
'org.junit.jupiter:junit-jupiter-api', 'org.junit.jupiter:junit-jupiter-api',
'org.junit.jupiter:junit-jupiter-engine', '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.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:bcpkix-jdk15to18',
'org.bouncycastle:bcprov-jdk15to18', 'org.bouncycastle:bcprov-jdk15to18',
@@ -18,6 +18,8 @@
*/ */
package org.apache.fineract.integrationtests; 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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -29,15 +31,20 @@ import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j; 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.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetDelinquencyRangesResponse; import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod; import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule; import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
import org.apache.fineract.client.models.GetLoansLoanIdResponse; 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.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.service.DateUtils; 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.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; 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.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.extension.ExtendWith; 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 @Slf4j
@ExtendWith(LoanTestLifecycleExtension.class) @ExtendWith(LoanTestLifecycleExtension.class)
@@ -77,8 +88,9 @@ public class DelinquencyAndChargebackIntegrationTest {
loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
} }
@Test @ParameterizedTest
public void testLoanClassificationStepAsPartOfCOB() { @MethodSource("loanProductFactory")
public void testLoanClassificationStepAsPartOfCOB(LoanProductTestBuilder loanProductTestBuilder) {
try { try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
@@ -96,7 +108,7 @@ public class DelinquencyAndChargebackIntegrationTest {
// Client and Loan account creation // Client and Loan account creation
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012"); final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
delinquencyBucket.getId()); delinquencyBucket.getId(), loanProductTestBuilder);
assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse);
// Older date to have more than one overdue installment // Older date to have more than one overdue installment
@@ -195,8 +207,9 @@ public class DelinquencyAndChargebackIntegrationTest {
} }
} }
@Test @ParameterizedTest
public void testLoanClassificationStepAsPartOfCOBRepeated() { @MethodSource("loanProductFactory")
public void testLoanClassificationStepAsPartOfCOBRepeated(LoanProductTestBuilder loanProductTestBuilder) {
try { try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
@@ -215,7 +228,7 @@ public class DelinquencyAndChargebackIntegrationTest {
// Client and Loan account creation // Client and Loan account creation
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012"); final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
delinquencyBucket.getId()); delinquencyBucket.getId(), loanProductTestBuilder);
assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse);
// Older date to have more than one overdue installment // Older date to have more than one overdue installment
@@ -325,8 +338,8 @@ public class DelinquencyAndChargebackIntegrationTest {
} }
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper, private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
final Integer delinquencyBucketId) { final Integer delinquencyBucketId, LoanProductTestBuilder loanProductTestBuilder) {
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId); final HashMap<String, Object> loanProductMap = loanProductTestBuilder.build(null, delinquencyBucketId);
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
return loanTransactionHelper.getLoanProduct(loanProductId); return loanTransactionHelper.getLoanProduct(loanProductId);
} }
@@ -365,4 +378,51 @@ public class DelinquencyAndChargebackIntegrationTest {
return delinquencyRange; 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()))));
}
} }
@@ -18,6 +18,8 @@
*/ */
package org.apache.fineract.integrationtests; 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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; 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.http.ContentType;
import io.restassured.specification.RequestSpecification; import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.UUID; 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.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse; 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.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest; 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.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; 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.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.extension.ExtendWith; 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) @ExtendWith(LoanTestLifecycleExtension.class)
public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest { public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
@@ -69,8 +81,9 @@ public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
} }
@Test @ParameterizedTest
public void loanTransactionChargebackForPaymentTypeRepaymentTransactionTest() { @MethodSource("loanProductFactory")
public void loanTransactionChargebackForPaymentTypeRepaymentTransactionTest(LoanProductTestBuilder loanProductTestBuilder) {
// Loan ExternalId // Loan ExternalId
String loanExternalIdStr = UUID.randomUUID().toString(); String loanExternalIdStr = UUID.randomUUID().toString();
@@ -83,7 +96,7 @@ public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
delinquencyBucketId); delinquencyBucketId, loanProductTestBuilder);
assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse);
final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr); final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr);
@@ -203,8 +216,9 @@ public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
} }
@Test @ParameterizedTest
public void loanChargebackNotAllowedForReversedPaymentTypeRepaymentTest() { @MethodSource("loanProductFactory")
public void loanChargebackNotAllowedForReversedPaymentTypeRepaymentTest(LoanProductTestBuilder loanProductTestBuilder) {
// Loan ExternalId // Loan ExternalId
String loanExternalIdStr = UUID.randomUUID().toString(); String loanExternalIdStr = UUID.randomUUID().toString();
@@ -217,7 +231,7 @@ public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
delinquencyBucketId); delinquencyBucketId, loanProductTestBuilder);
assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse);
final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr); final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr);
@@ -237,8 +251,8 @@ public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
} }
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper, private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
final Integer delinquencyBucketId) { final Integer delinquencyBucketId, LoanProductTestBuilder loanProductTestBuilder) {
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId); final HashMap<String, Object> loanProductMap = loanProductTestBuilder.build(null, delinquencyBucketId);
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
return loanTransactionHelper.getLoanProduct(loanProductId); return loanTransactionHelper.getLoanProduct(loanProductId);
} }
@@ -269,4 +283,52 @@ public class LoanChargebackOnPaymentTypeRepaymentTransactionsTest {
// Outstanding amount // Outstanding amount
assertEquals(outstandingBalance, getLoansTransactionResponse.getOutstandingLoanBalance()); 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()))));
}
} }
@@ -18,6 +18,8 @@
*/ */
package org.apache.fineract.integrationtests; 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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull; 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.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j; 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.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetDelinquencyRangesResponse; import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse; 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.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactions; import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse; 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.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.integrationtests.common.BusinessDateHelper; 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.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; 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.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.extension.ExtendWith; 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 @Slf4j
@ExtendWith(LoanTestLifecycleExtension.class) @ExtendWith(LoanTestLifecycleExtension.class)
@@ -91,10 +102,11 @@ public class LoanTransactionChargebackTest {
this.operationDate = Utils.dateFormatter.format(this.todaysDate); this.operationDate = Utils.dateFormatter.format(this.todaysDate);
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargeback() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargeback(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -106,6 +118,7 @@ public class LoanTransactionChargebackTest {
loanId); loanId);
assertNotNull(loanIdTransactionsResponse); assertNotNull(loanIdTransactionsResponse);
final Long transactionId = loanIdTransactionsResponse.getResourceId(); final Long transactionId = loanIdTransactionsResponse.getResourceId();
assertNotNull(transactionId);
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId); getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -142,10 +155,11 @@ public class LoanTransactionChargebackTest {
reverseTransactionResponse = loanTransactionHelper.reverseLoanTransaction(loanId, transactionId, operationDate, responseSpecErr503); reverseTransactionResponse = loanTransactionHelper.reverseLoanTransaction(loanId, transactionId, operationDate, responseSpecErr503);
} }
@Test @ParameterizedTest
public void applyAndAdjustLoanTransactionChargeback() { @MethodSource("loanProductFactory")
public void applyAndAdjustLoanTransactionChargeback(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); Float amount = Float.valueOf(amountVal);
PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(operationDate, amount, PostLoansLoanIdTransactionsResponse loanTransactionResponse = loanTransactionHelper.makeLoanRepayment(operationDate, amount,
@@ -160,10 +174,11 @@ public class LoanTransactionChargebackTest {
loanTransactionHelper.adjustLoanTransaction(loanId, chargebackTransactionId, operationDate, responseSpecErr403); loanTransactionHelper.adjustLoanTransaction(loanId, chargebackTransactionId, operationDate, responseSpecErr403);
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackWithAmountZero() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackWithAmountZero(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -183,8 +198,9 @@ public class LoanTransactionChargebackTest {
loanTransactionHelper.applyChargebackTransaction(loanId, transactionId, "0.00", 0, responseSpecErr400); loanTransactionHelper.applyChargebackTransaction(loanId, transactionId, "0.00", 0, responseSpecErr400);
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackInLongTermLoan() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackInLongTermLoan(LoanProductTestBuilder loanProductTestBuilder) {
try { try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
LocalDate businessDate = LocalDate.of(2023, 1, 20); LocalDate businessDate = LocalDate.of(2023, 1, 20);
@@ -193,7 +209,7 @@ public class LoanTransactionChargebackTest {
// Client and Loan account creation // Client and Loan account creation
final Integer daysToSubtract = 1; final Integer daysToSubtract = 1;
final Integer numberOfRepayments = 3; 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -243,10 +259,11 @@ public class LoanTransactionChargebackTest {
} }
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackOverNoRepaymentType() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackOverNoRepaymentType(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -262,8 +279,9 @@ public class LoanTransactionChargebackTest {
loanTransactionHelper.applyChargebackTransaction(loanId, loanTransaction.getId(), amountVal, 0, responseSpecErr503); loanTransactionHelper.applyChargebackTransaction(loanId, loanTransaction.getId(), amountVal, 0, responseSpecErr503);
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackAfterMature() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackAfterMature(LoanProductTestBuilder loanProductTestBuilder) {
try { try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
@@ -272,7 +290,7 @@ public class LoanTransactionChargebackTest {
log.info("Current Business date {}", todaysDate); log.info("Current Business date {}", todaysDate);
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -373,10 +391,11 @@ public class LoanTransactionChargebackTest {
} }
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackWithLoanOverpaidToLoanActive() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackWithLoanOverpaidToLoanActive(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -428,10 +447,11 @@ public class LoanTransactionChargebackTest {
log.info("Loan Delinquency Range is null {}", (delinquencyRange == null)); log.info("Loan Delinquency Range is null {}", (delinquencyRange == null));
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackWithLoanOverpaidToLoanClose() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackWithLoanOverpaidToLoanClose(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -463,10 +483,11 @@ public class LoanTransactionChargebackTest {
loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, Double.valueOf("0.00")); loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, Double.valueOf("0.00"));
} }
@Test @ParameterizedTest
public void applyLoanTransactionChargebackWithLoanOverpaidToKeepAsLoanOverpaid() { @MethodSource("loanProductFactory")
public void applyLoanTransactionChargebackWithLoanOverpaidToKeepAsLoanOverpaid(LoanProductTestBuilder loanProductTestBuilder) {
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); assertNotNull(getLoansLoanIdResponse);
@@ -513,8 +534,9 @@ public class LoanTransactionChargebackTest {
assertEquals("DEBIT", journalEntries.getPageItems().get(1).getEntryType().getValue()); assertEquals("DEBIT", journalEntries.getPageItems().get(1).getEntryType().getValue());
} }
@Test @ParameterizedTest
public void applyMultipleLoanTransactionChargeback() { @MethodSource("loanProductFactory")
public void applyMultipleLoanTransactionChargeback(LoanProductTestBuilder loanProductTestBuilder) {
try { try {
GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE); GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
final LocalDate todaysDate = Utils.getLocalDateOfTenant(); final LocalDate todaysDate = Utils.getLocalDateOfTenant();
@@ -522,7 +544,7 @@ public class LoanTransactionChargebackTest {
log.info("Current Business date {}", todaysDate); log.info("Current Business date {}", todaysDate);
// Client and Loan account creation // 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); GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse); 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 // Delinquency Bucket
final Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec); final Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec, final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
@@ -591,7 +614,7 @@ public class LoanTransactionChargebackTest {
// Client and Loan account creation // Client and Loan account creation
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012"); final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
delinquencyBucketId, withJournalEntries); delinquencyBucketId, withJournalEntries, loanProductTestBuilder);
assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse);
log.info("Loan Product Bucket Name: {}", getLoanProductsProductResponse.getDelinquencyBucket().getName()); log.info("Loan Product Bucket Name: {}", getLoanProductsProductResponse.getDelinquencyBucket().getName());
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), delinquencyBucket.getName()); assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), delinquencyBucket.getName());
@@ -605,18 +628,18 @@ public class LoanTransactionChargebackTest {
} }
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper, 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; final HashMap<String, Object> loanProductMap;
if (withJournalEntries) { if (withJournalEntries) {
final Account assetAccount = accountHelper.createAssetAccount(); final Account assetAccount = accountHelper.createAssetAccount();
final Account expenseAccount = accountHelper.createExpenseAccount(); final Account expenseAccount = accountHelper.createExpenseAccount();
final Account incomeAccount = accountHelper.createIncomeAccount(); final Account incomeAccount = accountHelper.createIncomeAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount(); final Account overpaymentAccount = accountHelper.createLiabilityAccount();
loanProductMap = new LoanProductTestBuilder() loanProductMap = loanProductTestBuilder
.withAccountingRulePeriodicAccrual(new Account[] { assetAccount, expenseAccount, incomeAccount, overpaymentAccount }) .withAccountingRulePeriodicAccrual(new Account[] { assetAccount, expenseAccount, incomeAccount, overpaymentAccount })
.build(null, delinquencyBucketId); .build(null, delinquencyBucketId);
} else { } else {
loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId); loanProductMap = loanProductTestBuilder.build(null, delinquencyBucketId);
} }
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
return loanTransactionHelper.getLoanProduct(loanProductId); return loanTransactionHelper.getLoanProduct(loanProductId);
@@ -653,4 +676,51 @@ public class LoanTransactionChargebackTest {
assertEquals(outstandingBalance, getLoansTransactionResponse.getOutstandingLoanBalance()); 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()))));
}
} }
@@ -18,6 +18,8 @@
*/ */
package org.apache.fineract.integrationtests; 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.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; 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.http.ContentType;
import io.restassured.specification.RequestSpecification; import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.UUID; 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.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse; 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.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest; 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.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; 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.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Named;
import org.junit.jupiter.api.extension.ExtendWith; 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) @ExtendWith(LoanTestLifecycleExtension.class)
public class LoanTransactionFullAmountChargebackForOverpaidLoanTest { public class LoanTransactionFullAmountChargebackForOverpaidLoanTest {
@@ -69,8 +81,9 @@ public class LoanTransactionFullAmountChargebackForOverpaidLoanTest {
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
} }
@Test @ParameterizedTest
public void loanTransactionChargebackOfFullAmountForOverpaidLoanTest() { @MethodSource("loanProductFactory")
public void loanTransactionChargebackOfFullAmountForOverpaidLoanTest(LoanProductTestBuilder loanProductTestBuilder) {
// Loan ExternalId // Loan ExternalId
String loanExternalIdStr = UUID.randomUUID().toString(); String loanExternalIdStr = UUID.randomUUID().toString();
@@ -83,7 +96,7 @@ public class LoanTransactionFullAmountChargebackForOverpaidLoanTest {
final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
delinquencyBucketId); delinquencyBucketId, loanProductTestBuilder);
assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse);
final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr); final Integer loanId = createLoanAccount(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr);
@@ -148,8 +161,8 @@ public class LoanTransactionFullAmountChargebackForOverpaidLoanTest {
} }
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper, private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
final Integer delinquencyBucketId) { final Integer delinquencyBucketId, LoanProductTestBuilder loanProductTestBuilder) {
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId); final HashMap<String, Object> loanProductMap = loanProductTestBuilder.build(null, delinquencyBucketId);
final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
return loanTransactionHelper.getLoanProduct(loanProductId); return loanTransactionHelper.getLoanProduct(loanProductId);
} }
@@ -168,4 +181,52 @@ public class LoanTransactionFullAmountChargebackForOverpaidLoanTest {
loanTransactionHelper.disburseLoanWithNetDisbursalAmount("03 September 2022", loanId, "1000"); loanTransactionHelper.disburseLoanWithNetDisbursalAmount("03 September 2022", loanId, "1000");
return loanId; 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()))));
}
} }