From 3fd0557f7a7c9a33665b88832fff1fb923aa8bae Mon Sep 17 00:00:00 2001 From: taskain7 Date: Mon, 4 Sep 2023 05:10:46 +0200 Subject: [PATCH] [FINERACT-1958] Tests for interest not applied on down payment installment --- ...nRepaymentScheduleWithDownPaymentTest.java | 197 ++++++++++++++++-- 1 file changed, 184 insertions(+), 13 deletions(-) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java index 0c7c2a3bb..8e27d9e2c 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java @@ -89,7 +89,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1"); + final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -135,7 +135,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1"); + final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -182,7 +182,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1"); + final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -228,7 +228,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1"); + final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -279,7 +279,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1"); + final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -331,7 +331,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4"); + final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -400,7 +400,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4"); + final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4", "0"); GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); @@ -482,7 +482,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1"); + final Integer loanId = createApproveAndDisburseLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "1", "0"); final Double feeAmount = 10.00; String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount.toString(), @@ -546,7 +546,7 @@ public class LoanRepaymentScheduleWithDownPaymentTest { .compareTo(disbursedAmountPercentageForDownPayment)); assertEquals(enableAutoRepaymentForDownPayment, getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment()); - final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4"); + final Integer loanId = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4", "0"); final Double feeAmount = 10.00; String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount.toString(), @@ -619,6 +619,177 @@ public class LoanRepaymentScheduleWithDownPaymentTest { assertEquals(outstandingBalanceOnThirdRepayment, thirdRepaymentPeriod.getPrincipalLoanBalanceOutstanding()); } + @Test + public void loanRepaymentScheduleWithChargeAndInterestAndDownPayment() { + String loanExternalIdStr = UUID.randomUUID().toString(); + + final Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec); + final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec, + delinquencyBucketId); + + Boolean enableDownPayment = true; + BigDecimal disbursedAmountPercentageForDownPayment = BigDecimal.valueOf(25); + Boolean enableAutoRepaymentForDownPayment = false; + + final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); + + Integer loanProductId = createLoanProductWithDownPaymentConfiguration(loanTransactionHelper, delinquencyBucketId, enableDownPayment, + "25", enableAutoRepaymentForDownPayment, true); + + 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", "1"); + + final Double feeAmount = 10.00; + String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount.toString(), + false); + final PostChargesResponse postChargesResponse = ChargesHelper.createLoanCharge(requestSpec, responseSpec, payloadJSON); + assertNotNull(postChargesResponse); + final Long loanChargeId = postChargesResponse.getResourceId(); + + payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), "03 September 2022", + feeAmount.toString()); + PostLoansLoanIdChargesResponse postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON, + responseSpec); + assertNotNull(postLoansLoanIdChargesResponse); + + GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + + assertNotNull(loanDetails); + assertEquals(enableDownPayment, loanDetails.getEnableDownPayment()); + assertEquals(0, loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment)); + assertEquals(enableAutoRepaymentForDownPayment, loanDetails.getEnableAutoRepaymentForDownPayment()); + + List periods = loanDetails.getRepaymentSchedule().getPeriods(); + Double expectedDownPaymentAmount = 250.00; + LocalDate expectedDownPaymentDueDate = LocalDate.of(2022, 9, 3); + Double expectedRepaymentAmount = 750.00; + Double expectedTotalDueForRepaymentInstallment = 770.0; + LocalDate expectedRepaymentDueDate = LocalDate.of(2022, 10, 3); + + assertTrue(periods.stream() // + .anyMatch(period -> expectedDownPaymentAmount.equals(period.getTotalDueForPeriod()) // + && expectedDownPaymentDueDate.equals(period.getDueDate()) // + && Double.valueOf(0.00).equals(period.getFeeChargesDue()) // + && Double.valueOf(0.00).equals(period.getInterestDue()))); + assertTrue(periods.stream() // + .anyMatch(period -> expectedTotalDueForRepaymentInstallment.equals(period.getTotalDueForPeriod()) // + && expectedRepaymentAmount.equals(period.getPrincipalDue()) // + && expectedRepaymentDueDate.equals(period.getDueDate()) // + && feeAmount.equals(period.getFeeChargesDue()) // + && Double.valueOf(10.0).equals(period.getInterestDue()))); + } + + @Test + public void loanRepaymentScheduleWithMultiDisbursementProductTwoDisbursementAndThreeRepaymentsAndDownPaymentAndChargeAndInterest() { + String loanExternalIdStr = UUID.randomUUID().toString(); + + final Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec); + final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec, + delinquencyBucketId); + + Boolean enableDownPayment = true; + BigDecimal disbursedAmountPercentageForDownPayment = BigDecimal.valueOf(25); + Boolean enableAutoRepaymentForDownPayment = true; + + final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); + + Integer loanProductId = createLoanProductWithDownPaymentConfiguration(loanTransactionHelper, delinquencyBucketId, enableDownPayment, + "25", enableAutoRepaymentForDownPayment, true); + + 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 = createApproveAndDisburseTwiceLoanAccount(clientId, loanProductId.longValue(), loanExternalIdStr, "4", "1"); + + final Double feeAmount = 10.00; + String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount.toString(), + false); + final PostChargesResponse postChargesResponse = ChargesHelper.createLoanCharge(requestSpec, responseSpec, payloadJSON); + assertNotNull(postChargesResponse); + final Long loanChargeId = postChargesResponse.getResourceId(); + + payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), "04 September 2022", + feeAmount.toString()); + PostLoansLoanIdChargesResponse postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON, + responseSpec); + assertNotNull(postLoansLoanIdChargesResponse); + + GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + + assertNotNull(loanDetails); + assertEquals(enableDownPayment, loanDetails.getEnableDownPayment()); + assertEquals(0, loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment)); + assertEquals(enableAutoRepaymentForDownPayment, loanDetails.getEnableAutoRepaymentForDownPayment()); + + loanTransactionHelper.printRepaymentSchedule(loanDetails); + + List periods = loanDetails.getRepaymentSchedule().getPeriods(); + Double expectedOutstandingLoanBalanceOnFirstDisbursement = 700.00; + Double expectedFirstDownPaymentAmount = 175.00; + Double expectedDownPaymentInterest = 0.00; + LocalDate expectedFirstDownPaymentDueDate = LocalDate.of(2022, 9, 3); + Double expectedOutstandingLoanBalanceOnSecondDisbursement = 300.00; + Double expectedSecondDownPaymentAmount = 75.00; + LocalDate expectedSecondDownPaymentDueDate = LocalDate.of(2022, 9, 4); + Double expectedRepaymentAmount = 250.00; + Double expectedRepaymentAmountWithInterest = 260.00; + Double expectedRepaymentInterest = 10.0; + Double expectedRepaymentTotalDueWithChargeAndInterest = 270.0; + LocalDate expectedFirstRepaymentDueDate = LocalDate.of(2022, 10, 3); + Double outstandingBalanceOnFirstRepayment = 500.00; + LocalDate expectedSecondRepaymentDueDate = LocalDate.of(2022, 11, 3); + Double outstandingBalanceOnSecondRepayment = 250.00; + LocalDate expectedThirdRepaymentDueDate = LocalDate.of(2022, 12, 3); + Double outstandingBalanceOnThirdRepayment = 0.00; + + GetLoansLoanIdRepaymentPeriod firstDisbursementPeriod = periods.get(0); + assertEquals(expectedFirstDownPaymentDueDate, firstDisbursementPeriod.getDueDate()); + assertEquals(expectedOutstandingLoanBalanceOnFirstDisbursement, firstDisbursementPeriod.getPrincipalLoanBalanceOutstanding()); + + GetLoansLoanIdRepaymentPeriod firstDownPaymentPeriod = periods.get(1); + assertEquals(expectedFirstDownPaymentAmount, firstDownPaymentPeriod.getTotalDueForPeriod()); + assertEquals(expectedFirstDownPaymentDueDate, firstDownPaymentPeriod.getDueDate()); + assertEquals(expectedDownPaymentInterest, firstDownPaymentPeriod.getInterestDue()); + + GetLoansLoanIdRepaymentPeriod secondDisbursementPeriod = periods.get(2); + assertEquals(expectedSecondDownPaymentDueDate, secondDisbursementPeriod.getDueDate()); + assertEquals(expectedOutstandingLoanBalanceOnSecondDisbursement, secondDisbursementPeriod.getPrincipalLoanBalanceOutstanding()); + + GetLoansLoanIdRepaymentPeriod secondDownPaymentPeriod = periods.get(3); + assertEquals(expectedSecondDownPaymentAmount, secondDownPaymentPeriod.getTotalDueForPeriod()); + assertEquals(expectedSecondDownPaymentDueDate, secondDownPaymentPeriod.getDueDate()); + assertEquals(expectedDownPaymentInterest, secondDownPaymentPeriod.getInterestDue()); + + GetLoansLoanIdRepaymentPeriod firstRepaymentPeriod = periods.get(4); + assertEquals(expectedRepaymentAmount, firstRepaymentPeriod.getPrincipalDue()); + assertEquals(expectedRepaymentTotalDueWithChargeAndInterest, firstRepaymentPeriod.getTotalDueForPeriod()); + assertEquals(expectedFirstRepaymentDueDate, firstRepaymentPeriod.getDueDate()); + assertEquals(outstandingBalanceOnFirstRepayment, firstRepaymentPeriod.getPrincipalLoanBalanceOutstanding()); + assertEquals(expectedRepaymentInterest, firstRepaymentPeriod.getInterestDue()); + + GetLoansLoanIdRepaymentPeriod secondRepaymentPeriod = periods.get(5); + assertEquals(expectedRepaymentAmountWithInterest, secondRepaymentPeriod.getTotalDueForPeriod()); + assertEquals(expectedSecondRepaymentDueDate, secondRepaymentPeriod.getDueDate()); + assertEquals(outstandingBalanceOnSecondRepayment, secondRepaymentPeriod.getPrincipalLoanBalanceOutstanding()); + assertEquals(expectedRepaymentInterest, secondRepaymentPeriod.getInterestDue()); + + GetLoansLoanIdRepaymentPeriod thirdRepaymentPeriod = periods.get(6); + assertEquals(expectedRepaymentAmountWithInterest, thirdRepaymentPeriod.getTotalDueForPeriod()); + assertEquals(expectedThirdRepaymentDueDate, thirdRepaymentPeriod.getDueDate()); + assertEquals(outstandingBalanceOnThirdRepayment, thirdRepaymentPeriod.getPrincipalLoanBalanceOutstanding()); + assertEquals(expectedRepaymentInterest, thirdRepaymentPeriod.getInterestDue()); + } + private Integer createLoanProductWithDownPaymentConfiguration(final LoanTransactionHelper loanTransactionHelper, final Integer delinquencyBucketId, Boolean enableDownPayment, String disbursedAmountPercentageForDownPayment, Boolean enableAutoRepaymentForDownPayment, boolean multiDisbursement) { @@ -641,11 +812,11 @@ public class LoanRepaymentScheduleWithDownPaymentTest { } private Integer createApproveAndDisburseLoanAccount(final Integer clientID, final Long loanProductID, final String externalId, - final String numberOfRepayments) { + final String numberOfRepayments, final String interestRate) { String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency(numberOfRepayments) .withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments).withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance() + .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod(interestRate).withInterestTypeAsFlatBalance() .withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod() .withExpectedDisbursementDate("03 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual") .withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null); @@ -657,11 +828,11 @@ public class LoanRepaymentScheduleWithDownPaymentTest { } private Integer createApproveAndDisburseTwiceLoanAccount(final Integer clientID, final Long loanProductID, final String externalId, - final String numberOfRepayments) { + final String numberOfRepayments, final String interestRate) { String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency(numberOfRepayments) .withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments).withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance() + .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod(interestRate).withInterestTypeAsFlatBalance() .withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod() .withExpectedDisbursementDate("04 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual") .withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null);