Skip to content

Commit b32837e

Browse files
committed
FINERACT-2390: Fix infinite loop issue
1 parent 1596d09 commit b32837e

File tree

4 files changed

+107
-4
lines changed

4 files changed

+107
-4
lines changed

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/helper/ErrorMessageHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ public static String wrongValueInLineInRepaymentSchedule(String resourceId, int
545545
List<String> expected) {
546546
String actual = actualList.stream().map(Object::toString).collect(Collectors.joining(System.lineSeparator()));
547547
return String.format("%nWrong value in Repayment schedule of resource %s tab line %s." //
548-
+ "%nActual values in line (with the same due date) are: %n%s - But expected values in line: %n%s", resourceId, line,
548+
+ "%nActual values in line (with the same due date) are: %n%s - %nBut expected values in line: %n%s", resourceId, line,
549549
actual, expected);
550550
}
551551

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,16 +4010,16 @@ public void initialize() throws Exception {
40104010
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PENALTY, //
40114011
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_FEE), //
40124012
createPaymentAllocation("GOODWILL_CREDIT", "REAMORTIZATION",
4013-
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PRINCIPAL, //
40144013
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_INTEREST, //
4014+
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PRINCIPAL, //
40154015
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_PENALTY, //
40164016
LoanProductPaymentAllocationRule.AllocationTypesEnum.PAST_DUE_FEE, //
4017-
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PRINCIPAL, //
40184017
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_INTEREST, //
4018+
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PRINCIPAL, //
40194019
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_PENALTY, //
40204020
LoanProductPaymentAllocationRule.AllocationTypesEnum.DUE_FEE, //
4021-
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PRINCIPAL, //
40224021
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_INTEREST, //
4022+
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PRINCIPAL, //
40234023
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_PENALTY, //
40244024
LoanProductPaymentAllocationRule.AllocationTypesEnum.IN_ADVANCE_FEE), //
40254025
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT",

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

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,91 @@ Feature: MerchantIssuedRefund
549549
When Admin sets the business date to "16 July 2024"
550550
#mismatch date for Interest Refund
551551
When Admin manually adds Interest Refund for "MERCHANT_ISSUED_REFUND" transaction made on invalid date "16 July 2024" with 2.42 EUR interest refund amount
552+
553+
554+
@TestRailId:C4127
555+
Scenario: High interest rate in advance paid Repayment + Merchant Issued Refund
556+
When Admin sets the business date to "10 July 2025"
557+
And Admin creates a client with random data
558+
And Admin creates a fully customized loan with the following data:
559+
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
560+
| LP2_ADV_CUSTOM_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL | 10 July 2025 | 1000 | 24.99 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 24 | MONTHS | 1 | MONTHS | 24 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
561+
And Admin successfully approves the loan on "10 July 2025" with "1000" amount and expected disbursement date on "10 July 2025"
562+
And Admin successfully disburse the loan on "10 July 2025" with "733.56" EUR transaction amount
563+
When Admin sets the business date to "29 July 2025"
564+
And Customer makes "REPAYMENT" transaction with "AUTOPAY" payment type on "29 July 2025" with 540.0 EUR transaction amount and system-generated Idempotency key
565+
Then Loan Repayment schedule has 24 periods, with the following data for periods:
566+
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
567+
| | | 10 July 2025 | | 733.56 | | | 0.0 | | 0.0 | 0.0 | | | |
568+
| 1 | 31 | 10 August 2025 | 29 July 2025 | 703.77 | 29.79 | 9.36 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
569+
| 2 | 31 | 10 September 2025 | 29 July 2025 | 664.62 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
570+
| 3 | 30 | 10 October 2025 | 29 July 2025 | 625.47 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
571+
| 4 | 31 | 10 November 2025 | 29 July 2025 | 586.32 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
572+
| 5 | 30 | 10 December 2025 | 29 July 2025 | 547.17 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
573+
| 6 | 31 | 10 January 2026 | 29 July 2025 | 508.02 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
574+
| 7 | 31 | 10 February 2026 | 29 July 2025 | 468.87 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
575+
| 8 | 28 | 10 March 2026 | 29 July 2025 | 429.72 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
576+
| 9 | 31 | 10 April 2026 | 29 July 2025 | 390.57 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
577+
| 10 | 30 | 10 May 2026 | 29 July 2025 | 351.42 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
578+
| 11 | 31 | 10 June 2026 | 29 July 2025 | 312.27 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
579+
| 12 | 30 | 10 July 2026 | 29 July 2025 | 273.12 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
580+
| 13 | 31 | 10 August 2026 | 29 July 2025 | 233.97 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
581+
| 14 | 31 | 10 September 2026 | | 194.82 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 31.05 | 31.05 | 0.0 | 8.1 |
582+
| 15 | 30 | 10 October 2026 | | 194.82 | 0.0 | 39.15 | 0.0 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 |
583+
| 16 | 31 | 10 November 2026 | | 181.27 | 13.55 | 25.6 | 0.0 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 |
584+
| 17 | 30 | 10 December 2026 | | 145.89 | 35.38 | 3.77 | 0.0 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 |
585+
| 18 | 31 | 10 January 2027 | | 109.78 | 36.11 | 3.04 | 0.0 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 |
586+
| 19 | 31 | 10 February 2027 | | 72.92 | 36.86 | 2.29 | 0.0 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 |
587+
| 20 | 28 | 10 March 2027 | | 35.29 | 37.63 | 1.52 | 0.0 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 |
588+
| 21 | 31 | 10 April 2027 | | 0.0 | 35.29 | 0.73 | 0.0 | 0.0 | 36.02 | 0.0 | 0.0 | 0.0 | 36.02 |
589+
| 22 | 30 | 10 May 2027 | 29 July 2025 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
590+
| 23 | 31 | 10 June 2027 | 29 July 2025 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
591+
| 24 | 30 | 10 July 2027 | 29 July 2025 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
592+
And Loan Repayment schedule has the following data in Total row:
593+
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
594+
| 733.56 | 85.46 | 0.0 | 0.0 | 819.02 | 540.0 | 540.0 | 0.0 | 279.02 |
595+
And Loan Transactions tab has the following data:
596+
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
597+
| 10 July 2025 | Disbursement | 733.56 | 0.0 | 0.0 | 0.0 | 0.0 | 733.56 | false | false |
598+
| 29 July 2025 | Repayment | 540.0 | 530.64 | 9.36 | 0.0 | 0.0 | 202.92 | false | false |
599+
When Admin sets the business date to "02 October 2025"
600+
And Customer makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "02 October 2025" with 635.23 EUR transaction amount and system-generated Idempotency key and interestRefundCalculation true
601+
Then Loan Repayment schedule has 24 periods, with the following data for periods:
602+
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
603+
| | | 10 July 2025 | | 733.56 | | | 0.0 | | 0.0 | 0.0 | | | |
604+
| 1 | 31 | 10 August 2025 | 29 July 2025 | 703.77 | 29.79 | 9.36 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
605+
| 2 | 31 | 10 September 2025 | 29 July 2025 | 664.62 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
606+
| 3 | 30 | 10 October 2025 | 29 July 2025 | 625.47 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
607+
| 4 | 31 | 10 November 2025 | 29 July 2025 | 586.32 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
608+
| 5 | 30 | 10 December 2025 | 29 July 2025 | 547.17 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
609+
| 6 | 31 | 10 January 2026 | 29 July 2025 | 508.02 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
610+
| 7 | 31 | 10 February 2026 | 29 July 2025 | 468.87 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
611+
| 8 | 28 | 10 March 2026 | 29 July 2025 | 429.72 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
612+
| 9 | 31 | 10 April 2026 | 29 July 2025 | 390.57 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
613+
| 10 | 30 | 10 May 2026 | 29 July 2025 | 351.42 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
614+
| 11 | 31 | 10 June 2026 | 29 July 2025 | 312.27 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
615+
| 12 | 30 | 10 July 2026 | 29 July 2025 | 273.12 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
616+
| 13 | 31 | 10 August 2026 | 29 July 2025 | 233.97 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
617+
| 14 | 31 | 10 September 2026 | 02 October 2025 | 202.92 | 31.05 | 0.0 | 0.0 | 0.0 | 31.05 | 31.05 | 31.05 | 0.0 | 0.0 |
618+
| 15 | 30 | 10 October 2026 | 02 October 2025 | 202.92 | 0.0 | 8.97 | 0.0 | 0.0 | 8.97 | 8.97 | 8.97 | 0.0 | 0.0 |
619+
| 16 | 31 | 10 November 2026 | 02 October 2025 | 202.92 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
620+
| 17 | 30 | 10 December 2026 | 02 October 2025 | 202.92 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
621+
| 18 | 31 | 10 January 2027 | 02 October 2025 | 202.92 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
622+
| 19 | 31 | 10 February 2027 | 02 October 2025 | 195.75 | 7.17 | 0.0 | 0.0 | 0.0 | 7.17 | 7.17 | 7.17 | 0.0 | 0.0 |
623+
| 20 | 28 | 10 March 2027 | 02 October 2025 | 156.6 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
624+
| 21 | 31 | 10 April 2027 | 02 October 2025 | 117.45 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
625+
| 22 | 30 | 10 May 2027 | 02 October 2025 | 78.3 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
626+
| 23 | 31 | 10 June 2027 | 02 October 2025 | 39.15 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
627+
| 24 | 30 | 10 July 2027 | 02 October 2025 | 0.0 | 39.15 | 0.0 | 0.0 | 0.0 | 39.15 | 39.15 | 39.15 | 0.0 | 0.0 |
628+
And Loan Repayment schedule has the following data in Total row:
629+
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
630+
| 733.56 | 18.33 | 0.0 | 0.0 | 751.89 | 751.89 | 751.89 | 0.0 | 0.0 |
631+
And Loan Transactions tab has the following data:
632+
| Transaction date | Transaction Type | Amount | Principal | Interest | Fees | Penalties | Loan Balance | Reverted | Replayed |
633+
| 10 July 2025 | Disbursement | 733.56 | 0.0 | 0.0 | 0.0 | 0.0 | 733.56 | false | false |
634+
| 29 July 2025 | Repayment | 540.0 | 530.64 | 9.36 | 0.0 | 0.0 | 202.92 | false | false |
635+
| 10 August 2025 | Accrual Activity | 9.36 | 0.0 | 9.36 | 0.0 | 0.0 | 0.0 | false | false |
636+
| 02 October 2025 | Merchant Issued Refund | 635.23 | 202.92 | 8.97 | 0.0 | 0.0 | 0.0 | false | false |
637+
| 02 October 2025 | Interest Refund | 17.07 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | false | false |
638+
| 02 October 2025 | Accrual | 18.33 | 0.0 | 18.33 | 0.0 | 0.0 | 0.0 | false | false |
639+
| 02 October 2025 | Accrual Activity | 8.97 | 0.0 | 8.97 | 0.0 | 0.0 | 0.0 | false | false |

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/calc/ProgressiveEMICalculator.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,21 @@ private static void moveOutstandingAmountsFromPeriodsBeforeReAging(final List<Re
690690
}
691691

692692
private void calculateLastUnpaidRepaymentPeriodEMI(ProgressiveLoanInterestScheduleModel scheduleModel, LocalDate tillDate) {
693+
694+
Money totalDuePaidDiff = scheduleModel.getTotalDuePrincipal().minus(scheduleModel.getTotalPaidPrincipal());
695+
// Remove outstanding principal from EMI in case outstanding principal is greater than total due minus paid
696+
// diff. We need this extra step in case excessive principal was paid with LAST_INSTALLMENT strategy
697+
scheduleModel.repaymentPeriods().forEach(rp -> {
698+
if (rp.getOutstandingPrincipal().isGreaterThan(totalDuePaidDiff)) {
699+
Money delta = rp.getOutstandingPrincipal().minus(totalDuePaidDiff);
700+
rp.setEmi(rp.getEmi().minus(delta));
701+
Money minimumEMI = MathUtil.plus(rp.getPaidInterest(), rp.getPaidPrincipal());
702+
if (rp.getEmi().isLessThan(minimumEMI)) {
703+
rp.setEmi(minimumEMI);
704+
}
705+
}
706+
});
707+
693708
Optional<RepaymentPeriod> findLastUnpaidRepaymentPeriod = scheduleModel.repaymentPeriods().stream().filter(rp -> !rp.isFullyPaid())
694709
.reduce((first, second) -> second);
695710

0 commit comments

Comments
 (0)