This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 389a1f15b FINERACT-1971: Downpayment repayment undo (#3512)
389a1f15b is described below

commit 389a1f15b277042025346b3f9a14c839cb4ab8a9
Author: taskain7 <[email protected]>
AuthorDate: Mon Oct 16 14:11:06 2023 +0200

    FINERACT-1971: Downpayment repayment undo (#3512)
    
    [FINERACT-1971] Downpayment repayment undo
---
 ...dvancedPaymentScheduleTransactionProcessor.java |   4 +-
 ...ndoRepaymentWithDownPaymentIntegrationTest.java | 388 +++++++++++++++++++++
 2 files changed, 390 insertions(+), 2 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index d51a8fb2f..72b46c601 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -116,7 +116,7 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
         final ChangedTransactionDetail changedTransactionDetail = new 
ChangedTransactionDetail();
         for (final LoanTransaction loanTransaction : 
transactionsPostDisbursement) {
             if (loanTransaction.getId() == null) {
-                processLatestTransaction(loanTransaction, currency, 
installments, charges, null);
+                processLatestTransaction(loanTransaction, currency, 
installments, charges, Money.zero(currency));
                 loanTransaction.adjustInterestComponent(currency);
             } else {
                 /**
@@ -127,7 +127,7 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
 
                 // Reset derived component of new loan transaction and
                 // re-process transaction
-                processLatestTransaction(newLoanTransaction, currency, 
installments, charges, null);
+                processLatestTransaction(newLoanTransaction, currency, 
installments, charges, Money.zero(currency));
                 newLoanTransaction.adjustInterestComponent(currency);
                 /**
                  * Check if the transaction amounts have changed. If so, 
reverse the original transaction and update
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoRepaymentWithDownPaymentIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoRepaymentWithDownPaymentIntegrationTest.java
new file mode 100644
index 000000000..0502db9a6
--- /dev/null
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoRepaymentWithDownPaymentIntegrationTest.java
@@ -0,0 +1,388 @@
+/**
+ * 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 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.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.fineract.client.models.AdvancedPaymentData;
+import org.apache.fineract.client.models.AllowAttributeOverrides;
+import org.apache.fineract.client.models.ChargeData;
+import org.apache.fineract.client.models.ChargeToGLAccountMapper;
+import org.apache.fineract.client.models.GetLoanFeeToIncomeAccountMappings;
+import 
org.apache.fineract.client.models.GetLoanPaymentChannelToFundSourceMappings;
+import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
+import org.apache.fineract.client.models.GetLoansLoanIdResponse;
+import org.apache.fineract.client.models.PaymentAllocationOrder;
+import org.apache.fineract.client.models.PostLoanProductsRequest;
+import org.apache.fineract.client.models.PostLoanProductsResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
+import 
org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
+import org.apache.fineract.client.models.PostPaymentTypesRequest;
+import org.apache.fineract.client.models.PostPaymentTypesResponse;
+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.GlobalConfigurationHelper;
+import org.apache.fineract.integrationtests.common.PaymentTypeHelper;
+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.accounting.JournalEntryHelper;
+import org.apache.fineract.integrationtests.common.funds.FundsHelper;
+import org.apache.fineract.integrationtests.common.funds.FundsResourceHandler;
+import 
org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
+import org.apache.fineract.integrationtests.common.loans.LoanProductHelper;
+import 
org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import 
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(LoanTestLifecycleExtension.class)
+public class UndoRepaymentWithDownPaymentIntegrationTest {
+
+    private static final DateTimeFormatter DATE_FORMATTER = new 
DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+    private ClientHelper clientHelper;
+    private LoanTransactionHelper loanTransactionHelper;
+    private JournalEntryHelper journalEntryHelper;
+    private AccountHelper accountHelper;
+    private LoanProductHelper loanProductHelper;
+    private PaymentTypeHelper paymentTypeHelper;
+    // asset
+    private Account loansReceivable;
+    private Account interestFeeReceivable;
+    private Account suspenseAccount;
+    private Account fundReceivables;
+    // liability
+    private Account suspenseClearingAccount;
+    private Account overpaymentAccount;
+    // income
+    private Account interestIncome;
+    private Account feeIncome;
+    private Account feeChargeOff;
+    private Account recoveries;
+    private Account interestIncomeChargeOff;
+    // expense
+    private Account creditLossBadDebt;
+    private Account creditLossBadDebtFraud;
+    private Account writtenOff;
+    private Account goodwillExpenseAccount;
+
+    @BeforeEach
+    public void setup() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new 
RequestSpecBuilder().setContentType(ContentType.JSON).build();
+        this.requestSpec.header("Authorization", "Basic " + 
Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new 
ResponseSpecBuilder().expectStatusCode(200).build();
+        this.loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+        this.accountHelper = new AccountHelper(this.requestSpec, 
this.responseSpec);
+        this.loanProductHelper = new LoanProductHelper();
+        this.paymentTypeHelper = new PaymentTypeHelper();
+
+        // Asset
+        this.loansReceivable = this.accountHelper.createAssetAccount();
+        this.interestFeeReceivable = this.accountHelper.createAssetAccount();
+        this.suspenseAccount = this.accountHelper.createAssetAccount();
+        this.fundReceivables = this.accountHelper.createAssetAccount();
+
+        // Liability
+        this.suspenseClearingAccount = 
this.accountHelper.createLiabilityAccount();
+        this.overpaymentAccount = this.accountHelper.createLiabilityAccount();
+
+        // income
+        this.interestIncome = this.accountHelper.createIncomeAccount();
+        this.feeIncome = this.accountHelper.createIncomeAccount();
+        this.feeChargeOff = this.accountHelper.createIncomeAccount();
+        this.recoveries = this.accountHelper.createIncomeAccount();
+        this.interestIncomeChargeOff = 
this.accountHelper.createIncomeAccount();
+
+        // expense
+        this.creditLossBadDebt = this.accountHelper.createExpenseAccount();
+        this.creditLossBadDebtFraud = 
this.accountHelper.createExpenseAccount();
+        this.writtenOff = this.accountHelper.createExpenseAccount();
+        this.goodwillExpenseAccount = 
this.accountHelper.createExpenseAccount();
+
+        this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, 
this.responseSpec);
+        this.clientHelper = new ClientHelper(this.requestSpec, 
this.responseSpec);
+    }
+
+    @Test
+    public void undoRepaymentWithDownPaymentAndAdvancedPaymentAllocationTest() 
{
+        GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
+
+        String loanExternalIdStr = UUID.randomUUID().toString();
+
+        Boolean enableDownPayment = true;
+        BigDecimal disbursedAmountPercentageForDownPayment = 
BigDecimal.valueOf(25);
+        Boolean enableAutoRepaymentForDownPayment = true;
+
+        final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
+
+        Integer loanProductId = 
createLoanProductWithPeriodicAccrualAccountingAndAdvancedPaymentAllocationStrategy();
+
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
+        assertNotNull(getLoanProductsProductResponse);
+        assertEquals(enableDownPayment, 
getLoanProductsProductResponse.getEnableDownPayment());
+        assertEquals(0, 
getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment()
+                .compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment());
+
+        final Integer loanId = createApproveAndDisburseLoanAccount(clientId, 
loanProductId.longValue(), loanExternalIdStr, "1", "0");
+
+        GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId.longValue());
+
+        assertNotNull(loanDetails);
+        assertEquals(enableDownPayment, loanDetails.getEnableDownPayment());
+        assertEquals(0, 
loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
loanDetails.getEnableAutoRepaymentForDownPayment());
+
+        PostLoansLoanIdTransactionsResponse 
postLoansLoanIdTransactionsResponse = loanTransactionHelper
+                .makeLoanRepayment("05 September 2022", 500.0f, loanId);
+        Long repaymentTransactionId = 
postLoansLoanIdTransactionsResponse.getResourceId();
+
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 9, 25));
+        PostLoansLoanIdTransactionsResponse 
secondPostLoansLoanIdTransactionsResponse = loanTransactionHelper
+                .makeLoanRepayment("25 September 2022", 250.0f, loanId);
+        Long secondRepaymentId = 
secondPostLoansLoanIdTransactionsResponse.getResourceId();
+
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 9, 28));
+        loanTransactionHelper.chargebackLoanTransaction(loanExternalIdStr, 
secondRepaymentId,
+                new 
PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(100.0).paymentTypeId(1L));
+
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, LocalDate.of(2022, 9, 30));
+        loanTransactionHelper.makeLoanRepayment("30 September 2022", 100.0f, 
loanId);
+
+        PostLoansLoanIdTransactionsResponse 
postLoansLoanIdTransactionsResponse1 = 
loanTransactionHelper.reverseLoanTransaction(loanId,
+                repaymentTransactionId, "05 September 2022", responseSpec);
+
+        assertNotNull(postLoansLoanIdTransactionsResponse1);
+
+        loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue());
+        assertEquals(500, loanDetails.getSummary().getTotalOutstanding());
+    }
+
+    private Integer 
createLoanProductWithPeriodicAccrualAccountingAndAdvancedPaymentAllocationStrategy()
 {
+
+        String name = Utils.uniqueRandomStringGenerator("LOAN_PRODUCT_", 6);
+        String shortName = Utils.uniqueRandomStringGenerator("", 4);
+
+        List<Integer> principalVariationsForBorrowerCycle = new ArrayList<>();
+        List<Integer> numberOfRepaymentVariationsForBorrowerCycle = new 
ArrayList<>();
+        List<Integer> interestRateVariationsForBorrowerCycle = new 
ArrayList<>();
+        List<ChargeData> charges = new ArrayList<>();
+        List<ChargeToGLAccountMapper> penaltyToIncomeAccountMappings = new 
ArrayList<>();
+        List<GetLoanFeeToIncomeAccountMappings> feeToIncomeAccountMappings = 
new ArrayList<>();
+
+        String paymentTypeName = PaymentTypeHelper.randomNameGenerator("P_T", 
5);
+        String description = PaymentTypeHelper.randomNameGenerator("PT_Desc", 
15);
+        Boolean isCashPayment = false;
+        Integer position = 1;
+
+        PostPaymentTypesResponse paymentTypesResponse = 
paymentTypeHelper.createPaymentType(new PostPaymentTypesRequest()
+                
.name(paymentTypeName).description(description).isCashPayment(isCashPayment).position(position));
+        Long paymentTypeIdOne = paymentTypesResponse.getResourceId();
+        Assertions.assertNotNull(paymentTypeIdOne);
+
+        List<GetLoanPaymentChannelToFundSourceMappings> 
paymentChannelToFundSourceMappings = new ArrayList<>();
+        GetLoanPaymentChannelToFundSourceMappings 
loanPaymentChannelToFundSourceMappings = new 
GetLoanPaymentChannelToFundSourceMappings();
+        
loanPaymentChannelToFundSourceMappings.fundSourceAccountId(fundReceivables.getAccountID().longValue());
+        
loanPaymentChannelToFundSourceMappings.paymentTypeId(paymentTypeIdOne.longValue());
+        
paymentChannelToFundSourceMappings.add(loanPaymentChannelToFundSourceMappings);
+
+        // fund
+        FundsHelper fh = 
FundsHelper.create(Utils.uniqueRandomStringGenerator("", 
10)).externalId(UUID.randomUUID().toString()).build();
+        String jsonData = fh.toJSON();
+
+        final Long fundID = createFund(jsonData, this.requestSpec, 
this.responseSpec);
+        Assertions.assertNotNull(fundID);
+
+        // Delinquency Bucket
+        final Integer delinquencyBucketId = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
+
+        String futureInstallmentAllocationRule = "NEXT_INSTALLMENT";
+        AdvancedPaymentData defaultAllocation = 
createDefaultPaymentAllocation(futureInstallmentAllocationRule);
+
+        PostLoanProductsRequest loanProductsRequest = new 
PostLoanProductsRequest().name(name)//
+                .shortName(shortName)//
+                .description("Loan Product Description")//
+                .fundId(fundID)//
+                .startDate(null)//
+                .closeDate(null)//
+                .includeInBorrowerCycle(false)//
+                .currencyCode("USD")//
+                .digitsAfterDecimal(2)//
+                .inMultiplesOf(0)//
+                .installmentAmountInMultiplesOf(1)//
+                .useBorrowerCycle(false)//
+                .minPrincipal(100.0)//
+                .principal(1000.0)//
+                .maxPrincipal(10000.0)//
+                .minNumberOfRepayments(1)//
+                .numberOfRepayments(1)//
+                .maxNumberOfRepayments(30)//
+                .isLinkedToFloatingInterestRates(false)//
+                .minInterestRatePerPeriod((double) 0)//
+                .interestRatePerPeriod((double) 0)//
+                .maxInterestRatePerPeriod((double) 0)//
+                .interestRateFrequencyType(2)//
+                .repaymentEvery(30)//
+                .repaymentFrequencyType(0)//
+                
.principalVariationsForBorrowerCycle(principalVariationsForBorrowerCycle)//
+                
.numberOfRepaymentVariationsForBorrowerCycle(numberOfRepaymentVariationsForBorrowerCycle)//
+                
.interestRateVariationsForBorrowerCycle(interestRateVariationsForBorrowerCycle)//
+                .amortizationType(1)//
+                .interestType(0)//
+                .isEqualAmortization(false)//
+                .interestCalculationPeriodType(1)//
+                
.transactionProcessingStrategyCode("advanced-payment-allocation-strategy")//
+                .addPaymentAllocationItem(defaultAllocation)//
+                .daysInYearType(1)//
+                .daysInMonthType(1)//
+                .canDefineInstallmentAmount(true)//
+                .graceOnArrearsAgeing(3)//
+                .overdueDaysForNPA(179)//
+                .accountMovesOutOfNPAOnlyOnArrearsCompletion(false)//
+                .principalThresholdForLastInstallment(50)//
+                .allowVariableInstallments(false)//
+                .canUseForTopup(false)//
+                .isInterestRecalculationEnabled(false)//
+                
.enableDownPayment(true).enableAutoRepaymentForDownPayment(true)
+                
.disbursedAmountPercentageForDownPayment(BigDecimal.valueOf(25)).holdGuaranteeFunds(false)//
+                .multiDisburseLoan(true)//
+                .allowAttributeOverrides(new AllowAttributeOverrides()//
+                        .amortizationType(true)//
+                        .interestType(true)//
+                        .transactionProcessingStrategyCode(true)//
+                        .interestCalculationPeriodType(true)//
+                        .inArrearsTolerance(true)//
+                        .repaymentEvery(true)//
+                        .graceOnPrincipalAndInterestPayment(true)//
+                        .graceOnArrearsAgeing(true))//
+                .allowPartialPeriodInterestCalcualtion(true)//
+                .maxTrancheCount(10)//
+                .outstandingLoanBalance(10000.0)//
+                .charges(charges)//
+                .accountingRule(3)//
+                
.fundSourceAccountId(suspenseClearingAccount.getAccountID().longValue())//
+                
.loanPortfolioAccountId(loansReceivable.getAccountID().longValue())//
+                
.transfersInSuspenseAccountId(suspenseAccount.getAccountID().longValue())//
+                
.interestOnLoanAccountId(interestIncome.getAccountID().longValue())//
+                .incomeFromFeeAccountId(feeIncome.getAccountID().longValue())//
+                
.incomeFromPenaltyAccountId(feeIncome.getAccountID().longValue())//
+                
.incomeFromRecoveryAccountId(recoveries.getAccountID().longValue())//
+                .writeOffAccountId(writtenOff.getAccountID().longValue())//
+                
.overpaymentLiabilityAccountId(overpaymentAccount.getAccountID().longValue())//
+                
.receivableInterestAccountId(interestFeeReceivable.getAccountID().longValue())//
+                
.receivableFeeAccountId(interestFeeReceivable.getAccountID().longValue())//
+                
.receivablePenaltyAccountId(interestFeeReceivable.getAccountID().longValue())//
+                .dateFormat("dd MMMM yyyy")//
+                .locale("en_GB")//
+                .disallowExpectedDisbursements(true)//
+                .allowApprovedDisbursedAmountsOverApplied(true)//
+                .overAppliedCalculationType("percentage")//
+                .overAppliedNumber(50)//
+                .delinquencyBucketId(delinquencyBucketId.longValue())//
+                
.goodwillCreditAccountId(goodwillExpenseAccount.getAccountID().longValue())//
+                
.incomeFromGoodwillCreditInterestAccountId(interestIncomeChargeOff.getAccountID().longValue())//
+                
.incomeFromGoodwillCreditFeesAccountId(feeChargeOff.getAccountID().longValue())//
+                
.incomeFromGoodwillCreditPenaltyAccountId(feeChargeOff.getAccountID().longValue())//
+                
.paymentChannelToFundSourceMappings(paymentChannelToFundSourceMappings)//
+                
.penaltyToIncomeAccountMappings(penaltyToIncomeAccountMappings)//
+                .feeToIncomeAccountMappings(feeToIncomeAccountMappings)//
+                
.incomeFromChargeOffInterestAccountId(interestIncomeChargeOff.getAccountID().longValue())//
+                
.incomeFromChargeOffFeesAccountId(feeChargeOff.getAccountID().longValue())//
+                
.chargeOffExpenseAccountId(creditLossBadDebt.getAccountID().longValue())//
+                
.chargeOffFraudExpenseAccountId(creditLossBadDebtFraud.getAccountID().longValue())//
+                
.incomeFromChargeOffPenaltyAccountId(feeChargeOff.getAccountID().longValue());//
+
+        PostLoanProductsResponse loanProductCreateResponse = 
loanProductHelper.createLoanProduct(loanProductsRequest);
+        return loanProductCreateResponse.getResourceId().intValue();
+    }
+
+    private Integer createApproveAndDisburseLoanAccount(final Integer 
clientID, final Long loanProductID, final String externalId,
+            final String numberOfRepayments, final String interestRate) {
+
+        String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency(numberOfRepayments)
+                
.withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments).withRepaymentEveryAfter("1")
+                
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod(interestRate).withInterestTypeAsFlatBalance()
+                
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
+                .withExpectedDisbursementDate("03 September 
2022").withSubmittedOnDate("01 September 2022").withLoanType("individual")
+                .withExternalId(externalId).build(clientID.toString(), 
loanProductID.toString(), null);
+
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan("02 September 2022", "1000", loanId, 
null);
+        loanTransactionHelper.disburseLoanWithTransactionAmount("03 September 
2022", loanId, "1000");
+        return loanId;
+    }
+
+    private Long createFund(final String fundJSON, final RequestSpecification 
requestSpec, final ResponseSpecification responseSpec) {
+        String fundId = 
String.valueOf(FundsResourceHandler.createFund(fundJSON, requestSpec, 
responseSpec));
+        if (fundId.equals("null")) {
+            // Invalid JSON data parameters
+            return null;
+        }
+
+        return Long.valueOf(fundId);
+    }
+
+    private AdvancedPaymentData createDefaultPaymentAllocation(String 
futureInstallmentAllocationRule) {
+        AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+        advancedPaymentData.setTransactionType("DEFAULT");
+        
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 List<PaymentAllocationOrder> 
getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+        AtomicInteger integer = new AtomicInteger(1);
+        return Arrays.stream(paymentAllocationTypes).map(pat -> {
+            PaymentAllocationOrder paymentAllocationOrder = new 
PaymentAllocationOrder();
+            paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+            paymentAllocationOrder.setOrder(integer.getAndIncrement());
+            return paymentAllocationOrder;
+        }).toList();
+    }
+}

Reply via email to