diff --git a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature index ae216afe6..57207a85e 100644 --- a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature +++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature @@ -3586,7 +3586,7 @@ Feature: Charge-off And Global configuration "is-principal-compounding-disabled-for-overdue-loans" is disabled @Skip @TestRailId:C3360 @AdvancedPaymentAllocation - Scenario: Verify accelerate maturity to charge-off date when interest recalculation is enabled - case when charge-off occurs with adjustment to last installment + Scenario: SKIPPED-Verify accelerate maturity to charge-off date when interest recalculation is enabled - case when charge-off occurs with adjustment to last installment When Admin sets the business date to "01 January 2024" When Admin creates a client with random data When Admin creates a fully customized loan with the following data: diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java index 49df1228c..f7c135710 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java @@ -2250,6 +2250,7 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep lastPeriod.setEmi(lastPeriod.getDuePrincipal().add(totalPrincipal).add(newInterest)); emiCalculator.calculateRateFactorForRepaymentPeriod(lastPeriod, transactionCtx.getModel()); + transactionCtx.getModel().disableEMIRecalculation(); for (LoanTransaction processTransaction : transactionsToBeReprocessed) { emiCalculator.addBalanceCorrection(transactionCtx.getModel(), processTransaction.getTransactionDate(), diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java index a48cd7de3..c941569e7 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java @@ -182,20 +182,25 @@ public final class ProgressiveEMICalculator implements EMICalculator { return; } Optional repaymentPeriod = findRepaymentPeriod(scheduleModel, repaymentPeriodDueDate); + boolean transactionDateIsBefore = transactionDate.isBefore(repaymentPeriod.get().getFromDate()); repaymentPeriod.ifPresent(rp -> rp.addPaidPrincipalAmount(principalAmount)); // If it is paid late, we need to calculate with the period due date LocalDate balanceCorrectionDate = DateUtils.isBefore(repaymentPeriodDueDate, transactionDate) ? repaymentPeriodDueDate : transactionDate; addBalanceCorrection(scheduleModel, balanceCorrectionDate, principalAmount.negated()); - - repaymentPeriod.ifPresent(rp -> { - // If any period total paid > calculated EMI, then set EMI to total paid -> effectively it is marked as - // fully paid - if (rp.getTotalPaidAmount().isGreaterThan(rp.getEmiPlusChargeback())) { - rp.setEmi(rp.getTotalPaidAmount().minus(rp.getTotalChargebackAmount())); + if (scheduleModel.isEMIRecalculationEnabled()) { + repaymentPeriod.ifPresent(rp -> { + // If any period total paid > calculated EMI, then set EMI to total paid -> effectively it is marked as + // fully paid + if (transactionDateIsBefore && rp.getTotalPaidAmount().isGreaterThan(rp.getEmiPlusChargeback())) { + rp.setEmi(rp.getTotalPaidAmount().minus(rp.getTotalChargebackAmount())); + } else if (transactionDateIsBefore + && rp.getTotalPaidAmount().isEqualTo(rp.getOriginalEmi().add(rp.getTotalChargebackAmount()))) { + rp.setEmi(rp.getTotalPaidAmount().minus(rp.getTotalChargebackAmount())); + } calculateLastUnpaidRepaymentPeriodEMI(scheduleModel); - } - }); + }); + } } private void addChargebackAmountsToInterestPeriod(ProgressiveLoanInterestScheduleModel scheduleModel, LocalDate transactionDate, @@ -357,7 +362,6 @@ public final class ProgressiveEMICalculator implements EMICalculator { interestPeriod.addChargebackPrincipalAmount(nextInterestPeriod.getChargebackPrincipal()); interestPeriod.addChargebackInterestAmount(nextInterestPeriod.getChargebackInterest()); } - repaymentPeriod.getInterestPeriods().subList(nextIdx, repaymentPeriod.getInterestPeriods().size()).clear(); scheduleModelCopy.repaymentPeriods().forEach(rp -> rp.getInterestPeriods().removeIf(ip -> ip.getDueDate().isAfter(targetDate))); calculateRateFactorForPeriods(scheduleModelCopy.repaymentPeriods(), scheduleModelCopy); @@ -374,7 +378,7 @@ public final class ProgressiveEMICalculator implements EMICalculator { final ProgressiveLoanInterestScheduleModel scheduleModel, final EmiChangeOperation operation) { final List relatedRepaymentPeriods = scheduleModel.getRelatedRepaymentPeriods(calculateFromRepaymentPeriodDueDate); final boolean onlyOnActualModelShouldApply = scheduleModel.isEmpty() - || operation.getAction() == EmiChangeOperation.Action.INTEREST_RATE_CHANGE || scheduleModel.isCopiedForCalculation(); + || operation.getAction() == EmiChangeOperation.Action.INTEREST_RATE_CHANGE || scheduleModel.isCopy(); calculateRateFactorForPeriods(relatedRepaymentPeriods, scheduleModel); calculateOutstandingBalance(scheduleModel); diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java new file mode 100644 index 000000000..e275ac918 --- /dev/null +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/LoanInterestScheduleModelModifiers.java @@ -0,0 +1,23 @@ +/** + * 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.portfolio.loanproduct.calc.data; + +public enum LoanInterestScheduleModelModifiers { + EMI_RECALCULATION, COPY, +} diff --git a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java index 279d624ed..7dfa1e075 100644 --- a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java +++ b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/data/ProgressiveLoanInterestScheduleModel.java @@ -19,6 +19,8 @@ package org.apache.fineract.portfolio.loanproduct.calc.data; import static org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleProcessingWrapper.isInPeriod; +import static org.apache.fineract.portfolio.loanproduct.calc.data.LoanInterestScheduleModelModifiers.COPY; +import static org.apache.fineract.portfolio.loanproduct.calc.data.LoanInterestScheduleModelModifiers.EMI_RECALCULATION; import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; @@ -56,7 +58,7 @@ public class ProgressiveLoanInterestScheduleModel { private final Integer installmentAmountInMultiplesOf; private final MathContext mc; private final Money zero; - private final boolean isCopiedForCalculation; + private final Map modifiers; public ProgressiveLoanInterestScheduleModel(final List repaymentPeriods, final LoanProductMinimumRepaymentScheduleRelatedDetail loanProductRelatedDetail, @@ -68,7 +70,7 @@ public class ProgressiveLoanInterestScheduleModel { this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.mc = mc; this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc); - this.isCopiedForCalculation = false; + modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, false)); } private ProgressiveLoanInterestScheduleModel(final List repaymentPeriods, final TreeSet interestRates, @@ -83,7 +85,7 @@ public class ProgressiveLoanInterestScheduleModel { this.loanTermVariations = loanTermVariations; this.installmentAmountInMultiplesOf = installmentAmountInMultiplesOf; this.zero = Money.zero(loanProductRelatedDetail.getCurrencyData(), mc); - this.isCopiedForCalculation = isCopiedForCalculation; + modifiers = new HashMap<>(Map.of(EMI_RECALCULATION, true, COPY, isCopiedForCalculation)); } public ProgressiveLoanInterestScheduleModel deepCopy(MathContext mc) { @@ -405,4 +407,16 @@ public class ProgressiveLoanInterestScheduleModel { return loanTermVariationsData.stream() .collect(Collectors.groupingBy(ltvd -> LoanTermVariationType.fromInt(ltvd.getTermType().getId().intValue()))); } + + public void disableEMIRecalculation() { + this.modifiers.put(EMI_RECALCULATION, false); + } + + public boolean isEMIRecalculationEnabled() { + return this.modifiers.get(EMI_RECALCULATION); + } + + public boolean isCopy() { + return this.modifiers.get(COPY); + } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java index 8b5448f10..f1d3f15fc 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java @@ -767,6 +767,7 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest { } protected void verifyTRJournalEntries(Long transactionId, Journal... entries) { + Assertions.assertNotNull(transactionId, "transactionId is null"); GetJournalEntriesTransactionIdResponse journalEntriesForLoan = journalEntryHelper.getJournalEntries("L" + transactionId.toString()); Assertions.assertEquals(entries.length, journalEntriesForLoan.getPageItems().size()); Arrays.stream(entries).forEach(journalEntry -> { @@ -1425,6 +1426,8 @@ public abstract class BaseLoanIntegrationTest extends IntegrationTest { public static class FuturePaymentAllocationRule { public static final String LAST_INSTALLMENT = "LAST_INSTALLMENT"; + public static final String NEXT_INSTALLMENT = "NEXT_INSTALLMENT"; + } public static class SupportedInterestRefundTypesItem { diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRefundTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRefundTest.java index 4f1f91e28..a39b2bd58 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRefundTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestRefundTest.java @@ -29,16 +29,16 @@ import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; import java.math.BigDecimal; -import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.client.models.AdvancedPaymentData; import org.apache.fineract.client.models.GetLoansLoanIdResponse; import org.apache.fineract.client.models.GetLoansLoanIdTransactions; import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse; +import org.apache.fineract.client.models.PaymentAllocationOrder; import org.apache.fineract.client.models.PostClientsResponse; import org.apache.fineract.client.models.PostLoanProductsResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; @@ -48,6 +48,7 @@ import org.apache.fineract.integrationtests.common.BusinessStepHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; +import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -90,12 +91,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), transaction(1000.0, "Payout Refund", "22 January 2021")); }); @@ -118,12 +118,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), transaction(1000.0, "Merchant Issued Refund", "22 January 2021")); }); @@ -143,8 +142,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { 6, null); Assertions.assertNotNull(loanId); disburseLoan(loanId, BigDecimal.valueOf(600), "1 January 2021"); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 600F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "1 January 2021", 600.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); @@ -177,8 +176,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { Assertions.assertNotNull(loanId); disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021"); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 980F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "1 January 2021", 980.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); @@ -218,8 +217,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { Assertions.assertNotNull(loanId); disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021"); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "1 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); @@ -261,12 +260,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, // transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Payout Refund", "22 January 2021"), // @@ -319,12 +317,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Merchant Issued Refund", "22 January 2021"), // transaction(5.75, "Accrual", "22 January 2021"), // @@ -351,8 +348,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); @@ -391,8 +388,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { 12, null); Assertions.assertNotNull(loanId); disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021"); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "MerchantIssuedRefund", "1 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); @@ -429,8 +426,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { 12, null); Assertions.assertNotNull(loanId); disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021"); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment("Repayment", - "1 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "Repayment", "1 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); @@ -473,12 +470,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Payout Refund", "22 January 2021"), // transaction(5.75, "Accrual", "22 January 2021"), // @@ -506,12 +502,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "1 February 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "1 February 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Payout Refund", "01 February 2021"), // transaction(8.48, "Accrual", "01 February 2021"), // @@ -538,24 +533,22 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment("Repayment", - "1 February 2021", 87.89F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "Repayment", "1 February 2021", 87.89); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), transaction(87.89, "Repayment", "01 February 2021")); }); runAt("9 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "9 February 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "9 February 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(87.89, "Repayment", "01 February 2021"), // transaction(1000.0, "Payout Refund", "09 February 2021"), // @@ -588,12 +581,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(750.0, "Disbursement", "01 January 2021"), // transaction(250.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Payout Refund", "22 January 2021"), // @@ -627,12 +619,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(750.0, "Disbursement", "04 January 2021"), // transaction(250.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Payout Refund", "22 January 2021"), // @@ -667,24 +658,22 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment("Repayment", - "1 February 2021", 87.82F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "Repayment", "1 February 2021", 87.82); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), transaction(500.0, "Disbursement", "07 January 2021"), transaction(87.82, "Repayment", "01 February 2021")); }); runAt("9 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "9 February 2021", 1000F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "9 February 2021", 1000.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "07 January 2021"), // transaction(1000.0, "Payout Refund", "09 February 2021"), // @@ -715,12 +704,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("14 December 2020", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "14 December 2020", 500F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "14 December 2020", 500.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 December 2020"), // transaction(500.0, "Payout Refund", "14 December 2020"), // transaction(1.78, "Interest Refund", "14 December 2020")); @@ -743,29 +731,24 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { Assertions.assertNotNull(loanId); loanIdRef.set(loanId); disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021"); - - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId); - logInstallmentsOfLoanDetails(loanDetails); }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment("Repayment", - "1 February 2021", 87.89F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "Repayment", "1 February 2021", 87.89); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(87.89, "Repayment", "01 February 2021")); }); runAt("9 February 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "09 February 2021", 500F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "09 February 2021", 500.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(87.89, "Repayment", "01 February 2021"), // transaction(500.0, "Payout Refund", "09 February 2021"), // @@ -795,12 +778,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 500F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 500.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Payout Refund", "22 January 2021"), // @@ -832,12 +814,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "22 January 2021", 500F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "22 January 2021", 500.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "07 January 2021"), // transaction(500.0, "Payout Refund", "22 January 2021"), // @@ -867,20 +848,16 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { runAt("7 January 2021", () -> { Long loanId = loanIdRef.get(); disburseLoan(loanId, BigDecimal.valueOf(750), "7 January 2021"); - - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId); - logInstallmentsOfLoanDetails(loanDetails); }); runAt("1 July 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 171.29F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 March 2021", 171.29F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 April 2021", 171.29F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 May 2021", 171.29F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 June 2021", 171.29F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 July 2021", 171.32F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 171.29); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 March 2021", 171.29); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 April 2021", 171.29); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 May 2021", 171.29); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 June 2021", 171.29); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 July 2021", 171.32); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "07 January 2021"), // transaction(171.29, "Repayment", "01 February 2021"), // @@ -894,12 +871,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("11 July 2021", () -> { Long loanId = loanIdRef.get(); - PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper - .makeLoanRepayment("PayoutRefund", "11 July 2021", 500.0F, loanId.intValue()); + PostLoansLoanIdTransactionsResponse postLoansLoanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(loanId, + "PayoutRefund", "11 July 2021", 500.0); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse); Assertions.assertNotNull(postLoansLoanIdTransactionsResponse.getResourceId()); - logLoanTransactions(loanId); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "07 January 2021"), // transaction(171.29, "Repayment", "01 February 2021"), // @@ -935,7 +911,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("14 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "14 January 2021", 500F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "14 January 2021", 500.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Merchant Issued Refund", "14 January 2021"), // @@ -943,8 +919,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "22 January 2021", 500F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "22 January 2021", 500.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Merchant Issued Refund", "14 January 2021"), // transaction(1.78, "Interest Refund", "14 January 2021"), // @@ -975,14 +950,14 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 171.50F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 171.50); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(171.5, "Repayment", "01 February 2021")); }); runAt("9 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "9 February 2021", 500F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "9 February 2021", 500.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(171.5, "Repayment", "01 February 2021"), // @@ -991,7 +966,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("25 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "25 February 2021", 250F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "25 February 2021", 250.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(171.5, "Repayment", "01 February 2021"), // @@ -1026,7 +1001,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 500F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "22 January 2021", 500.0); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "01 January 2021"), // @@ -1036,7 +1011,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("26 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "26 January 2021", 400F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "26 January 2021", 400.0); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "01 January 2021"), // @@ -1048,7 +1023,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 100.84F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 100.84); verifyTransactions(loanId, transaction(250.0, "Disbursement", "01 January 2021"), // transaction(750.0, "Disbursement", "01 January 2021"), // @@ -1093,7 +1068,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 250F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "22 January 2021", 250.0); verifyTransactions(loanId, transaction(200.0, "Disbursement", "01 January 2021"), // transaction(300.0, "Disbursement", "01 January 2021"), // @@ -1104,8 +1079,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("26 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "26 January 2021", 400F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "26 January 2021", 400.0); verifyTransactions(loanId, transaction(200.0, "Disbursement", "01 January 2021"), // transaction(300.0, "Disbursement", "01 January 2021"), // @@ -1118,9 +1092,9 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 April 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 171.41F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 March 2021", 171.41F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 April 2021", 11.24F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 171.41); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 March 2021", 171.41); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 April 2021", 11.24); verifyTransactions(loanId, transaction(200.0, "Disbursement", "01 January 2021"), // transaction(300.0, "Disbursement", "01 January 2021"), // @@ -1168,7 +1142,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 171.41F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 171.41); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "05 January 2021"), // @@ -1176,7 +1150,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("13 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "13 February 2021", 250F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "13 February 2021", 250.0); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "05 January 2021"), // @@ -1187,8 +1161,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("24 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "24 February 2021", 400F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "24 February 2021", 400.0); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "05 January 2021"), // @@ -1201,8 +1174,8 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 April 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 March 2021", 171.41F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 April 2021", 11.25F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 March 2021", 171.41); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 April 2021", 11.25); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId); Assertions.assertNotNull(loanDetails); @@ -1237,7 +1210,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 171.41F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 171.41); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "05 January 2021"), // @@ -1245,7 +1218,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("13 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "13 February 2021", 250F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "13 February 2021", 250.0); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "05 January 2021"), // @@ -1257,13 +1230,12 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { runAt("1 April 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 March 2021", 171.41F, loanId.intValue()); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 April 2021", 171.41F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 March 2021", 171.41); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 April 2021", 171.41); }); runAt("6 April 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "6 April 2021", 400F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "6 April 2021", 400.0); verifyTransactions(loanId, transaction(500.0, "Disbursement", "01 January 2021"), // transaction(500.0, "Disbursement", "05 January 2021"), // @@ -1307,7 +1279,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("12 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "12 January 2021", 400F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "12 January 2021", 400.0); verifyTransactions(loanId, // transaction(1000.0, "Disbursement", "01 January 2021"), // @@ -1317,7 +1289,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "17 January 2021", 150F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "17 January 2021", 150.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(400.0, "Payout Refund", "12 January 2021"), // @@ -1329,12 +1301,11 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { runAt("1 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 February 2021", 171.5F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 February 2021", 171.5); }); runAt("8 February 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("PayoutRefund", "8 February 2021", 250F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "PayoutRefund", "8 February 2021", 250.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(400.0, "Payout Refund", "12 January 2021"), // @@ -1348,7 +1319,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("1 March 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("Repayment", "1 March 2021", 30.43F, loanId.intValue()); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "1 March 2021", 30.43); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId); Assertions.assertNotNull(loanDetails); Assertions.assertNotNull(loanDetails.getStatus()); @@ -1378,16 +1349,14 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 1000F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "22 January 2021", 1000.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Merchant Issued Refund", "22 January 2021"), // transaction(5.70, "Interest Refund", "22 January 2021"), // transaction(5.70, "Accrual", "22 January 2021") // ); - loanTransactionHelper.makeLoanRepayment("Repayment", "10 January 2021", 85.63F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "10 January 2021", 85.63); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(85.63, "Repayment", "10 January 2021"), // @@ -1417,14 +1386,12 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { Assertions.assertNotNull(loanId); disburseLoan(loanId, BigDecimal.valueOf(1000), "1 January 2021"); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "1 January 2021", 1000F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "1 January 2021", 1000.0); verifyTransactions(loanId, // transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(1000.0, "Merchant Issued Refund", "01 January 2021") // ); - logLoanTransactions(loanId); }); } @@ -1450,8 +1417,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("10 January 2021", () -> { Long loanId = loanIdRef.get(); - Long response = loanTransactionHelper.makeLoanRepayment("Repayment", "10 January 2021", 85.63F, loanId.intValue()) - .getResourceId(); + Long response = loanTransactionHelper.makeLoanRepayment(loanId, "Repayment", "10 January 2021", 85.63).getResourceId(); Assertions.assertNotNull(response); repaymentIdRef.set(response); @@ -1461,8 +1427,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 1000F, loanId.intValue()); - logLoanTransactions(loanId); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "22 January 2021", 1000.0); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // transaction(85.63, "Repayment", "10 January 2021"), // @@ -1472,8 +1437,7 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { ); Long repaymentId = repaymentIdRef.get(); - loanTransactionHelper.reverseLoanTransaction(loanId.intValue(), repaymentId, "10 January 2021", responseSpec); - logLoanTransactions(loanId); + loanTransactionHelper.reverseLoanTransaction(loanId, repaymentId, "10 January 2021"); verifyTransactions(loanId, transaction(1000.0, "Disbursement", "01 January 2021"), // reversedTransaction(85.63, "Repayment", "10 January 2021"), // @@ -1515,12 +1479,14 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { }); runAt("22 January 2021", () -> { Long loanId = loanIdRef.get(); - loanTransactionHelper.makeLoanRepayment("MerchantIssuedRefund", "22 January 2021", 1000F, loanId.intValue()); - logLoanTransactions(loanId); - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue()); - Optional optInterestRefundTransaction = loanDetails.getTransactions().stream() - .filter(item -> Objects.equals(item.getType().getValue(), "Interest Refund")).findFirst(); - final Long interestRefundTransactionId = optInterestRefundTransaction.get().getId(); + loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", "22 January 2021", 1000.0); + GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId); + Assertions.assertNotNull(loanDetails.getTransactions()); + Optional optInterestRefundTransaction = loanDetails.getTransactions().stream().filter(item -> { + Assertions.assertNotNull(item.getType()); + return Objects.equals(item.getType().getValue(), "Interest Refund"); + }).findFirst(); + final Long interestRefundTransactionId = optInterestRefundTransaction.orElseThrow().getId(); CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, () -> loanTransactionHelper.reverseLoanTransaction(loanId, interestRefundTransactionId, @@ -1531,36 +1497,81 @@ public class LoanInterestRefundTest extends BaseLoanIntegrationTest { Optional optMerchantIssuedTransaction = loanDetails.getTransactions().stream() .filter(item -> Objects.equals(item.getType().getValue(), "Merchant Issued Refund")).findFirst(); - final Long merchantIssuedTransactionId = optMerchantIssuedTransaction.get().getId(); + final Long merchantIssuedTransactionId = optMerchantIssuedTransaction.orElseThrow().getId(); loanTransactionHelper.reverseLoanTransaction(loanId, merchantIssuedTransactionId, new PostLoansLoanIdTransactionsTransactionIdRequest().dateFormat(DATETIME_PATTERN).transactionDate("22 January 2021") .transactionAmount(0.0).locale("en")); - loanDetails = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue()); + loanDetails = loanTransactionHelper.getLoanDetails(loanId); + Assertions.assertNotNull(loanDetails.getTransactions()); optInterestRefundTransaction = loanDetails.getTransactions().stream() .filter(item -> Objects.equals(item.getType().getValue(), "Interest Refund")).findFirst(); - assertEquals(Boolean.TRUE, optInterestRefundTransaction.get().getManuallyReversed()); + assertEquals(Boolean.TRUE, optInterestRefundTransaction.orElseThrow().getManuallyReversed()); }); } - private void logInstallmentsOfLoanDetails(GetLoansLoanIdResponse loanDetails) { - log.info("index, dueDate, principal, fee, penalty, interest"); - if (loanDetails != null && loanDetails.getRepaymentSchedule() != null && loanDetails.getRepaymentSchedule().getPeriods() != null) { - loanDetails.getRepaymentSchedule().getPeriods() - .forEach(period -> log.info("{}, \"{}\", {}, {}, {}, {}", period.getPeriod(), - DateTimeFormatter.ofPattern(DATETIME_PATTERN, Locale.ENGLISH) - .format(Objects.requireNonNull(period.getDueDate())), - period.getPrincipalDue(), period.getFeeChargesDue(), period.getPenaltyChargesDue(), period.getInterestDue())); - } + AdvancedPaymentData createPaymentAllocationInterestPrincipalPenaltyFee(String transactionType, String futureInstallmentAllocationRule) { + AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData(); + advancedPaymentData.setTransactionType(transactionType); + advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule); + + List paymentAllocationOrders = getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_INTEREST, + PaymentAllocationType.PAST_DUE_PRINCIPAL, PaymentAllocationType.PAST_DUE_PENALTY, PaymentAllocationType.PAST_DUE_FEE, + PaymentAllocationType.DUE_INTEREST, PaymentAllocationType.DUE_PRINCIPAL, PaymentAllocationType.DUE_PENALTY, + PaymentAllocationType.DUE_FEE, PaymentAllocationType.IN_ADVANCE_INTEREST, PaymentAllocationType.IN_ADVANCE_PRINCIPAL, + PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE); + + advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders); + return advancedPaymentData; } - private void logLoanTransactions(Long loanId) { - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue()); - if (loanDetails.getTransactions() != null) { - loanDetails.getTransactions() - .forEach(tr -> log.info("Transaction {} {} {} ", tr.getType().getValue(), tr.getDate(), tr.getAmount())); - } + private Long createLoanProduct() { + PostLoanProductsResponse loanProduct = loanProductHelper.createLoanProduct(create4IProgressive() // + .daysInMonthType(DaysInMonthType.ACTUAL) // + .daysInYearType(DaysInYearType.ACTUAL) // + .isInterestRecalculationEnabled(true) // + .addSupportedInterestRefundTypesItem(SupportedInterestRefundTypesItem.PAYOUT_REFUND) // + .addSupportedInterestRefundTypesItem(SupportedInterestRefundTypesItem.MERCHANT_ISSUED_REFUND) // + .recalculationRestFrequencyType(RecalculationRestFrequencyType.DAILY) // + .paymentAllocation(List.of(// + createPaymentAllocationInterestPrincipalPenaltyFee("DEFAULT", FuturePaymentAllocationRule.NEXT_INSTALLMENT), // + createPaymentAllocationInterestPrincipalPenaltyFee("PAYOUT_REFUND", FuturePaymentAllocationRule.LAST_INSTALLMENT), // + createPaymentAllocationInterestPrincipalPenaltyFee("MERCHANT_ISSUED_REFUND", + FuturePaymentAllocationRule.LAST_INSTALLMENT))) // + ); + Assertions.assertNotNull(loanProduct.getResourceId()); + return loanProduct.getResourceId(); } + private Long loanProductId = null; + + private Long getOrCreateLoanProduct() { + if (loanProductId == null) { + loanProductId = createLoanProduct(); + } + return loanProductId; + } + + @Test + public void verifyMerchantIssuedRefundPostingForBackdatedLoan() { + runAt("29 January 2025", () -> { + Long loanProductId = getOrCreateLoanProduct(); + Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProductId, "29 August 2024", 450.0, 26.0, 12, null); + Assertions.assertNotNull(loanId); + disburseLoan(loanId, BigDecimal.valueOf(450.0), "29 August 2024"); + + PostLoansLoanIdTransactionsResponse repayment = loanTransactionHelper.makeLoanRepayment(loanId, "MerchantIssuedRefund", + "29 January 2025", 500.0); + Assertions.assertNotNull(repayment); + Assertions.assertNotNull(repayment.getResourceId()); + + verifyTransactions(loanId, // + transaction(450.0, "Disbursement", "29 August 2024"), // + transaction(500.0, "Merchant Issued Refund", "29 January 2025"), // + transaction(48.94, "Interest Refund", "29 January 2025"), // + transaction(48.94, "Accrual", "29 January 2025") // + ); // + }); + } }