You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by al...@apache.org on 2022/11/22 02:06:31 UTC
[fineract] 01/01: FINERACT-1745: Loan Schedule Final Installment calculation issue (#2690)
This is an automated email from the ASF dual-hosted git repository.
aleks pushed a commit to branch 1.7.2
in repository https://gitbox.apache.org/repos/asf/fineract.git
commit 8ef6bc0fd15561c1392b0be881f1e3e51c4b1809
Author: logoutdhaval <10...@users.noreply.github.com>
AuthorDate: Fri Nov 4 20:46:15 2022 +0530
FINERACT-1745: Loan Schedule Final Installment calculation issue (#2690)
---
.../domain/AbstractLoanScheduleGenerator.java | 1 +
...liningBalanceInterestLoanScheduleGenerator.java | 3 +-
.../ClientLoanIntegrationTest.java | 80 ++++++++++++++++++++++
.../common/loans/LoanTransactionHelper.java | 9 +++
4 files changed, 91 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 e7c389985..d8d2e54d2 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
@@ -2313,6 +2313,7 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
int period = periodNumber;
if (!lastInstallmentDate.isEqual(installment.getDueDate())) {
period--;
+ periodNumber = period;
}
reducePrincipal = fetchEarlyPaidAmount(installment.getPrincipal(currency), principalPortionCalculated, reducePrincipal,
loanApplicationTerms, totalCumulativePrincipal, period, mc);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java
index c39112577..5a8af0483 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java
@@ -60,7 +60,7 @@ public class DecliningBalanceInterestLoanScheduleGenerator extends AbstractLoanS
final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal,
@SuppressWarnings("unused") final Money totalCumulativeInterest,
@SuppressWarnings("unused") final Money totalInterestDueForLoan, final Money cumulatingInterestPaymentDueToGrace,
- final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, final int periodNumber, final MathContext mc,
+ final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, int periodNumber, final MathContext mc,
final TreeMap<LocalDate, Money> principalVariation, final Map<LocalDate, Money> compoundingMap, final LocalDate periodStartDate,
final LocalDate periodEndDate, final Collection<LoanTermVariationsData> termVariations) {
@@ -157,7 +157,6 @@ public class DecliningBalanceInterestLoanScheduleGenerator extends AbstractLoanS
// update cumulative fields for principal & interest
final Money interestBroughtFowardDueToGrace = cumulatingInterestDueToGrace;
final Money totalCumulativePrincipalToDate = totalCumulativePrincipal.plus(principalForThisInstallment);
-
// adjust if needed
principalForThisInstallment = loanApplicationTerms.adjustPrincipalIfLastRepaymentPeriod(principalForThisInstallment,
totalCumulativePrincipalToDate, periodNumber);
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 e9cd83abd..2e39e4172 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
@@ -6091,6 +6091,86 @@ public class ClientLoanIntegrationTest {
WorkingDaysHelper.updateWorkingDays(this.requestSpec, this.responseSpec);
}
+ @Test
+ public void testLoanScheduleWithInterestRecalculationForLastInstallmentAmountNotMoreThanEMI() {
+ this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+ WorkingDaysHelper.updateWorkingDaysWeekDays(this.requestSpec, this.responseSpec);
+ DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
+ dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
+ GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "42", true);
+ GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "43", true);
+ final String loanDisbursementDate = "06 May 2022";
+ String firstRepayment = "27 May 2022";
+ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+ ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+ String principalAmount = "7800.00";
+ String rateOfInterest = "8.9";
+ String numberOfRepayments = "12";
+ final Integer loanProductID = createLoanProductWithInterestRecalculationAndCompoundingDetails(
+ LoanProductTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY,
+ LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
+ LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
+ LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD,
+ LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, "12", numberOfRepayments, principalAmount,
+ rateOfInterest);
+
+ final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, loanDisbursementDate,
+ LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY, firstRepayment, numberOfRepayments,
+ principalAmount, rateOfInterest);
+
+ 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<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+ Assertions.assertNotNull(loanSchedule);
+
+ this.loanTransactionHelper.makeRepayment("27 May 2022", 1080.0F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("27 June 2022", 1080.0F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("27 July 2022", 1080.0F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("30 August 2022", 1080.0F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("01 September 2022", 17.01F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("01 September 2022", 34.02F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("27 September 2022", 1080.0F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ this.loanTransactionHelper.makeRepayment("27 October 2022", 1080.0F, loanID);
+ Assertions.assertTrue(
+ this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
+
+ WorkingDaysHelper.updateWorkingDays(this.requestSpec, this.responseSpec);
+ }
+
private Calendar convertStringDateToCalender(final String stringDate) {
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
Calendar date = Calendar.getInstance();
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index 36fbfdca2..fdc8af866 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -943,4 +943,13 @@ public class LoanTransactionHelper {
return Utils.performServerOutputTemplateLocationGet(requestSpec, responseSpec,
"/fineract-provider/api/v1/imports/getOutputTemplateLocation" + "?" + Utils.TENANT_IDENTIFIER, importDocumentId);
}
+
+ public boolean checkForLastInstallmentLessThanEMI(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+ final Integer loanID, final Float emiAmount) {
+ ArrayList<HashMap> loanSchedule = this.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+ String principal = String.valueOf(loanSchedule.get(loanSchedule.size() - 1).get("principalOriginalDue"));
+ String interest = String.valueOf(loanSchedule.get(loanSchedule.size() - 1).get("interestOriginalDue"));
+ Float amount = Float.parseFloat(principal) + Float.parseFloat(interest);
+ return amount.compareTo(emiAmount) <= 0;
+ }
}