blob: 7e71d422310c0b2958e5ead15294d2e0e1606354 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.integrationtests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
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.Collectors;
import org.apache.fineract.client.models.AdvancedPaymentData;
import org.apache.fineract.client.models.BusinessDateRequest;
import org.apache.fineract.client.models.GetLoansLoanIdLoanChargeData;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.PaymentAllocationOrder;
import org.apache.fineract.client.models.PostClientsResponse;
import org.apache.fineract.client.models.PostCreateRescheduleLoansRequest;
import org.apache.fineract.client.models.PostCreateRescheduleLoansResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
import org.apache.fineract.client.models.PostLoanProductsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
import org.apache.fineract.client.models.PostLoansRequest;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
import org.apache.fineract.client.util.CallFailedRuntimeException;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.CommonConstants;
import org.apache.fineract.integrationtests.common.LoanRescheduleRequestHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
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.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.FineractStyleLoanRepaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ExtendWith(LoanTestLifecycleExtension.class)
public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoanIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(AdvancedPaymentAllocationLoanRepaymentScheduleTest.class);
private static final String DATETIME_PATTERN = "dd MMMM yyyy";
private static ResponseSpecification responseSpec;
private static RequestSpecification requestSpec;
private static BusinessDateHelper businessDateHelper;
private static LoanTransactionHelper loanTransactionHelper;
private static AccountHelper accountHelper;
private static Integer commonLoanProductId;
private static PostClientsResponse client;
private static LoanRescheduleRequestHelper loanRescheduleRequestHelper;
@BeforeAll
public static void setup() {
Utils.initializeRESTAssured();
requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
requestSpec.header("Fineract-Platform-TenantId", "default");
responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
businessDateHelper = new BusinessDateHelper();
accountHelper = new AccountHelper(requestSpec, responseSpec);
ClientHelper clientHelper = new ClientHelper(requestSpec, responseSpec);
loanRescheduleRequestHelper = new LoanRescheduleRequestHelper(requestSpec, responseSpec);
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
commonLoanProductId = createLoanProduct("500", "15", "4", true, "25", true, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
}
// UC1: Simple payments
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay installments on due dates
@Test
public void uc1() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 250.0, 250.0, 250.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 2, 125.0, 125.0, 0.0, 250.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 125.0, 375.0, 125.0, 375.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 125.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC2: Overpayment1
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Overpay 2nd installment
// 4. Overpay loan
@Test
public void uc2() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(150.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 225.0, 275.0, 225.0, 275.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 25.0, 100.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 2, 150.0, 150.0, 0.0, 225.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 400.0, 100.0, 400.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 25.0, 100.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 100.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 25.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 100.0, 25.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
});
}
// UC3: Overpayment2
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Overpay 2nd installment
@Test
public void uc3() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(150.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 225.0, 275.0, 225.0, 275.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 25.0, 100.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 2, 150.0, 150.0, 0.0, 225.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 400.0, 100.0, 400.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 25.0, 100.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 100.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 25.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 100.0, 25.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
});
}
// UC4: Delinquent balance
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment - fails
// 3. Pay 1st installment - fails
// 4. Pay rest manually
@Test
public void uc4() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(2).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("20 January 2023").locale("en").transactionAmount(100.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 400.0, 100.0, 400.0, 100.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 100.0, 25.0, 0.0, 100.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 3, 100.0, 100.0, 0.0, 400.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(40.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 360.0, 140.0, 360.0, 140.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 15.0, 110.0, 0.0, 15.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 4, 40.0, 40.0, 0.0, 360.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(360.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 5, 360.0, 360.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC5: Refund past due
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment - fails
// 3. Partial Merchant refund
// 4. Pay rest on time
@Test
public void uc5() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("8 January 2023").locale("en").transactionAmount(300.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 200.0, 300.0, 200.0, 300.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 58.33, 66.67, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 58.33, 66.67, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 58.34, 66.66, 58.34, 0.0);
validateLoanTransaction(loanDetails, 2, 300.0, 300.0, 0.0, 200.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(66.67));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 133.33, 366.67, 133.33, 366.67, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 58.33, 66.67, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 58.34, 66.66, 58.34, 0.0);
validateLoanTransaction(loanDetails, 3, 66.67, 66.67, 0.0, 133.33);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(66.67));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 66.66, 433.34, 66.66, 433.34, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 58.34, 66.66, 58.34, 0.0);
validateLoanTransaction(loanDetails, 4, 66.67, 66.67, 0.0, 66.66);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(66.66));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 58.33, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 58.34, 0.0);
validateLoanTransaction(loanDetails, 5, 66.66, 66.66, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC7: Refund & due reamortization
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay 1st installment on time
// 4. Merchant issued refund
// 4. Pay rest on time
@Test
public void uc7() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 250.0, 250.0, 250.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 2, 125.0, 125.0, 0.0, 250.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 450.0, 50.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 100.0, 25.0, 100.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 100.0, 25.0, 100.0, 0.0);
validateLoanTransaction(loanDetails, 3, 200, 200.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(25.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 25.0, 475.0, 25.0, 475.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 100.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 100.0, 25.0, 100.0, 0.0);
validateLoanTransaction(loanDetails, 4, 25.0, 25.0, 0.0, 25.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(25.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 100.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 100.0, 0.0);
validateLoanTransaction(loanDetails, 5, 25.0, 25.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC8: Refund after due & past due
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment - fails
// 3. Pay 1st installment on time - fails
// 4. Merchant issued refund next day
// 4. Pay rest on time
@Test
public void uc8() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(2).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("17 January 2023").locale("en").transactionAmount(300.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 200.0, 300.0, 200.0, 300.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 25.0, 100.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 25.0, 100.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 3, 300.0, 300.0, 0.0, 200.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(100.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 400.0, 100.0, 400.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 25.0, 100.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 4, 100.0, 100.0, 0.0, 100.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(100.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 5, 100.0, 100.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC9: Refund next installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Refund
// 4. Pay rest on time
@Test
public void uc9() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makePayoutRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("05 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 175.0, 325.0, 175.0, 325.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 75.0, 50.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 2, 200.0, 200.0, 0.0, 175.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 125.0, 375.0, 125.0, 375.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 3, 50.0, 50.0, 0.0, 125.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC10: Refund PD and next installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. 1st installment on time - fails
// 4. Payout refund issued refund next day
// 4. Pay rest on time
@Test
public void uc10() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(2).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makePayoutRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("17 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 175.0, 325.0, 175.0, 325.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 75.0, 50.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 3, 200.0, 200.0, 0.0, 175.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 125.0, 375.0, 125.0, 375.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 4, 50.0, 50.0, 0.0, 125.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 5, 125.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC11: Refund Past, pay in advance installments
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment - fails
// 3. Payout refund issued refund next day
// 4. Pay rest on time
@Test
public void uc11() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makePayoutRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 January 2023").locale("en").transactionAmount(400.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 400.0, 100.0, 400.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 25.0, 100.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 2, 400.0, 400.0, 0.0, 100.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(100.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 25.0, 0.0);
validateLoanTransaction(loanDetails, 3, 100.0, 100.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC12: Refund last installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Goodwill credit in advance
// 4. Pay rest on time
@Test
public void uc12() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("08 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 175.0, 325.0, 175.0, 325.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 75.0, 50.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 2, 200.0, 200.0, 0.0, 175.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 450.0, 50.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 75.0, 50.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 75.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC13: Due apply last installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay first installment on time - fails
// 4. Goodwill credit(due and in advance)
// 5. Pay rest on time
@Test
public void uc13() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(2).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("18 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 175.0, 325.0, 175.0, 325.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 75.0, 50.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 3, 200.0, 200.0, 0.0, 175.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 450.0, 50.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 75.0, 50.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 5, 50.0, 50.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC14: Refund PD
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay first installment on time - fails
// 4. Refund (DP due and in advance)
// 5. Pay rest on time
@Test
public void uc14() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(2).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("17 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 300.0, 200.0, 300.0, 200.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 75.0, 50.0, 0.0, 75.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 3, 200.0, 200.0, 0.0, 300.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 175.0, 325.0, 175.0, 325.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 75.0, 50.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 175.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(175.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 50.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 5, 175.0, 175.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC15: Goodwill credit PD
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay first installment on time - fails
// 4. Refund (DP due and in advance)
// 5. Pay rest on time
@Test
public void uc15() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 January 2023").locale("en").transactionAmount(200.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 300.0, 200.0, 300.0, 200.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 75.0, 50.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 2, 200.0, 200.0, 0.0, 300.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 175.0, 325.0, 175.0, 325.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 75.0, 50.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 175.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 450.0, 50.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 75.0, 50.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 75.0, 0.0);
validateLoanTransaction(loanDetails, 5, 50.0, 50.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC17a: Full refund with CBR
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay first installment on time
// 4. Full merchant issued refund
// 5. CBR
@Test
public void uc17a() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("08 January 2023").locale("en").transactionAmount(500.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 125.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 2, 500.0, 375.0, 125.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeCreditBalanceRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("09 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 0.0, 125.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC17b: Full refund with CBR
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay first installment on time
// 4. Full payout refund
// 5. CBR
@Test
public void uc17b() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makePayoutRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("08 January 2023").locale("en").transactionAmount(500.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 125.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 2, 500.0, 375.0, 125.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeCreditBalanceRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("09 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 0.0, 125.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC17c: Full refund with CBR
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay first installment on time
// 4. Full Goodwill credit
// 5. CBR
@Test
public void uc17c() {
runAt("15 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("08 January 2023").locale("en").transactionAmount(500.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 125.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 2, 500.0, 375.0, 125.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeCreditBalanceRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("09 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 0.0, 125.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC18: Full refund with CBR (N+1)
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment
// 3. Pay everything on time
// 4. Full merchant issued refund (after maturity date)
// 5. CBR
@Test
public void uc18() {
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 375.0, 125.0, 375.0, 125.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 125.0, 125.0, 0.0, 375.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 250.0, 250.0, 250.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 2, 125.0, 125.0, 0.0, 250.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 125.0, 375.0, 125.0, 375.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 3, 125.0, 125.0, 0.0, 125.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("18 February 2023").locale("en").transactionAmount(500.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 500.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 5, 500.0, 0.0, 500.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeCreditBalanceRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("20 February 2023").locale("en").transactionAmount(500.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 6, 500.0, 0.0, 500.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC24: Merchant issued credit reverse-replay
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment - fails
// 3. Merchant issued credit
// 4. Payments
// 5. CBR
// 6. Merchant issued credit - reversal
// 7. Payments
@Test
public void uc24() {
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("02 January 2023").locale("en").transactionAmount(400.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 400.0, 100.0, 400.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 91.67, 33.33, 91.67, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 91.67, 33.33, 91.67, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 91.66, 33.34, 91.66, 0.0);
validateLoanTransaction(loanDetails, 2, 400.0, 400.0, 0.0, 100.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("04 January 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 450.0, 50.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 108.34, 16.66, 108.34, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 91.66, 33.34, 91.66, 0.0);
validateLoanTransaction(loanDetails, 3, 50.0, 50.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, 75.0);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 4, 125.0, 50.0, 75.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeCreditBalanceRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("18 January 2023").locale("en").transactionAmount(75.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 500.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 125.0, 0.0);
validateLoanTransaction(loanDetails, 5, 75.0, 0.0, 75.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(2).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("20 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 400.0, 175.0, 400.0, 175.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 50.0, 75.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 200.0, 0.0, 200.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("31 January 2023").locale("en").transactionAmount(275.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 125.0, 450.0, 125.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 75.0);
validateRepaymentPeriod(loanDetails, 3, 200.0, 200.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 6, 275.0, 275.0, 0.0, 125.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("15 February 2023").locale("en").transactionAmount(125.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 575.0, 0.0, 575.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 0.0, 75.0);
validateRepaymentPeriod(loanDetails, 3, 200.0, 200.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 125.0, 0.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 7, 125.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC25: Merchant issued credit reverse-replay with uneven balances
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay down payment - fails
// 3. Merchant issued credit
// 4. Payments
// 5. Merchant issued credit
@Test
public void uc25() {
runAt("20 February 2023", () -> {
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), commonLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), loanDetails.getTransactions().get(1).getId(),
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("02 January 2023").locale("en").transactionAmount(400.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 400.0, 100.0, 400.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 91.67, 33.33, 91.67, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 91.67, 33.33, 91.67, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 91.66, 33.34, 91.66, 0.0);
validateLoanTransaction(loanDetails, 2, 400.0, 400.0, 0.0, 100.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("04 January 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 450.0, 50.0, 450.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 108.34, 16.66, 108.34, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 91.66, 33.34, 91.66, 0.0);
validateLoanTransaction(loanDetails, 3, 50.0, 50.0, 0.0, 50.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("06 January 2023").locale("en").transactionAmount(40.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 10.0, 490.0, 10.0, 490.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 115.0, 10.0, 115.0, 0.0);
validateLoanTransaction(loanDetails, 4, 40.0, 40.0, 0.0, 10.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC101: Multiple disbursement test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan
// 2. Pay over the down payment
// 3. Disburse again
@Test
public void uc101() {
runAt("20 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("04 January 2023").locale("en").transactionAmount(175.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 325.0, 175.0, 325.0, 175.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 50.0, 75.0, 50.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 125.0, 0.0, 125.0, 0.0, 0.0);
validateLoanTransaction(loanDetails, 1, 175.0, 175.0, 0.0, 325.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("05 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 825.0, 175.0, 825.0, 175.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 250.0, 50.0, 200.0, 50.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", true));
Integer penalty1LoanChargeId = loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "22 February 2023", "100"));
assertNotNull(penalty1LoanChargeId);
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 925.0, 175.0, 825.0, 175.0, null);
validateRepaymentPeriod(loanDetails, 1, 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, 250.0, 50.0, 200.0, 50.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 2, 22), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 0.0, 100.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC102: Multiple disbursement & reschedule test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (500)
// 2. Reschedule the 2nd period
// 3. Repayment (450)
// 3. Disburse again (250)
// 4. Reschedule the 3rd period to be later than the 2nd disbursement
@Test
public void uc102() {
runAt("20 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
PostCreateRescheduleLoansResponse rescheduleLoansResponse = loanRescheduleRequestHelper
.createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest().loanId(loanDetails.getId()).locale("en")
.dateFormat(DATETIME_PATTERN).rescheduleReasonId(1L).rescheduleFromDate("16 January 2023")
.adjustedDueDate("31 January 2023").submittedOnDate("16 January 2023"));
loanRescheduleRequestHelper.approveLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(),
new PostUpdateRescheduleLoansRequest().approvedOnDate("16 January 2023").locale("en").dateFormat(DATETIME_PATTERN));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 January 2023").locale("en").transactionAmount(350.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 150.0, 350.0, 150.0, 350.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 125.0, 100.0, 25.0, 100.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("20 February 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(250.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 400.0, 350.0, 400.0, 350.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 125.0, 100.0, 25.0, 100.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 20), 62.5, 0.0, 62.5, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 2), 312.5, 0.0, 312.5, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
rescheduleLoansResponse = loanRescheduleRequestHelper.createLoanRescheduleRequest(new PostCreateRescheduleLoansRequest()
.loanId(loanDetails.getId()).locale("en").dateFormat(DATETIME_PATTERN).rescheduleReasonId(1L)
.rescheduleFromDate("15 February 2023").adjustedDueDate("25 February 2023").submittedOnDate("15 February 2023"));
loanRescheduleRequestHelper.approveLoanRescheduleRequest(rescheduleLoansResponse.getResourceId(),
new PostUpdateRescheduleLoansRequest().approvedOnDate("15 February 2023").locale("en").dateFormat(DATETIME_PATTERN));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 400.0, 350.0, 400.0, 350.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 125.0, 125.0, 0.0, 125.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 20), 62.5, 0.0, 62.5, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 25), 218.75, 100.0, 118.75, 100.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 12), 218.75, 0.0, 218.75, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC103: Advanced payment allocation, add charge after maturity -> N+1 installment, repay the loan
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (500)
// 2. Add charge after maturity date
// 3. Fully repay the loan
@Test
public void uc103() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", true));
Integer penalty1LoanChargeId = loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "22 February 2023", "100"));
assertNotNull(penalty1LoanChargeId);
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 600.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 2, 22), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 0.0, 100.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("22 February 2023").locale("en").transactionAmount(600.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 600.0, 0.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 2, 22), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 100.0, 100.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
});
}
// UC104: Advanced payment allocation, horizontal repayment processing
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (500)
// 2. Add charge for 3rd and 4th installments
// 3. Pay little more than the charge of 1st installment
// 4. Pay little more than the principal of 1st installment and charge of 2nd installment
@Test
public void uc104() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "25", true));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "20 January 2023", "25"));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "10 February 2023", "25"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 550.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("22 February 2023").locale("en").transactionAmount(260.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 290.0, 260.0, 250.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 10.0, 15.0, 0.0, 0.0,
0.0, 0.0, 10.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("22 February 2023").locale("en").transactionAmount(26.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 264.0, 286.0, 239.0, 261.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 125.0, 0.0, 0.0, 125.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 11.0, 114.0, 0.0, 0.0, 0.0, 25.0, 25.0, 0.0, 0.0, 0.0,
0.0, 0.0, 36.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC105: Advanced payment allocation, vertical repayment processing
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (500)
// 2. Add charge for 3rd and 4th installments
// 3. Pay little more than the charge of 1st installment
// 4. Pay little more than the charges
@Test
public void uc105() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("500", "15", "4", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(500.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(500)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(500.00)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 500.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "25", true));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "20 January 2023", "25"));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "10 February 2023", "25"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 550.0, 0.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 0.0, 25.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("22 February 2023").locale("en").transactionAmount(26.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 524.0, 26.0, 500.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 25.0, 0.0, 0.0, 0.0,
0.0, 0.0, 25.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 1.0, 24.0, 0.0, 0.0,
0.0, 0.0, 1.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("22 February 2023").locale("en").transactionAmount(26.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 498.0, 52.0, 498.0, 2.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 125.0, 2.0, 123.0, 0.0, 2.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 125.0, 0.0, 125.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 25.0, 0.0, 0.0, 0.0,
0.0, 0.0, 25.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 125.0, 0.0, 125.0, 0.0, 0.0, 0.0, 25.0, 25.0, 0.0, 0.0, 0.0,
0.0, 0.0, 25.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC106: Advanced payment allocation, horizontal repayment processing, mixed grouping of allocation rules
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, but the allocation rules are mixed -> expect validation error
@Test
public void uc106() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
AdvancedPaymentData defaultPaymentAllocation = createDefaultPaymentAllocationWithMixedGrouping();
ArrayList<HashMap<String, Object>> loanProductErrorData = createLoanProductGetError("500", "15", "4", false,
LoanScheduleType.PROGRESSIVE, LoanScheduleProcessingType.HORIZONTAL, defaultPaymentAllocation, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
assertNotNull(loanProductErrorData);
assertEquals("mixed.due.type.allocation.rules.are.not.supported.with.horizontal.installment.processing",
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
});
}
// UC107: Advanced payment allocation, vertical repayment processing, mixed grouping of allocation rules
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, but the allocation rules are mixed -> no validation error
// 2. Change transaction processor while submitting loan -> expect validation error
// 3. Change to HORIZONTAL loan schedule processing and allocation rules are mixed - > expect validation error
@Test
public void uc107() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
AdvancedPaymentData defaultPaymentAllocation = createDefaultPaymentAllocationWithMixedGrouping();
Integer localLoanProductId = createLoanProduct("500", "15", "4", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, defaultPaymentAllocation, assetAccount, incomeAccount, expenseAccount,
overpaymentAccount);
assertNotNull(localLoanProductId);
CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class,
() -> applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023",
FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE,
LoanScheduleProcessingType.VERTICAL.name()));
assertEquals(400, exception.getResponse().code());
assertTrue(exception.getMessage().contains("supported.only.with.advanced.payment.allocation.strategy"));
exception = assertThrows(CallFailedRuntimeException.class,
() -> applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(500.0), 45, 15, 3,
BigDecimal.ZERO, "01 January 2023", "01 January 2023",
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
LoanScheduleProcessingType.HORIZONTAL.name()));
assertEquals(400, exception.getResponse().code());
assertTrue(exception.getMessage()
.contains("mixed.due.type.allocation.rules.are.not.supported.with.horizontal.installment.processing"));
});
}
// UC108: Advanced payment allocation, progressive loan schedule handling, rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 1000 principal, across 3 installment
// 2. Submit the loan, and check the generated repayment schedule
@Test
public void uc108() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", false, null, false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 45,
15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getPendingApproval());
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 166.65, 0.0, 166.65, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getPendingApproval());
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 166.65, 0.0, 166.65, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 166.65, 0.0, 166.65, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC109: Advanced payment allocation, progressive loan schedule handling, rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 1000 principal, across 3 installment
// 2. Submit the loan, and check the generated repayment schedule
@Test
public void uc109() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", false, null, false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 45,
15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getPendingApproval());
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 333.33, 0.0, 333.33, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 333.34, 0.0, 333.34, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(1000), 90, 15, 6,
BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 166.65, 0.0, 166.65, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getPendingApproval());
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 166.65, 0.0, 166.65, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 16), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 31), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 2, 15), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 3, 2), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 3, 17), 166.67, 0.0, 166.67, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 6, LocalDate.of(2023, 4, 1), 166.65, 0.0, 166.65, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC110: Advanced payment allocation, progressive loan schedule handling, rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 40.50 principal, across 4 installment (1 down payment, 3 normal installment)
// 2. Submit the loan, and check the generated repayment schedule
@Test
public void uc110() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("40.50", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(40.50),
45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 10.12, 0.0, 10.12, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getPendingApproval());
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(40.5)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 10.12, 0.0, 10.12, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(40.5)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 40.5, 0.0, 40.5, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 10.12, 0.0, 10.12, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC111: Advanced payment allocation, progressive loan schedule handling, rounding test
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product, 40.50 principal, across 4 installment (1 down payment, 3 normal installment)
// 2. Submit the loan, and check the generated repayment schedule
@Test
public void uc111() {
runAt("22 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("40.50", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
assertNotNull(localLoanProductId);
PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId, BigDecimal.valueOf(40.50),
45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 10.12, 0.0, 10.12, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getPendingApproval());
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(40.5)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 10.12, 0.0, 10.12, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getWaitingForDisbursal());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(40.5)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 40.5, 0.0, 40.5, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 10.12, 0.0, 10.12, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 10.13, 0.0, 10.13, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 10.12, 0.0, 10.12, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC112: Advanced payment allocation, horizontal repayment processing
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge after maturity date
// 3. Pay 1st installment
// 4. Pay 2nd installment
// 5. Add charge to 3rd installment
// 6. Add charge to 4th installment
// 7. Do goodwill credit (in advance payment)
@Test
public void uc112() {
runAt("01 September 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 September 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 September 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "20", true));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 October 2023", "20"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1020.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("01 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 770.0, 250.0, 750.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
businessDateHelper.updateBusinessDate(new BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
.date("2023.09.16").dateFormat("yyyy.MM.dd").locale("en"));
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 520.0, 500.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 September 2023", "20"));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "16 October 2023", "20"));
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 510.0, 550.0, 490.0, 510.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 10.0, 240.0, 0.0, 0.0, 0.0, 20.0, 20.0, 0.0, 0.0,
0.0, 0.0, 30.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 20.0, 0.0, 0.0, 0.0,
0.0, 20.0, 0.0);
validateLoanCharge(loanDetails, 0, LocalDate.of(2023, 9, 17), 20.0, 0.0, 20.0);
validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 20.0, 20.0, 0.0);
validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 20.0, 20.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC113: Advanced payment allocation, vertical repayment processing
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge after maturity date
// 3. Pay 1st installment
// 4. Pay 2nd installment
// 5. Add charge to 3rd installment
// 6. Add charge to 4th installment
// 7. Do goodwill credit (in advance payment)
@Test
public void uc113() {
runAt("01 September 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 September 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 September 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "20", true));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 October 2023", "20"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1020.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("01 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 770.0, 250.0, 750.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
businessDateHelper.updateBusinessDate(new BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
.date("2023.09.16").dateFormat("yyyy.MM.dd").locale("en"));
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 520.0, 500.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 September 2023", "20"));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "16 October 2023", "20"));
loanTransactionHelper.makeGoodwillCredit(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(50.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 510.0, 550.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0, 0.0,
0.0, 10.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 20.0, 0.0, 0.0, 0.0,
0.0, 20.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 20.0, 0.0, 0.0, 0.0,
0.0, 20.0, 0.0);
validateLoanCharge(loanDetails, 0, LocalDate.of(2023, 9, 17), 20.0, 10.0, 10.0);
validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 20.0, 20.0, 0.0);
validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 20.0, 20.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC114: Advanced payment allocation, horizontal repayment processing
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge after maturity date
// 3. Pay 1st installment
// 4. Pay 2nd installment
// 5. Add charge to 3rd installment
// 6. Add charge to 4th installment
// 7. Do merchant issued refund (in advance payment)
@Test
public void uc114() {
runAt("01 September 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 September 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 September 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "20", true));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 October 2023", "20"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1020.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("01 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 770.0, 250.0, 750.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
businessDateHelper.updateBusinessDate(new BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
.date("2023.09.16").dateFormat("yyyy.MM.dd").locale("en"));
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 520.0, 500.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 September 2023", "20"));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "16 October 2023", "20"));
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(30.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 530.0, 530.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0, 0.0,
0.0, 10.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0,
0.0, 0.0, 10.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0, 0.0,
0.0, 10.0, 0.0);
validateLoanCharge(loanDetails, 0, LocalDate.of(2023, 9, 17), 20.0, 10.0, 10.0);
validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 20.0, 10.0, 10.0);
validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 20.0, 10.0, 10.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC115: Advanced payment allocation, vertical repayment processing
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge after maturity date
// 3. Pay 1st installment
// 4. Pay 2nd installment
// 5. Add charge to 3rd installment
// 6. Add charge to 4th installment
// 7. Do merchant issued refund (in advance payment)
@Test
public void uc115() {
runAt("01 September 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.VERTICAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 September 2023", "01 September 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 September 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 September 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Penalty
Integer penalty = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "20", true));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 October 2023", "20"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1020.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("01 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 770.0, 250.0, 750.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
businessDateHelper.updateBusinessDate(new BusinessDateRequest().type(BusinessDateType.BUSINESS_DATE.getName())
.date("2023.09.16").dateFormat("yyyy.MM.dd").locale("en"));
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 520.0, 500.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 0.0, 20.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "17 September 2023", "20"));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty), "16 October 2023", "20"));
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("16 September 2023").locale("en").transactionAmount(30.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 530.0, 530.0, 500.0, 500.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 9, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 9, 16), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 10, 1), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0, 0.0,
0.0, 10.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 10, 16), 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0,
0.0, 0.0, 10.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2023, 10, 17), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 10.0, 10.0, 0.0, 0.0,
0.0, 10.0, 0.0);
validateLoanCharge(loanDetails, 0, LocalDate.of(2023, 9, 17), 20.0, 10.0, 10.0);
validateLoanCharge(loanDetails, 1, LocalDate.of(2023, 10, 16), 20.0, 10.0, 10.0);
validateLoanCharge(loanDetails, 2, LocalDate.of(2023, 10, 17), 20.0, 10.0, 10.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC116: Advanced payment allocation, horizontal repayment processing, disbursement on due date of an installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge on disbursement date(50)
// 3. Repay down payment fully on disbursement date (250)
// 4. Disburse on 1st installment due date (400)
@Test
public void uc116() {
runAt("01 January 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Fee
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee), "01 January 2023", "50"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1050.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 800.0, 250.0, 750.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
updateBusinessDate("16 January 2023");
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("16 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(400.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1200.0, 250.0, 1150.0, 250.0, null);
validatePeriod(loanDetails, 0, LocalDate.of(2023, 1, 1), null, 1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), LocalDate.of(2023, 1, 1), 750.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), null, 500.0, 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 3, LocalDate.of(2023, 1, 16), null, 400.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 4, LocalDate.of(2023, 1, 16), null, 800.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 5, LocalDate.of(2023, 1, 31), null, 400.0, 400.0, 0.0, 400.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 6, LocalDate.of(2023, 2, 15), null, 0.0, 400.0, 0.0, 400.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC117: Advanced payment allocation, horizontal repayment processing, multi disbursement on due date of an
// installment
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Add charge on disbursement date(50)
// 3. Repay down payment fully on disbursement date (250)
// 4. Disburse on 1st installment due date (400)
// 4. Disburse on 1st installment due date (80)
@Test
public void uc117() {
runAt("01 January 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
// Add Charge Fee
Integer fee = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "50", false));
loanTransactionHelper.addChargesForLoan(loanResponse.getLoanId().intValue(),
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(fee), "01 January 2023", "50"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1050.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("01 January 2023").locale("en").transactionAmount(250.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 800.0, 250.0, 750.0, 250.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 250.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
updateBusinessDate("16 January 2023");
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("16 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(400.0)).locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("16 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(80.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1280.0, 250.0, 1230.0, 250.0, null);
validatePeriod(loanDetails, 0, LocalDate.of(2023, 1, 1), null, 1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), LocalDate.of(2023, 1, 1), 750.0, 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), null, 500.0, 250.0, 0.0, 250.0, 50.0, 0.0, 50.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 3, LocalDate.of(2023, 1, 16), null, 400.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 4, LocalDate.of(2023, 1, 16), null, 80.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 5, LocalDate.of(2023, 1, 16), null, 880.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 6, LocalDate.of(2023, 1, 16), null, 860.0, 20.0, 0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
validatePeriod(loanDetails, 7, LocalDate.of(2023, 1, 31), null, 430.0, 430.0, 0.0, 430.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 8, LocalDate.of(2023, 2, 15), null, 0.0, 430.0, 0.0, 430.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC118: Advanced payment allocation, horizontal repayment processing, multi disbursement on disbursement date
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Disburse the loan (1000)
// 2. Disburse on disbursement date (400)
@Test
public void uc118() {
runAt("01 January 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("01 January 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(1000.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1000.0, 0.0, 1000.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 1, 16), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 1, 31), 250.0, 0.0, 250.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 2, 15), 250.0, 0.0, 250.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("01 January 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(400.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 1400.0, 0.0, 1400.0, 0.0, null);
validatePeriod(loanDetails, 0, LocalDate.of(2023, 1, 1), null, 1000.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 1, LocalDate.of(2023, 1, 1), null, 400.0, null, null, null, 0.0, 0.0, null, null, null, null, null,
null, null, null, null);
validatePeriod(loanDetails, 2, LocalDate.of(2023, 1, 1), null, 1150.0, 250.0, 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 3, LocalDate.of(2023, 1, 1), null, 1050.0, 100.0, 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 4, LocalDate.of(2023, 1, 16), null, 700.0, 350.0, 0.0, 350.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 5, LocalDate.of(2023, 1, 31), null, 350.0, 350.0, 0.0, 350.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 6, LocalDate.of(2023, 2, 15), null, 0.0, 350.0, 0.0, 350.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC119: Advanced payment allocation with Loan Schedule as Cumulative
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc., but the loan schedule as Cumulative -> expect validation error
@Test
public void uc119() {
runAt("02 February 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
AdvancedPaymentData defaultPaymentAllocation = createDefaultPaymentAllocation();
ArrayList<HashMap<String, Object>> loanProductErrorData = createLoanProductGetError("500", "15", "4", false,
LoanScheduleType.CUMULATIVE, LoanScheduleProcessingType.HORIZONTAL, defaultPaymentAllocation, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
assertNotNull(loanProductErrorData);
assertEquals("validation.msg.loanproduct.loanScheduleProcessingType.supported.only.for.progressive.loan.schedule.type",
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
});
}
// UC120: Advanced payment allocation with auto down payment and multiple disbursement on the first day
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc., and auto down payment
// 2. Submit Loan and approve
// 3. Disburse only 100 from 1000
// 4. Disburse again on the same day but now 901
@Test
public void uc120() {
runAt("22 November 2023", () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", true, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), localLoanProductId,
BigDecimal.valueOf(1000.0), 45, 15, 3, BigDecimal.ZERO, "22 November 2023", "01 January 2023");
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("22 November 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("22 November 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(100.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 75.0, 25.0, 75.0, 25.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 25.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 12, 7), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 22), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2024, 1, 6), 25.0, 0.0, 25.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("22 November 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(901.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 750.75, 250.25, 750.75, 250.25, null);
validatePeriod(loanDetails, 0, LocalDate.of(2023, 11, 22), null, 100.0, null, null, null, 0.0, 0.0, null, null, null, null,
null, null, null, null, null);
validatePeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), null, 901.0, null, null, null, 0.0, 0.0, null, null, null, null,
null, null, null, null, null);
validatePeriod(loanDetails, 2, LocalDate.of(2023, 11, 22), LocalDate.of(2023, 11, 22), 976.0, 25.0, 25.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 3, LocalDate.of(2023, 11, 22), LocalDate.of(2023, 11, 22), 750.75, 225.25, 225.25, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 4, LocalDate.of(2023, 12, 7), null, 500.50, 250.25, 0.0, 250.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 5, LocalDate.of(2023, 12, 22), null, 250.25, 250.25, 0.0, 250.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0);
validatePeriod(loanDetails, 6, LocalDate.of(2024, 1, 6), null, 0.0, 250.25, 0.0, 250.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
});
}
// UC121: Advanced payment allocation, horizontal repayment processing product and Loan application
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
@Test
public void uc121() {
final String operationDate = "01 January 2023";
runAt(operationDate, () -> {
final Account assetAccount = accountHelper.createAssetAccount();
final Account incomeAccount = accountHelper.createIncomeAccount();
final Account expenseAccount = accountHelper.createExpenseAccount();
final Account overpaymentAccount = accountHelper.createLiabilityAccount();
Integer localLoanProductId = createLoanProduct("1000", "15", "3", true, "25", false, LoanScheduleType.PROGRESSIVE,
LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(client.getClientId()).productId(localLoanProductId.longValue())
.loanType("individual").locale("en").submittedOnDate(operationDate).expectedDisbursementDate(operationDate)
.dateFormat(DATETIME_PATTERN).amortizationType(1).interestRatePerPeriod(BigDecimal.ZERO)
.interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0).repaymentEvery(15).repaymentFrequencyType(0)
.numberOfRepayments(3).loanTermFrequency(45).loanTermFrequencyType(0).principal(BigDecimal.valueOf(1000.0))
.maxOutstandingLoanBalance(BigDecimal.valueOf(35000))
.transactionProcessingStrategyCode(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
.loanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL.name()));
loanTransactionHelper.applyLoanWithError(new PostLoansRequest().clientId(client.getClientId())
.productId(localLoanProductId.longValue()).loanType("individual").locale("en").submittedOnDate(operationDate)
.expectedDisbursementDate(operationDate).dateFormat(DATETIME_PATTERN).amortizationType(1)
.interestRatePerPeriod(BigDecimal.ZERO).interestCalculationPeriodType(1).interestType(0).repaymentFrequencyType(0)
.repaymentEvery(15).repaymentFrequencyType(0).numberOfRepayments(3).loanTermFrequency(45).loanTermFrequencyType(0)
.principal(BigDecimal.valueOf(1000.0)).maxOutstandingLoanBalance(BigDecimal.valueOf(35000))
.transactionProcessingStrategyCode(FineractStyleLoanRepaymentScheduleTransactionProcessor.STRATEGY_CODE)
.loanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL.name()), 403);
});
}
// UC122: Advanced payment allocation, 2nd disbursement on overpaid loan
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc.
// 2. Submit Loan and approve
// 3. Disburse only 100 from 1000
// 4. Overpay the loan (150)
// 5. Disburse again 100
@Test
public void uc122() {
runAt("24 November 2023", () -> {
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation()
.numberOfRepayments(3).repaymentEvery(15).enableDownPayment(true)
.disbursedAmountPercentageForDownPayment(BigDecimal.valueOf(25)).enableAutoRepaymentForDownPayment(false);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductResponse.getResourceId(), "22 November 2023",
1000.0, 4);
applicationRequest = applicationRequest.numberOfRepayments(3).loanTermFrequency(45)
.transactionProcessingStrategyCode(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY).repaymentEvery(15);
PostLoansResponse loanResponse = loanTransactionHelper.applyLoan(applicationRequest);
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("22 November 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("22 November 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(100.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 0.0, 100.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 12, 7), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 22), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2024, 1, 6), 25.0, 0.0, 25.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("23 November 2023").locale("en").transactionAmount(150.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 50.0);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 25.0, 0.0, 0.0, 25.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 12, 7), 25.0, 25.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 22), 25.0, 25.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2024, 1, 6), 25.0, 25.0, 0.0, 25.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("24 November 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(100.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 50.0, 150.0, 50.0, 150.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 25.0, 0.0, 0.0, 25.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 11, 24), 25.0, 25.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 7), 50.0, 50.0, 0.0, 50.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 12, 22), 50.0, 25.0, 25.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2024, 1, 6), 50.0, 25.0, 25.0, 25.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
verifyTransactions(loanResponse.getLoanId(), //
transaction(100, "Disbursement", "22 November 2023", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(150, "Repayment", "23 November 2023", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 50.0), //
transaction(100, "Disbursement", "24 November 2023", 50.0, 0.0, 0.0, 0.0, 0.0, 0.0, 50.0) //
);
// verify journal entries
verifyJournalEntries(loanResponse.getLoanId(), journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
journalEntry(50.0, overpaymentAccount, "CREDIT"), //
journalEntry(150.0, fundSource, "DEBIT"), //
journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
journalEntry(50.0, overpaymentAccount, "DEBIT"), //
journalEntry(100.0, fundSource, "CREDIT") //
);
});
}
// UC123: Advanced payment allocation, 2nd disbursement on overpaid loan
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc.
// 2. Submit Loan and approve
// 3. Disburse only 100 from 1000
// 4. Overpay the loan (150)
// 5. Disburse again 25
@Test
public void uc123() {
runAt("22 November 2023", () -> {
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation()
.numberOfRepayments(3).repaymentEvery(15).enableDownPayment(true)
.disbursedAmountPercentageForDownPayment(BigDecimal.valueOf(25)).enableAutoRepaymentForDownPayment(false);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductResponse.getResourceId(), "22 November 2023",
1000.0, 4);
applicationRequest = applicationRequest.numberOfRepayments(3).loanTermFrequency(45)
.transactionProcessingStrategyCode(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY).repaymentEvery(15);
PostLoansResponse loanResponse = loanTransactionHelper.applyLoan(applicationRequest);
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("22 November 2023").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("22 November 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(100.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 0.0, 100.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 12, 7), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 22), 25.0, 0.0, 25.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2024, 1, 6), 25.0, 0.0, 25.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.dateFormat(DATETIME_PATTERN).transactionDate("22 November 2023").locale("en").transactionAmount(150.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 50.0);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 25.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 12, 7), 25.0, 25.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 22), 25.0, 25.0, 0.0, 25.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2024, 1, 6), 25.0, 25.0, 0.0, 25.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("22 November 2023").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(28.0)).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 128.0, 0.0, 128.0, 22.0);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2023, 11, 22), 25.0, 25.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2023, 11, 22), 7.0, 7.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 3, LocalDate.of(2023, 12, 7), 32.0, 32.0, 0.0, 32.0, 0.0);
validateRepaymentPeriod(loanDetails, 4, LocalDate.of(2023, 12, 22), 32.0, 32.0, 0.0, 32.0, 0.0);
validateRepaymentPeriod(loanDetails, 5, LocalDate.of(2024, 1, 6), 32.0, 32.0, 0.0, 32.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
verifyTransactions(loanResponse.getLoanId(), //
transaction(100, "Disbursement", "22 November 2023", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(150, "Repayment", "22 November 2023", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 50.0), //
transaction(28, "Disbursement", "22 November 2023", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 28.0) //
);
// verify journal entries
verifyJournalEntries(loanResponse.getLoanId(), journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
journalEntry(50.0, overpaymentAccount, "CREDIT"), //
journalEntry(150.0, fundSource, "DEBIT"), //
journalEntry(28.0, overpaymentAccount, "DEBIT"), //
journalEntry(28.0, fundSource, "CREDIT") //
);
});
}
// UC124: Advanced payment allocation, MIR, CBR and Chargeback on overpaid loan
// ADVANCED_PAYMENT_ALLOCATION_STRATEGY
// 1. Create a Loan product with Adv. Pment. Alloc.
// 2. Submit Loan and approve
// 3. Disburse only 100
// 4. Fully pay the loan
// 5. Do MIR 3 times
// 6. Do a CBR
// 7. Do MIR 2 times
// 8. Reverse the 1st MIR
// 9. Do Chargeback (lower than overpayment amount)
// 10.Do Chargeback again (reactive the loan)
@Test
public void uc124() {
runAt("06 March 2024", () -> {
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation()
.numberOfRepayments(1).repaymentEvery(30).enableDownPayment(false);
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductResponse.getResourceId(), "25 January 2024", 1000.0,
4);
applicationRequest = applicationRequest.numberOfRepayments(1).loanTermFrequency(30)
.transactionProcessingStrategyCode(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY).repaymentEvery(30);
PostLoansResponse loanResponse = loanTransactionHelper.applyLoan(applicationRequest);
loanTransactionHelper.approveLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().approvedLoanAmount(BigDecimal.valueOf(1000)).dateFormat(DATETIME_PATTERN)
.approvedOnDate("25 January 2024").locale("en"));
loanTransactionHelper.disburseLoan(loanResponse.getLoanId(),
new PostLoansLoanIdRequest().actualDisbursementDate("25 January 2024").dateFormat(DATETIME_PATTERN)
.transactionAmount(BigDecimal.valueOf(100.0)).locale("en"));
GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 100.0, 0.0, 100.0, 0.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 0.0, 100.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getActive());
String repaymentExternalId = UUID.randomUUID().toString();
loanTransactionHelper.makeLoanRepayment(loanResponse.getLoanId(),
new PostLoansLoanIdTransactionsRequest().dateFormat(DATETIME_PATTERN).transactionDate("24 February 2024").locale("en")
.transactionAmount(100.0).externalId(repaymentExternalId));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
String mir1ExternalId = UUID.randomUUID().toString();
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(),
new PostLoansLoanIdTransactionsRequest().transactionDate("28 February 2024").dateFormat(DATETIME_PATTERN)
.transactionAmount(36.99).locale("en").externalId(mir1ExternalId));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 36.99);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.transactionDate("28 February 2024").dateFormat(DATETIME_PATTERN).transactionAmount(18.94).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 55.93);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.transactionDate("28 February 2024").dateFormat(DATETIME_PATTERN).transactionAmount(36.99).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 92.92);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.transactionDate("28 February 2024").dateFormat(DATETIME_PATTERN).transactionAmount(31.99).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 124.91);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeCreditBalanceRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.transactionDate("01 March 2024").dateFormat(DATETIME_PATTERN).transactionAmount(124.91).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getClosedObligationsMet());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.transactionDate("02 March 2024").dateFormat(DATETIME_PATTERN).transactionAmount(19.99).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 19.99);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
loanTransactionHelper.makeMerchantIssuedRefund(loanResponse.getLoanId(), new PostLoansLoanIdTransactionsRequest()
.transactionDate("02 March 2024").dateFormat(DATETIME_PATTERN).transactionAmount(19.99).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 100.0, 0.0, 100.0, 39.98);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
assertTrue(loanDetails.getStatus().getOverpaid());
verifyTransactions(loanResponse.getLoanId(), //
transaction(100, "Disbursement", "25 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100, "Repayment", "24 February 2024", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(18.94, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 18.94), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 55.93), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 92.92), //
transaction(31.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 124.91), //
transaction(124.91, "Credit Balance Refund", "01 March 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 124.91), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 19.99), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 39.98) //
);
loanTransactionHelper.reverseLoanTransaction(loanResponse.getLoanId(), mir1ExternalId,
new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("02 March 2024")
.transactionAmount(0.0).locale("en"));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 224.91, 0.0, 224.91, 2.99);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2024, 3, 1), 124.91, 124.91, 0.0, 0.0, 36.99);
assertTrue(loanDetails.getStatus().getOverpaid());
verifyTransactions(loanResponse.getLoanId(), //
transaction(100, "Disbursement", "25 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100, "Repayment", "24 February 2024", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 36.99, true), //
transaction(18.94, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 18.94), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 55.93), //
transaction(31.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 87.92), //
transaction(124.91, "Credit Balance Refund", "01 March 2024", 36.99, 36.99, 0.0, 0.0, 0.0, 0.0, 87.92), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 17.0, 19.99, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 0.0, 17.0, 0.0, 0.0, 0.0, 0.0, 2.99) //
);
loanTransactionHelper.chargebackLoanTransaction(loanResponse.getLoanId(), repaymentExternalId,
new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(2.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.0, 224.91, 0.0, 224.91, 0.99);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2024, 3, 1), 124.91, 124.91, 0.0, 0.0, 36.99);
assertTrue(loanDetails.getStatus().getOverpaid());
verifyTransactions(loanResponse.getLoanId(), //
transaction(100, "Disbursement", "25 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100, "Repayment", "24 February 2024", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 36.99, true), //
transaction(18.94, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 18.94), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 55.93), //
transaction(31.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 87.92), //
transaction(124.91, "Credit Balance Refund", "01 March 2024", 36.99, 36.99, 0.0, 0.0, 0.0, 0.0, 87.92), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 17.0, 19.99, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 0.0, 17.0, 0.0, 0.0, 0.0, 0.0, 2.99), //
transaction(2.0, "Chargeback", "06 March 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0) //
);
loanTransactionHelper.chargebackLoanTransaction(loanResponse.getLoanId(), repaymentExternalId,
new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(1.0));
loanDetails = loanTransactionHelper.getLoanDetails(loanResponse.getLoanId());
validateLoanSummaryBalances(loanDetails, 0.01, 225.90, 0.01, 225.90, null);
validateRepaymentPeriod(loanDetails, 1, LocalDate.of(2024, 2, 24), 100.0, 100.0, 0.0, 0.0, 0.0);
validateRepaymentPeriod(loanDetails, 2, LocalDate.of(2024, 3, 6), 125.91, 125.90, 0.01, 0.0, 36.99);
assertTrue(loanDetails.getStatus().getActive());
verifyTransactions(loanResponse.getLoanId(), //
transaction(100, "Disbursement", "25 January 2024", 100.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(100, "Repayment", "24 February 2024", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 36.99, true), //
transaction(18.94, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 18.94), //
transaction(36.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 55.93), //
transaction(31.99, "Merchant Issued Refund", "28 February 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 87.92), //
transaction(124.91, "Credit Balance Refund", "01 March 2024", 36.99, 36.99, 0.0, 0.0, 0.0, 0.0, 87.92), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 17.0, 19.99, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(19.99, "Merchant Issued Refund", "02 March 2024", 0.0, 17.0, 0.0, 0.0, 0.0, 0.0, 2.99), //
transaction(2.0, "Chargeback", "06 March 2024", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0), //
transaction(1.0, "Chargeback", "06 March 2024", 0.01, 0.01, 0.0, 0.0, 0.0, 0.0, 0.99) //
);
});
}
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;
}).collect(Collectors.toList());
}
private static AdvancedPaymentData createDefaultPaymentAllocationWithMixedGrouping() {
AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
advancedPaymentData.setTransactionType("DEFAULT");
advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
List<PaymentAllocationOrder> paymentAllocationOrders = getPaymentAllocationOrder(PaymentAllocationType.DUE_PENALTY,
PaymentAllocationType.PAST_DUE_FEE, PaymentAllocationType.PAST_DUE_PRINCIPAL, PaymentAllocationType.PAST_DUE_INTEREST,
PaymentAllocationType.PAST_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 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 AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule) {
AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
advancedPaymentData.setTransactionType(transactionType);
advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule);
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 Integer createLoanProduct(final String principal, final String repaymentAfterEvery, final String numberOfRepayments,
boolean autoPayForDownPayment, LoanScheduleType loanScheduleType, LoanScheduleProcessingType loanScheduleProcessingType,
AdvancedPaymentData allocationRuleData, final Account... accounts) {
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
final String loanProductJSON = new LoanProductTestBuilder().withMinPrincipal(principal).withPrincipal(principal)
.withRepaymentTypeAsDays().withRepaymentAfterEvery(repaymentAfterEvery).withNumberOfRepayments(numberOfRepayments)
.withEnableDownPayment(true, "25", autoPayForDownPayment).withinterestRatePerPeriod("0")
.withInterestRateFrequencyTypeAsMonths()
.withRepaymentStrategy(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
.withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts)
.addAdvancedPaymentAllocation(allocationRuleData).withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
.withInterestTypeAsDecliningBalance().withMultiDisburse().withDisallowExpectedDisbursements(true)
.withLoanScheduleType(loanScheduleType).withLoanScheduleProcessingType(loanScheduleProcessingType).withDaysInMonth("30")
.withDaysInYear("365").withMoratorium("0", "0").build(null);
return loanTransactionHelper.getLoanProductId(loanProductJSON);
}
private static ArrayList<HashMap<String, Object>> createLoanProductGetError(final String principal, final String repaymentAfterEvery,
final String numberOfRepayments, boolean autoPayForDownPayment, LoanScheduleType loanScheduleType,
LoanScheduleProcessingType loanScheduleProcessingType, AdvancedPaymentData allocationRuleData, final Account... accounts) {
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
final String loanProductJSON = new LoanProductTestBuilder().withMinPrincipal(principal).withPrincipal(principal)
.withRepaymentTypeAsDays().withRepaymentAfterEvery(repaymentAfterEvery).withNumberOfRepayments(numberOfRepayments)
.withEnableDownPayment(true, "25", autoPayForDownPayment).withinterestRatePerPeriod("0")
.withInterestRateFrequencyTypeAsMonths()
.withRepaymentStrategy(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
.withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts)
.addAdvancedPaymentAllocation(allocationRuleData).withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
.withInterestTypeAsDecliningBalance().withMultiDisburse().withDisallowExpectedDisbursements(true)
.withLoanScheduleType(loanScheduleType).withLoanScheduleProcessingType(loanScheduleProcessingType).withDaysInMonth("30")
.withDaysInYear("365").withMoratorium("0", "0").build(null);
LoanTransactionHelper loanTransactionHelperBadRequest = new LoanTransactionHelper(requestSpec,
new ResponseSpecBuilder().expectStatusCode(400).build());
return loanTransactionHelperBadRequest.getLoanProductError(loanProductJSON, CommonConstants.RESPONSE_ERROR);
}
private static Integer createLoanProduct(final String principal, final String repaymentAfterEvery, final String numberOfRepayments,
boolean downPaymentEnabled, String downPaymentPercentage, boolean autoPayForDownPayment, LoanScheduleType loanScheduleType,
LoanScheduleProcessingType loanScheduleProcessingType, final Account... accounts) {
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation();
AdvancedPaymentData goodwillCreditAllocation = createPaymentAllocation("GOODWILL_CREDIT", "LAST_INSTALLMENT");
AdvancedPaymentData merchantIssuedRefundAllocation = createPaymentAllocation("MERCHANT_ISSUED_REFUND", "REAMORTIZATION");
AdvancedPaymentData payoutRefundAllocation = createPaymentAllocation("PAYOUT_REFUND", "NEXT_INSTALLMENT");
LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
final String loanProductJSON = new LoanProductTestBuilder().withMinPrincipal(principal).withPrincipal(principal)
.withRepaymentTypeAsDays().withRepaymentAfterEvery(repaymentAfterEvery).withNumberOfRepayments(numberOfRepayments)
.withEnableDownPayment(downPaymentEnabled, downPaymentPercentage, autoPayForDownPayment).withinterestRatePerPeriod("0")
.withInterestRateFrequencyTypeAsMonths()
.withRepaymentStrategy(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
.withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts)
.addAdvancedPaymentAllocation(defaultAllocation, goodwillCreditAllocation, merchantIssuedRefundAllocation,
payoutRefundAllocation)
.withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withInterestTypeAsDecliningBalance().withMultiDisburse()
.withDisallowExpectedDisbursements(true).withLoanScheduleType(loanScheduleType)
.withLoanScheduleProcessingType(loanScheduleProcessingType).withDaysInMonth("30").withDaysInYear("365")
.withMoratorium("0", "0").build(null);
return loanTransactionHelper.getLoanProductId(loanProductJSON);
}
private static void validatePeriod(GetLoansLoanIdResponse loanDetails, Integer index, LocalDate dueDate, LocalDate paidDate,
Double balanceOfLoan, Double principalDue, Double principalPaid, Double principalOutstanding, Double feeDue, Double feePaid,
Double feeOutstanding, Double penaltyDue, Double penaltyPaid, Double penaltyOutstanding, Double interestDue,
Double interestPaid, Double interestOutstanding, Double paidInAdvance, Double paidLate) {
GetLoansLoanIdRepaymentPeriod period = loanDetails.getRepaymentSchedule().getPeriods().get(index);
assertEquals(dueDate, period.getDueDate());
assertEquals(paidDate, period.getObligationsMetOnDate());
assertEquals(balanceOfLoan, period.getPrincipalLoanBalanceOutstanding());
assertEquals(principalDue, period.getPrincipalDue());
assertEquals(principalPaid, period.getPrincipalPaid());
assertEquals(principalOutstanding, period.getPrincipalOutstanding());
assertEquals(feeDue, period.getFeeChargesDue());
assertEquals(feePaid, period.getFeeChargesPaid());
assertEquals(feeOutstanding, period.getFeeChargesOutstanding());
assertEquals(penaltyDue, period.getPenaltyChargesDue());
assertEquals(penaltyPaid, period.getPenaltyChargesPaid());
assertEquals(penaltyOutstanding, period.getPenaltyChargesOutstanding());
assertEquals(interestDue, period.getInterestDue());
assertEquals(interestPaid, period.getInterestPaid());
assertEquals(interestOutstanding, period.getInterestOutstanding());
assertEquals(paidInAdvance, period.getTotalPaidInAdvanceForPeriod());
assertEquals(paidLate, period.getTotalPaidLateForPeriod());
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate, String transactionProcessorCode,
String loanScheduleProcessingType) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
return loanTransactionHelper.applyLoan(new PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
.expectedDisbursementDate(expectedDisbursementDate).dateFormat(DATETIME_PATTERN)
.transactionProcessingStrategyCode(transactionProcessorCode).locale("en").submittedOnDate(submittedOnDate)
.amortizationType(1).interestRatePerPeriod(interestRate).interestCalculationPeriodType(1).interestType(0)
.repaymentFrequencyType(0).repaymentEvery(repaymentAfterEvery).repaymentFrequencyType(0)
.numberOfRepayments(numberOfRepayments).loanTermFrequency(loanTermFrequency).loanTermFrequencyType(0).principal(principal)
.loanType("individual").loanScheduleProcessingType(loanScheduleProcessingType)
.maxOutstandingLoanBalance(BigDecimal.valueOf(35000)));
}
private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
final String expectedDisbursementDate, final String submittedOnDate) {
LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
return applyForLoanApplication(clientId, loanProductId, principal, loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
interestRate, expectedDisbursementDate, submittedOnDate,
AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY,
LoanScheduleProcessingType.HORIZONTAL.name());
}
private static void validateLoanTransaction(GetLoansLoanIdResponse loanDetails, int index, double transactionAmount,
double principalPortion, double overPaidPortion, double loanBalance) {
assertEquals(transactionAmount, loanDetails.getTransactions().get(index).getAmount());
assertEquals(principalPortion, loanDetails.getTransactions().get(index).getPrincipalPortion());
assertEquals(overPaidPortion, loanDetails.getTransactions().get(index).getOverpaymentPortion());
assertEquals(loanBalance, loanDetails.getTransactions().get(index).getOutstandingLoanBalance());
}
private void validateLoanCharge(GetLoansLoanIdResponse loanDetails, int index, LocalDate dueDate, double charged, double paid,
double outstanding) {
GetLoansLoanIdLoanChargeData chargeData = loanDetails.getCharges().get(index);
assertEquals(dueDate, chargeData.getDueDate());
assertEquals(charged, chargeData.getAmount());
assertEquals(paid, chargeData.getAmountPaid());
assertEquals(outstanding, chargeData.getAmountOutstanding());
}
}