Skip to content

Commit 931946e

Browse files
logoutdhavalvidakovic
authored andcommitted
FINERACT-1745: Loan Schedule Final Installment calculation issue (#2690)
1 parent 0d7b7e2 commit 931946e

4 files changed

Lines changed: 91 additions & 2 deletions

File tree

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2313,6 +2313,7 @@ private LoanScheduleDTO rescheduleNextInstallments(final MathContext mc, final L
23132313
int period = periodNumber;
23142314
if (!lastInstallmentDate.isEqual(installment.getDueDate())) {
23152315
period--;
2316+
periodNumber = period;
23162317
}
23172318
reducePrincipal = fetchEarlyPaidAmount(installment.getPrincipal(currency), principalPortionCalculated, reducePrincipal,
23182319
loanApplicationTerms, totalCumulativePrincipal, period, mc);

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/DecliningBalanceInterestLoanScheduleGenerator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(final Pay
6060
final double interestCalculationGraceOnRepaymentPeriodFraction, final Money totalCumulativePrincipal,
6161
@SuppressWarnings("unused") final Money totalCumulativeInterest,
6262
@SuppressWarnings("unused") final Money totalInterestDueForLoan, final Money cumulatingInterestPaymentDueToGrace,
63-
final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, final int periodNumber, final MathContext mc,
63+
final Money outstandingBalance, final LoanApplicationTerms loanApplicationTerms, int periodNumber, final MathContext mc,
6464
final TreeMap<LocalDate, Money> principalVariation, final Map<LocalDate, Money> compoundingMap, final LocalDate periodStartDate,
6565
final LocalDate periodEndDate, final Collection<LoanTermVariationsData> termVariations) {
6666

@@ -157,7 +157,6 @@ public PrincipalInterest calculatePrincipalInterestComponentsForPeriod(final Pay
157157
// update cumulative fields for principal & interest
158158
final Money interestBroughtFowardDueToGrace = cumulatingInterestDueToGrace;
159159
final Money totalCumulativePrincipalToDate = totalCumulativePrincipal.plus(principalForThisInstallment);
160-
161160
// adjust if needed
162161
principalForThisInstallment = loanApplicationTerms.adjustPrincipalIfLastRepaymentPeriod(principalForThisInstallment,
163162
totalCumulativePrincipalToDate, periodNumber);

integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6091,6 +6091,86 @@ public void testLoanScheduleWithInterestRecalculationForLateRepaymentOfLateRepay
60916091
WorkingDaysHelper.updateWorkingDays(this.requestSpec, this.responseSpec);
60926092
}
60936093

6094+
@Test
6095+
public void testLoanScheduleWithInterestRecalculationForLastInstallmentAmountNotMoreThanEMI() {
6096+
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
6097+
WorkingDaysHelper.updateWorkingDaysWeekDays(this.requestSpec, this.responseSpec);
6098+
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
6099+
dateFormat.setTimeZone(Utils.getTimeZoneOfTenant());
6100+
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "42", true);
6101+
GlobalConfigurationHelper.updateEnabledFlagForGlobalConfiguration(this.requestSpec, this.responseSpec, "43", true);
6102+
final String loanDisbursementDate = "06 May 2022";
6103+
String firstRepayment = "27 May 2022";
6104+
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
6105+
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
6106+
String principalAmount = "7800.00";
6107+
String rateOfInterest = "8.9";
6108+
String numberOfRepayments = "12";
6109+
final Integer loanProductID = createLoanProductWithInterestRecalculationAndCompoundingDetails(
6110+
LoanProductTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY,
6111+
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
6112+
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
6113+
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD,
6114+
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE, null, "12", numberOfRepayments, principalAmount,
6115+
rateOfInterest);
6116+
6117+
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, loanDisbursementDate,
6118+
LoanApplicationTestBuilder.INTEREST_PRINCIPAL_PENALTIES_FEES_ORDER_STRATEGY, firstRepayment, numberOfRepayments,
6119+
principalAmount, rateOfInterest);
6120+
6121+
Assertions.assertNotNull(loanID);
6122+
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
6123+
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
6124+
6125+
LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------");
6126+
loanStatusHashMap = this.loanTransactionHelper.approveLoan(loanDisbursementDate, loanID);
6127+
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
6128+
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
6129+
6130+
LOG.info("-------------------------------DISBURSE LOAN-------------------------------------------");
6131+
String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, loanID);
6132+
loanStatusHashMap = this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount(loanDisbursementDate, loanID,
6133+
JsonPath.from(loanDetails).get("netDisbursalAmount").toString());
6134+
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
6135+
6136+
ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
6137+
Assertions.assertNotNull(loanSchedule);
6138+
6139+
this.loanTransactionHelper.makeRepayment("27 May 2022", 1080.0F, loanID);
6140+
Assertions.assertTrue(
6141+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6142+
6143+
this.loanTransactionHelper.makeRepayment("27 June 2022", 1080.0F, loanID);
6144+
Assertions.assertTrue(
6145+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6146+
6147+
this.loanTransactionHelper.makeRepayment("27 July 2022", 1080.0F, loanID);
6148+
Assertions.assertTrue(
6149+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6150+
6151+
this.loanTransactionHelper.makeRepayment("30 August 2022", 1080.0F, loanID);
6152+
Assertions.assertTrue(
6153+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6154+
6155+
this.loanTransactionHelper.makeRepayment("01 September 2022", 17.01F, loanID);
6156+
Assertions.assertTrue(
6157+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6158+
6159+
this.loanTransactionHelper.makeRepayment("01 September 2022", 34.02F, loanID);
6160+
Assertions.assertTrue(
6161+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6162+
6163+
this.loanTransactionHelper.makeRepayment("27 September 2022", 1080.0F, loanID);
6164+
Assertions.assertTrue(
6165+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6166+
6167+
this.loanTransactionHelper.makeRepayment("27 October 2022", 1080.0F, loanID);
6168+
Assertions.assertTrue(
6169+
this.loanTransactionHelper.checkForLastInstallmentLessThanEMI(this.requestSpec, this.responseSpec, loanID, 1080.0F));
6170+
6171+
WorkingDaysHelper.updateWorkingDays(this.requestSpec, this.responseSpec);
6172+
}
6173+
60946174
private Calendar convertStringDateToCalender(final String stringDate) {
60956175
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US);
60966176
Calendar date = Calendar.getInstance();

integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,4 +943,13 @@ public String getOutputTemplateLocation(final String importDocumentId) {
943943
return Utils.performServerOutputTemplateLocationGet(requestSpec, responseSpec,
944944
"/fineract-provider/api/v1/imports/getOutputTemplateLocation" + "?" + Utils.TENANT_IDENTIFIER, importDocumentId);
945945
}
946+
947+
public boolean checkForLastInstallmentLessThanEMI(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
948+
final Integer loanID, final Float emiAmount) {
949+
ArrayList<HashMap> loanSchedule = this.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
950+
String principal = String.valueOf(loanSchedule.get(loanSchedule.size() - 1).get("principalOriginalDue"));
951+
String interest = String.valueOf(loanSchedule.get(loanSchedule.size() - 1).get("interestOriginalDue"));
952+
Float amount = Float.parseFloat(principal) + Float.parseFloat(interest);
953+
return amount.compareTo(emiAmount) <= 0;
954+
}
946955
}

0 commit comments

Comments
 (0)