Skip to content

Commit e82753b

Browse files
committed
FINERACT-2181: Cumulative loan reschedule and downpayment fix
1 parent dd4ca4d commit e82753b

File tree

8 files changed

+70
-37
lines changed

8 files changed

+70
-37
lines changed

fineract-e2e-tests-runner/src/test/resources/features/LoanDownPayment.feature

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,14 +1108,14 @@ Feature: Loan DownPayment
11081108
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
11091109
| | | 01 January 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
11101110
| 1 | 0 | 01 January 2022 | 01 January 2022 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
1111-
| 2 | 31 | 01 February 2022 | 15 February 2022 | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 250.0 | 0.0 |
1111+
| 2 | 31 | 01 February 2022 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
11121112
| | | 15 February 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
1113-
| 3 | 0 | 15 February 2022 | | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
1114-
| 4 | 28 | 01 March 2022 | | 750.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
1115-
| 5 | 31 | 01 April 2022 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
1113+
| 3 | 0 | 15 February 2022 | 15 February 2022 | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
1114+
| 4 | 28 | 01 March 2022 | | 625.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
1115+
| 5 | 31 | 01 April 2022 | | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
11161116
Then Loan Repayment schedule has the following data in Total row:
11171117
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
1118-
| 2000.0 | 0 | 0 | 0 | 2000.0 | 500.0 | 0 | 250 | 1500 |
1118+
| 2000.0 | 0 | 0 | 0 | 2000.0 | 500.0 | 0 | 0 | 1500 |
11191119
Then Loan Transactions tab has the following data:
11201120
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance |
11211121
| 01 January 2022 | Disbursement | 1000.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1000.0 |
@@ -1162,8 +1162,8 @@ Feature: Loan DownPayment
11621162
| 2 | 31 | 01 February 2022 | | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
11631163
| | | 15 February 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
11641164
| 3 | 0 | 15 February 2022 | | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
1165-
| 4 | 28 | 01 March 2022 | | 750.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
1166-
| 5 | 31 | 01 April 2022 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
1165+
| 4 | 28 | 01 March 2022 | | 625.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
1166+
| 5 | 31 | 01 April 2022 | | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
11671167
Then Loan Repayment schedule has the following data in Total row:
11681168
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
11691169
| 2000.0 | 0 | 0 | 0 | 2000.0 | 250.0 | 0 | 0 | 1750 |
@@ -1175,8 +1175,8 @@ Feature: Loan DownPayment
11751175
| 2 | 31 | 01 February 2022 | 15 February 2022 | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 250.0 | 0.0 |
11761176
| | | 15 February 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
11771177
| 3 | 0 | 15 February 2022 | | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
1178-
| 4 | 28 | 01 March 2022 | | 750.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
1179-
| 5 | 31 | 01 April 2022 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
1178+
| 4 | 28 | 01 March 2022 | | 625.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
1179+
| 5 | 31 | 01 April 2022 | | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
11801180
Then Loan Repayment schedule has the following data in Total row:
11811181
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
11821182
| 2000.0 | 0 | 0 | 0 | 2000.0 | 500.0 | 0 | 250 | 1500 |
@@ -1227,8 +1227,8 @@ Feature: Loan DownPayment
12271227
| 2 | 31 | 01 February 2022 | 01 February 2022 | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
12281228
| | | 15 February 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
12291229
| 3 | 0 | 15 February 2022 | 15 February 2022 | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
1230-
| 4 | 28 | 01 March 2022 | | 750.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
1231-
| 5 | 31 | 01 April 2022 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
1230+
| 4 | 28 | 01 March 2022 | | 625.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
1231+
| 5 | 31 | 01 April 2022 | | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
12321232
Then Loan Repayment schedule has the following data in Total row:
12331233
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
12341234
| 2000.0 | 0 | 0 | 0 | 2000.0 | 750.0 | 0 | 0 | 1250 |
@@ -1291,8 +1291,8 @@ Feature: Loan DownPayment
12911291
| 2 | 31 | 01 February 2022 | 01 February 2022 | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
12921292
| | | 15 February 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
12931293
| 3 | 0 | 15 February 2022 | | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 |
1294-
| 4 | 28 | 01 March 2022 | | 750.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
1295-
| 5 | 31 | 01 April 2022 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
1294+
| 4 | 28 | 01 March 2022 | | 625.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
1295+
| 5 | 31 | 01 April 2022 | | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
12961296
Then Loan Repayment schedule has the following data in Total row:
12971297
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
12981298
| 2000.0 | 0 | 0 | 0 | 2000.0 | 500.0 | 0 | 0 | 1500 |
@@ -1304,8 +1304,8 @@ Feature: Loan DownPayment
13041304
| 2 | 31 | 01 February 2022 | 01 February 2022 | 500.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
13051305
| | | 15 February 2022 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
13061306
| 3 | 0 | 15 February 2022 | 15 February 2022 | 1250.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
1307-
| 4 | 28 | 01 March 2022 | | 750.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 | 0.0 | 0.0 | 0.0 | 500.0 |
1308-
| 5 | 31 | 01 April 2022 | | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 | 0.0 | 0.0 | 0.0 | 750.0 |
1307+
| 4 | 28 | 01 March 2022 | | 625.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
1308+
| 5 | 31 | 01 April 2022 | | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 | 0.0 | 0.0 | 0.0 | 625.0 |
13091309
Then Loan Repayment schedule has the following data in Total row:
13101310
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
13111311
| 2000.0 | 0 | 0 | 0 | 2000.0 | 750.0 | 0 | 0 | 1250 |

fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,6 @@ Feature: LoanReschedule
344344
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
345345
| 1400.0 | 0.0 | 0.0 | 0.0 | 1400.0 | 350.0 | 0.0 | 0.0 | 1050.0 |
346346

347-
# TODO unskip and check when PS-1729 is done
348-
@Skip
349347
@TestRailId:C2998
350348
Scenario: Verify that reschedule: add extra terms working properly with auto downpayment and 2nd disbursement after reschedule and first installment
351349
When Admin sets the business date to "01 October 2023"
@@ -365,16 +363,16 @@ Feature: LoanReschedule
365363
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
366364
| | | 01 October 2023 | | 1000.0 | | | 0.0 | | 0.0 | 0.0 | | | |
367365
| 1 | 0 | 01 October 2023 | 01 October 2023 | 750.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0 | 0.0 |
368-
| 2 | 15 | 16 October 2023 | | 600.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 100.0 | 0.0 | 100.0 | 50.0 |
366+
| 2 | 15 | 16 October 2023 | | 600.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 | 0.0 | 0.0 | 0.0 | 150.0 |
369367
| | | 20 October 2023 | | 400.0 | | | 0.0 | | 0.0 | 0.0 | | | |
370-
| 3 | 0 | 20 October 2023 | | 900.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 |
368+
| 3 | 0 | 20 October 2023 | 20 October 2023 | 900.0 | 100.0 | 0.0 | 0.0 | 0.0 | 100.0 | 100.0 | 0.0 | 0.0 | 0.0 |
371369
| 4 | 15 | 31 October 2023 | | 675.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
372370
| 5 | 15 | 15 November 2023 | | 450.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
373371
| 6 | 15 | 30 November 2023 | | 225.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
374372
| 7 | 15 | 15 December 2023 | | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 | 0.0 | 0.0 | 0.0 | 225.0 |
375373
Then Loan Repayment schedule has the following data in Total row:
376374
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
377-
| 1400.0 | 0.0 | 0.0 | 0.0 | 1400.0 | 350.0 | 0.0 | 100.0 | 1050.0 |
375+
| 1400.0 | 0.0 | 0.0 | 0.0 | 1400.0 | 350.0 | 0.0 | 0.0 | 1050.0 |
378376

379377
@TestRailId:C3022
380378
Scenario: Verify that Payment Holiday (Reschedule with adjustedDueDate) works properly in case of loan schedule adjusted by 1 installment period after successful downpayment

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,27 @@ protected Money processTransaction(final LoanTransaction loanTransaction, final
682682
}
683683
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings = new ArrayList<>();
684684

685+
if (loanTransaction.isDownPayment()) {
686+
Optional<LoanRepaymentScheduleInstallment> downPaymentInstallmentOpt = installments.stream()
687+
.filter(i -> i.getDueDate().equals(loanTransaction.getDateOf()) && i.isDownPayment()).findFirst();
688+
if (downPaymentInstallmentOpt.isPresent()) {
689+
LoanRepaymentScheduleInstallment downPaymentInstallment = downPaymentInstallmentOpt.get();
690+
if (downPaymentInstallment.isNotFullyPaidOff()) {
691+
692+
if (DateUtils.isBefore(transactionDate, downPaymentInstallment.getDueDate())) {
693+
transactionAmountUnprocessed = handleTransactionThatIsPaymentInAdvanceOfInstallment(downPaymentInstallment,
694+
installments, loanTransaction, transactionAmountUnprocessed, transactionMappings, charges);
695+
} else if (DateUtils.isAfter(transactionDate, downPaymentInstallment.getDueDate())) {
696+
transactionAmountUnprocessed = handleTransactionThatIsALateRepaymentOfInstallment(downPaymentInstallment,
697+
installments, loanTransaction, transactionAmountUnprocessed, transactionMappings, charges);
698+
} else {
699+
transactionAmountUnprocessed = handleTransactionThatIsOnTimePaymentOfInstallment(downPaymentInstallment,
700+
loanTransaction, transactionAmountUnprocessed, transactionMappings, charges);
701+
}
702+
}
703+
}
704+
}
705+
685706
for (final LoanRepaymentScheduleInstallment currentInstallment : installments) {
686707
if (transactionAmountUnprocessed.isGreaterThanZero()) {
687708
if (currentInstallment.isNotFullyPaidOff()) {

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractCumulativeLoanScheduleGenerator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,8 @@ private void processDisbursements(final LoanApplicationTerms loanApplicationTerm
10581058
scheduleParams.addOutstandingBalance(remainingPrincipal);
10591059
scheduleParams.addPrincipalToBeScheduled(remainingPrincipal);
10601060
loanApplicationTerms.setPrincipal(loanApplicationTerms.getPrincipal().plus(remainingPrincipal));
1061+
loanApplicationTerms.updateAccountedTillPeriod(scheduleParams.getPeriodNumber() - 1,
1062+
scheduleParams.getTotalCumulativePrincipal(), scheduleParams.getTotalCumulativeInterest(), 0);
10611063
}
10621064
}
10631065
}

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,8 +1179,12 @@ private Money flatInterestPerInstallment(final MathContext mc, final Money total
11791179
.dividedBy(Long.valueOf(this.actualNumberOfRepayments) - defaultToZeroIfNull(this.excludePeriodsForCalculation), mc);
11801180
if (this.excludePeriodsForCalculation < this.periodsCompleted) {
11811181
Money interestLeft = this.totalInterestDue.minus(this.totalInterestAccounted);
1182-
interestPerInstallment = interestLeft
1183-
.dividedBy(Long.valueOf(this.actualNumberOfRepayments) - defaultToZeroIfNull(this.periodsCompleted), mc);
1182+
long remainingPeriods = Long.valueOf(this.actualNumberOfRepayments) - defaultToZeroIfNull(this.periodsCompleted);
1183+
if (remainingPeriods > 0) {
1184+
interestPerInstallment = interestLeft.dividedBy(remainingPeriods, mc);
1185+
} else {
1186+
interestPerInstallment = interestLeft;
1187+
}
11841188
}
11851189

11861190
return interestPerInstallment;
@@ -1195,8 +1199,12 @@ private Money calculateTotalPrincipalPerPeriodWithoutGrace(final MathContext mc,
11951199
principalPerPeriod = this.principal.minus(totalPrincipalAccounted)
11961200
.percentageOf(this.fixedPrincipalPercentagePerInstallment, mc).plus(this.adjustPrincipalForFlatLoans);
11971201
} else {
1198-
principalPerPeriod = this.principal.minus(totalPrincipalAccounted).dividedBy(totalRepaymentsWithCapitalPayment, mc)
1199-
.plus(this.adjustPrincipalForFlatLoans);
1202+
if (totalRepaymentsWithCapitalPayment > 0) {
1203+
principalPerPeriod = this.principal.minus(totalPrincipalAccounted).dividedBy(totalRepaymentsWithCapitalPayment, mc)
1204+
.plus(this.adjustPrincipalForFlatLoans);
1205+
} else {
1206+
principalPerPeriod = this.principal.minus(totalPrincipalAccounted).plus(this.adjustPrincipalForFlatLoans);
1207+
}
12001208
}
12011209
if (isPrincipalGraceApplicableForThisPeriod(periodNumber)) {
12021210
principalPerPeriod = principalPerPeriod.zero();
@@ -1283,7 +1291,11 @@ private Money calculateTotalFlatInterestForInstallmentAveragingOutGracePeriods(f
12831291
Money interestLeft = this.totalInterestDue.minus(this.totalInterestAccounted);
12841292
Integer interestDuePeriods = calculateNumberOfRemainingInterestPaymentPeriods(this.actualNumberOfRepayments,
12851293
this.periodsCompleted);
1286-
interestForInstallment = interestLeft.dividedBy(Long.valueOf(interestDuePeriods), mc);
1294+
if (interestDuePeriods != null && interestDuePeriods > 0) {
1295+
interestForInstallment = interestLeft.dividedBy(Long.valueOf(interestDuePeriods), mc);
1296+
} else {
1297+
interestForInstallment = interestLeft;
1298+
}
12871299
}
12881300
if (!this.periodNumbersApplicableForInterestGrace.isEmpty()) {
12891301
int periodsElapsed = calculateLastInterestGracePeriod(periodNumber);

0 commit comments

Comments
 (0)