From 7753e591caf769a494a6e3ec76693ef22ecd143b Mon Sep 17 00:00:00 2001 From: Dhaval Maniyar Date: Tue, 13 Sep 2022 18:06:59 +0530 Subject: [PATCH] fineract-loan issue --- .../domain/AbstractLoanScheduleGenerator.java | 14 ++- .../ClientLoanIntegrationTest.java | 98 +++++++++++++++++++ .../common/loans/LoanProductTestBuilder.java | 6 ++ 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java index 3a695c326d2..5fcab14b877 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java @@ -2219,7 +2219,17 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L .adjustRepaymentDate(actualRepaymentDate, loanApplicationTerms, holidayDetailDTO).getChangedScheduleDate(); LocalDate modifiedLastInstDate = null; LoanTermVariationsData variation1 = null; + + /* + * while (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(lastInstallmentDate)) + * { LoanTermVariationsData variation = + * loanApplicationTerms.getLoanTermVariations().nextDueDateVariation(); if + * (!variation.isSpecificToInstallment()) { actualRepaymentDate = variation.getDateValue(); + * lastInstallmentDate = actualRepaymentDate; } dueDateVariationsDataList.add(variation); } + */ + boolean flag = false; while (loanApplicationTerms.getLoanTermVariations().hasDueDateVariation(lastInstallmentDate)) { + flag = true; LoanTermVariationsData variation = loanApplicationTerms.getLoanTermVariations().nextDueDateVariation(); if (!variation.isSpecificToInstallment()) { modifiedLastInstDate = variation.getDateValue(); @@ -2227,8 +2237,8 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L } } - if (!lastInstallmentDate.isEqual(installment.getDueDate()) - && !installment.getDueDate().equals(modifiedLastInstDate)) { + if (!lastInstallmentDate.isEqual(installment.getDueDate()) && !installment.getDueDate().equals(modifiedLastInstDate) + && flag) { lastInstallmentDate = prevLastInstDate; actualRepaymentDate = lastInstallmentDate; if (modifiedLastInstDate != null) { diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java index f2a61b0db97..0e0703887cb 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java @@ -4678,6 +4678,23 @@ private Integer createLoanProductWithInterestRecalculationAndCompoundingDetails( recalculationRestFrequencyOnDayType, recalculationRestFrequencyDayOfWeekType); } + private Integer createLoanProductWithInterestRecalculationAndCompoundingDetails(final String repaymentStrategy, + final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod, + final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval, + final String recalculationRestFrequencyDate, final String recalculationCompoundingFrequencyType, + final String recalculationCompoundingFrequencyInterval, final String recalculationCompoundingFrequencyDate, + final String preCloseInterestCalculationStrategy, final Account[] accounts, + final Integer recalculationCompoundingFrequencyOnDayType, final Integer recalculationCompoundingFrequencyDayOfWeekType, + final Integer recalculationRestFrequencyOnDayType, final Integer recalculationRestFrequencyDayOfWeekType, + final String installmentMultipleOf) { + return createLoanProductWithInterestRecalculation(repaymentStrategy, interestRecalculationCompoundingMethod, + rescheduleStrategyMethod, recalculationRestFrequencyType, recalculationRestFrequencyInterval, + recalculationRestFrequencyDate, recalculationCompoundingFrequencyType, recalculationCompoundingFrequencyInterval, + recalculationCompoundingFrequencyDate, preCloseInterestCalculationStrategy, accounts, null, false, + recalculationCompoundingFrequencyOnDayType, recalculationCompoundingFrequencyDayOfWeekType, + recalculationRestFrequencyOnDayType, recalculationRestFrequencyDayOfWeekType, installmentMultipleOf); + } + private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy, final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod, final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval, @@ -4712,6 +4729,40 @@ private Integer createLoanProductWithInterestRecalculation(final String repaymen return this.loanTransactionHelper.getLoanProductId(loanProductJSON); } + private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy, + final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod, + final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval, + final String recalculationRestFrequencyDate, final String recalculationCompoundingFrequencyType, + final String recalculationCompoundingFrequencyInterval, final String recalculationCompoundingFrequencyDate, + final String preCloseInterestCalculationStrategy, final Account[] accounts, final String chargeId, + boolean isArrearsBasedOnOriginalSchedule, final Integer recalculationCompoundingFrequencyOnDayType, + final Integer recalculationCompoundingFrequencyDayOfWeekType, final Integer recalculationRestFrequencyOnDayType, + final Integer recalculationRestFrequencyDayOfWeekType, final String installmentsMultiplesOf) { + LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); + LoanProductTestBuilder builder = new LoanProductTestBuilder().withPrincipal("10000.00").withNumberOfRepayments("12") + .withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("19.9") + .withInterestRateFrequencyTypeAsMonths().withRepaymentStrategy(repaymentStrategy).withAmortizationTypeAsEqualInstallments() + .withInterestTypeAsDecliningBalance().withInterestCalculationPeriodTypeAsDays() + .withInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod, + preCloseInterestCalculationStrategy) + .withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, recalculationRestFrequencyInterval, + recalculationRestFrequencyOnDayType, recalculationRestFrequencyDayOfWeekType) + .withInterestRecalculationCompoundingFrequencyDetails(recalculationCompoundingFrequencyType, + recalculationCompoundingFrequencyInterval, recalculationCompoundingFrequencyOnDayType, + recalculationCompoundingFrequencyDayOfWeekType) + .withInstallmentAmountInMultiplesOf(installmentsMultiplesOf).withAllowFixingOfInstallmentsAmount(); + if (accounts != null) { + builder = builder.withAccountingRulePeriodicAccrual(accounts); + } + + if (isArrearsBasedOnOriginalSchedule) { + builder = builder.withArrearsConfiguration(); + } + + final String loanProductJSON = builder.build(chargeId); + return this.loanTransactionHelper.getLoanProductId(loanProductJSON); + } + private Integer applyForLoanApplicationForInterestRecalculation(final Integer clientID, final Integer loanProductID, final String disbursementDate, final String repaymentStrategy, final List charges) { return applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, disbursementDate, repaymentStrategy, charges, null, @@ -5746,6 +5797,53 @@ public void testCollateralDataIsAvailableWhenRequested() { assertEquals(clientCollateralId, clientCollateralIdResult); } + @Test + public void testLoanScheduleWithInterestRecalculationMakePrepaymentAfterRepayment() { + this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + + final String loanDisbursementDate = "08 January 2022"; + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); + final Integer loanProductID = createLoanProductWithInterestRecalculationAndCompoundingDetails( + LoanProductTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY, + LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_INTEREST, + LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS, + LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "1", loanDisbursementDate, + LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_MONTHLY, "1", loanDisbursementDate, + LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, null, null, null, null, "10"); + + final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, loanDisbursementDate, + LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY, new ArrayList(0)); + + Assertions.assertNotNull(loanID); + HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); + LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + + LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------"); + loanStatusHashMap = this.loanTransactionHelper.approveLoan(loanDisbursementDate, loanID); + LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); + LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + + LOG.info("-------------------------------DISBURSE LOAN-------------------------------------------"); + String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, loanID); + loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount(loanDisbursementDate, loanID, + JsonPath.from(loanDetails).get("netDisbursalAmount").toString()); + LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap); + + ArrayList loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); + Assertions.assertNotNull(loanSchedule); + String loanFirstRepaymentDate = "10 January 2022"; + Float earlyPayment = Float.parseFloat("4000"); + this.loanTransactionHelper.makeRepayment(loanFirstRepaymentDate, earlyPayment, loanID); + + HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID); + String prepayAmount = String.valueOf(prepayDetail.get("amount")); + String loanPrepaymentDate = "28 February 2022"; + this.loanTransactionHelper.makeRepayment(loanPrepaymentDate, Float.parseFloat(prepayAmount), loanID); + loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); + LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap); + } + private void validateIfValuesAreNotOverridden(Integer loanID, Integer loanProductID) { String loanProductDetails = this.loanTransactionHelper.getLoanProductDetails(this.requestSpec, this.responseSpec, loanProductID); String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, loanID); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java index 4d9ff06bdc7..68936632efb 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java @@ -130,6 +130,7 @@ public class LoanProductTestBuilder { private boolean syncExpectedWithDisbursementDate = false; private String fixedPrincipalPercentagePerInstallment; private String installmentAmountInMultiplesOf; + private boolean allowFixingOfInstallmentsAmount; public String build(final String chargeId) { final HashMap map = build(chargeId, null); @@ -387,6 +388,11 @@ public LoanProductTestBuilder withMultiDisburse() { return this; } + public LoanProductTestBuilder withAllowFixingOfInstallmentsAmount() { + this.allowFixingOfInstallmentsAmount = true; + return this; + } + public LoanProductTestBuilder withDisallowExpectectedDisbursements(boolean disallowExpectectedDisbursements) { this.disallowExpectedDisbursements = disallowExpectectedDisbursements; if (this.disallowExpectedDisbursements) {