This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 0daf42ec33 FINERACT-2124: Fix final income accrual calculation with
multiple fee charges
0daf42ec33 is described below
commit 0daf42ec330b3534317c88701ab3a1dffdc261ed
Author: mariiaKraievska <[email protected]>
AuthorDate: Wed Jul 30 18:38:29 2025 +0300
FINERACT-2124: Fix final income accrual calculation with multiple fee
charges
---
.../src/test/resources/features/LoanCharge.feature | 291 +++++++++++++++++++++
.../portfolio/loanaccount/domain/Loan.java | 3 +-
.../domain/LoanTransactionRepository.java | 13 +
...tLoanRepaymentScheduleTransactionProcessor.java | 11 +
.../loanaccount/service/LoanChargeService.java | 3 +-
.../service/LoanAccrualsProcessingServiceImpl.java | 10 +-
6 files changed, 328 insertions(+), 3 deletions(-)
diff --git
a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
index f1de715dae..6bbb3de045 100644
--- a/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
+++ b/fineract-e2e-tests-runner/src/test/resources/features/LoanCharge.feature
@@ -7486,3 +7486,294 @@ Feature: LoanCharge
| Name | isPenalty | Payment due at |
Due as of | Calculation type | Due | Paid | Waived | Outstanding |
| Installment flat fee | false | Installment Fee |
| Flat | 60.0 | 20.0 | 0.0 | 40.0 |
| Installment percentage interest fee | false | Installment Fee |
| % Interest | 0.17 | 0.05 | 0.0 | 0.12 |
+
+ @TestRailId:C3890
+ Scenario: Cumulative loan - Verify final income accrual with multiple fee
charges created successfully
+ When Admin sets the business date to "01 January 2024"
+ When Admin creates a client with random data
+ When Admin creates a fully customized loan with the following data:
+ | 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
|
+ | LP2_DOWNPAYMENT | 01 October 2023 | 100 | 0
| DECLINING_BALANCE | SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS |
6 | MONTHS | 1 | MONTHS
| 6 | 0 | 0 | 0
|
DUE_PENALTY_INTEREST_PRINCIPAL_FEE_IN_ADVANCE_PENALTY_INTEREST_PRINCIPAL_FEE |
+ And Admin successfully approves the loan on "01 January 2024" with "100"
amount and expected disbursement date on "01 January 2024"
+ When Admin successfully disburse the loan on "01 January 2024" with "100"
EUR transaction amount
+ When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 April 2024" due
date and 50 EUR transaction amount
+ When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 April 2024" due
date and 35 EUR transaction amount
+ When Admin adds "LOAN_FIXED_RETURNED_PAYMENT_FEE" due date charge with "06
April 2024" due date and 10 EUR transaction amount
+ When Admin adds "LOAN_FIXED_RETURNED_PAYMENT_FEE" due date charge with "10
April 2024" due date and 5 EUR transaction amount
+ When Admin adds "LOAN_INSTALLMENT_FEE_FLAT" installment charge with 10
amount
+ Then Loan Repayment schedule has 7 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan | Principal
due | Interest | Fees | Penalties | Due | Paid | In advance | Late |
Outstanding |
+ | | | 01 January 2024 | | 100.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 0 | 01 January 2024 | | 75.0 | 25.0
| 0.0 | 0.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0
|
+ | 2 | 31 | 01 February 2024 | | 63.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 0.0 | 0.0 | 0.0 | 22.0
|
+ | 3 | 29 | 01 March 2024 | | 51.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 0.0 | 0.0 | 0.0 | 22.0
|
+ | 4 | 31 | 01 April 2024 | | 39.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 0.0 | 0.0 | 0.0 | 22.0
|
+ | 5 | 30 | 01 May 2024 | | 27.0 | 12.0
| 0.0 | 110.0 | 0.0 | 122.0 | 0.0 | 0.0 | 0.0 | 122.0
|
+ | 6 | 31 | 01 June 2024 | | 15.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 0.0 | 0.0 | 0.0 | 22.0
|
+ | 7 | 30 | 01 July 2024 | | 0.0 | 15.0
| 0.0 | 10.0 | 0.0 | 25.0 | 0.0 | 0.0 | 0.0 | 25.0
|
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 100.0 | 0.0 | 160.0 | 0.0 | 260.0 | 0.0 | 0.0
| 0.0 | 260.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted | Replayed |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 |
0.0 | 0.0 | 100.0 | false | false |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as
of | Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee |
| Flat | 60.0 | 0.0 | 0.0 | 60.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 50.0 | 0.0 | 0.0 | 50.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 35.0 | 0.0 | 0.0 | 35.0 |
+ | Fixed Returned payment fee | false | Specified due date | 06 April
2024 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
+ | Fixed Returned payment fee | false | Specified due date | 10 April
2024 | Flat | 5.0 | 0.0 | 0.0 | 5.0 |
+ When Admin sets the business date to "02 January 2024"
+ When Admin runs inline COB job for Loan
+ When Admin sets the business date to "03 March 2024"
+ When Admin runs inline COB job for Loan
+ And Customer makes "AUTOPAY" repayment on "03 March 2024" with 260.0 EUR
transaction amount
+ Then Loan Repayment schedule has 7 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan |
Principal due | Interest | Fees | Penalties | Due | Paid | In advance |
Late | Outstanding |
+ | | | 01 January 2024 | | 100.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 0 | 01 January 2024 | 03 March 2024 | 75.0 | 25.0
| 0.0 | 0.0 | 0.0 | 25.0 | 25.0 | 0.0 | 25.0 |
0.0 |
+ | 2 | 31 | 01 February 2024 | 03 March 2024 | 63.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 22.0 | 0.0 | 22.0 |
0.0 |
+ | 3 | 29 | 01 March 2024 | 03 March 2024 | 51.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 22.0 | 0.0 | 22.0 |
0.0 |
+ | 4 | 31 | 01 April 2024 | 03 March 2024 | 39.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 22.0 | 22.0 | 0.0 |
0.0 |
+ | 5 | 30 | 01 May 2024 | 03 March 2024 | 27.0 | 12.0
| 0.0 | 110.0 | 0.0 | 122.0 | 122.0 | 122.0 | 0.0 |
0.0 |
+ | 6 | 31 | 01 June 2024 | 03 March 2024 | 15.0 | 12.0
| 0.0 | 10.0 | 0.0 | 22.0 | 22.0 | 22.0 | 0.0 |
0.0 |
+ | 7 | 30 | 01 July 2024 | 03 March 2024 | 0.0 | 15.0
| 0.0 | 10.0 | 0.0 | 25.0 | 25.0 | 25.0 | 0.0 |
0.0 |
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 100.0 | 0.0 | 160.0 | 0.0 | 260.0 | 260.0 | 191.0
| 69.0 | 0.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted | Replayed |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 |
0.0 | 0.0 | 100.0 | false | false |
+ | 01 February 2024 | Accrual | 10.0 | 0.0 | 0.0 |
10.0 | 0.0 | 0.0 | false | false |
+ | 01 March 2024 | Accrual | 10.0 | 0.0 | 0.0 |
10.0 | 0.0 | 0.0 | false | false |
+ | 03 March 2024 | Repayment | 260.0 | 100.0 | 0.0 |
160.0 | 0.0 | 0.0 | false | false |
+ | 03 March 2024 | Accrual | 140.0 | 0.0 | 0.0 |
140.0 | 0.0 | 0.0 | false | false |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as
of | Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee |
| Flat | 60.0 | 60.0 | 0.0 | 0.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 50.0 | 50.0 | 0.0 | 0.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 35.0 | 35.0 | 0.0 | 0.0 |
+ | Fixed Returned payment fee | false | Specified due date | 06 April
2024 | Flat | 10.0 | 10.0 | 0.0 | 0.0 |
+ | Fixed Returned payment fee | false | Specified due date | 10 April
2024 | Flat | 5.0 | 5.0 | 0.0 | 0.0 |
+
+ @TestRailId:C3891
+ Scenario: Progressive loan - Verify final income accrual with multiple fee
charges created successfully
+ When Admin sets the business date to "01 January 2024"
+ When Admin creates a client with random data
+ When Admin creates a fully customized loan with the following data:
+ | 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 |
+ | LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30 | 01 January 2024 | 100
| 7 | DECLINING_BALANCE | DAILY
| EQUAL_INSTALLMENTS | 6 | MONTHS | 1
| MONTHS | 6 | 0 | 0
| 0 | ADVANCED_PAYMENT_ALLOCATION |
+ And Admin successfully approves the loan on "01 January 2024" with "100"
amount and expected disbursement date on "01 January 2024"
+ When Admin successfully disburse the loan on "01 January 2024" with "100"
EUR transaction amount
+ When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 April 2024" due
date and 50 EUR transaction amount
+ When Admin adds "LOAN_SNOOZE_FEE" due date charge with "06 April 2024" due
date and 35 EUR transaction amount
+ When Admin adds "LOAN_FIXED_RETURNED_PAYMENT_FEE" due date charge with "06
April 2024" due date and 10 EUR transaction amount
+ When Admin adds "LOAN_FIXED_RETURNED_PAYMENT_FEE" due date charge with "10
April 2024" due date and 5 EUR transaction amount
+ When Admin adds "LOAN_INSTALLMENT_FEE_FLAT" installment charge with 10
amount
+ Then Loan Repayment schedule has 6 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan | Principal
due | Interest | Fees | Penalties | Due | Paid | In advance | Late |
Outstanding |
+ | | | 01 January 2024 | | 100.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 31 | 01 February 2024 | | 83.57 | 16.43
| 0.58 | 10.0 | 0.0 | 27.01 | 0.0 | 0.0 | 0.0 | 27.01
|
+ | 2 | 29 | 01 March 2024 | | 67.05 | 16.52
| 0.49 | 10.0 | 0.0 | 27.01 | 0.0 | 0.0 | 0.0 | 27.01
|
+ | 3 | 31 | 01 April 2024 | | 50.43 | 16.62
| 0.39 | 10.0 | 0.0 | 27.01 | 0.0 | 0.0 | 0.0 | 27.01
|
+ | 4 | 30 | 01 May 2024 | | 33.71 | 16.72
| 0.29 | 110.0 | 0.0 | 127.01 | 0.0 | 0.0 | 0.0 | 127.01
|
+ | 5 | 31 | 01 June 2024 | | 16.9 | 16.81
| 0.2 | 10.0 | 0.0 | 27.01 | 0.0 | 0.0 | 0.0 | 27.01
|
+ | 6 | 30 | 01 July 2024 | | 0.0 | 16.9
| 0.1 | 10.0 | 0.0 | 27.0 | 0.0 | 0.0 | 0.0 | 27.0
|
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 100.0 | 2.05 | 160.0 | 0.0 | 262.05 | 0.0 | 0.0
| 0.0 | 262.05 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted | Replayed |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 |
0.0 | 0.0 | 100.0 | false | false |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as
of | Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee |
| Flat | 60.0 | 0.0 | 0.0 | 60.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 50.0 | 0.0 | 0.0 | 50.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 35.0 | 0.0 | 0.0 | 35.0 |
+ | Fixed Returned payment fee | false | Specified due date | 06 April
2024 | Flat | 10.0 | 0.0 | 0.0 | 10.0 |
+ | Fixed Returned payment fee | false | Specified due date | 10 April
2024 | Flat | 5.0 | 0.0 | 0.0 | 5.0 |
+ When Admin sets the business date to "02 January 2024"
+ When Admin runs inline COB job for Loan
+ When Admin sets the business date to "03 March 2024"
+ When Admin runs inline COB job for Loan
+ And Customer makes "AUTOPAY" repayment on "03 March 2024" with 262.05 EUR
transaction amount
+ Then Loan Repayment schedule has 6 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan |
Principal due | Interest | Fees | Penalties | Due | Paid | In advance |
Late | Outstanding |
+ | | | 01 January 2024 | | 100.0 |
| | 0.0 | | 0.0 | 0.0 | |
| |
+ | 1 | 31 | 01 February 2024 | 03 March 2024 | 83.57 | 16.43
| 0.58 | 10.0 | 0.0 | 27.01 | 27.01 | 0.0 | 27.01
| 0.0 |
+ | 2 | 29 | 01 March 2024 | 03 March 2024 | 67.05 | 16.52
| 0.49 | 10.0 | 0.0 | 27.01 | 27.01 | 0.0 | 27.01
| 0.0 |
+ | 3 | 31 | 01 April 2024 | 03 March 2024 | 50.43 | 16.62
| 0.39 | 10.0 | 0.0 | 27.01 | 27.01 | 27.01 | 0.0
| 0.0 |
+ | 4 | 30 | 01 May 2024 | 03 March 2024 | 33.71 | 16.72
| 0.29 | 110.0 | 0.0 | 127.01 | 127.01 | 127.01 | 0.0
| 0.0 |
+ | 5 | 31 | 01 June 2024 | 03 March 2024 | 16.9 | 16.81
| 0.2 | 10.0 | 0.0 | 27.01 | 27.01 | 27.01 | 0.0
| 0.0 |
+ | 6 | 30 | 01 July 2024 | 03 March 2024 | 0.0 | 16.9
| 0.1 | 10.0 | 0.0 | 27.0 | 27.0 | 27.0 | 0.0
| 0.0 |
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 100.0 | 2.05 | 160.0 | 0.0 | 262.05 | 262.05 |
208.03 | 54.02 | 0.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted | Replayed |
+ | 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 |
0.0 | 0.0 | 100.0 | false | false |
+ | 02 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 03 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 04 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 05 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 06 January 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 07 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 08 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 09 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 10 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 11 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 12 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 13 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 14 January 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 15 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 16 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 17 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 18 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 19 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 20 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 21 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 22 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 23 January 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 24 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 25 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 26 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 27 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 28 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 29 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 30 January 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 31 January 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 01 February 2024 | Accrual | 10.02 | 0.0 | 0.02 |
10.0 | 0.0 | 0.0 | false | false |
+ | 02 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 03 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 04 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 05 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 06 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 07 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 08 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 09 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 10 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 11 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 12 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 13 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 14 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 15 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 16 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 17 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 18 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 19 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 20 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 21 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 22 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 23 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 24 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 25 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 26 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 27 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 28 February 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 29 February 2024 | Accrual | 0.02 | 0.0 | 0.02 |
0.0 | 0.0 | 0.0 | false | false |
+ | 01 March 2024 | Accrual | 10.02 | 0.0 | 0.02 |
10.0 | 0.0 | 0.0 | false | false |
+ | 02 March 2024 | Accrual | 0.01 | 0.0 | 0.01 |
0.0 | 0.0 | 0.0 | false | false |
+ | 03 March 2024 | Repayment | 262.05 | 100.0 | 2.05 |
160.0 | 0.0 | 0.0 | false | false |
+ | 03 March 2024 | Accrual | 140.97 | 0.0 | 0.97 |
140.0 | 0.0 | 0.0 | false | false |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as
of | Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee |
| Flat | 60.0 | 60.0 | 0.0 | 0.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 50.0 | 50.0 | 0.0 | 0.0 |
+ | Snooze fee | false | Specified due date | 06 April
2024 | Flat | 35.0 | 35.0 | 0.0 | 0.0 |
+ | Fixed Returned payment fee | false | Specified due date | 06 April
2024 | Flat | 10.0 | 10.0 | 0.0 | 0.0 |
+ | Fixed Returned payment fee | false | Specified due date | 10 April
2024 | Flat | 5.0 | 5.0 | 0.0 | 0.0 |
+
+ @TestRailId:C3892
+ Scenario: Verify installment fee charge allocation when loan has down
payment, additional installment and re-aging
+ When Admin sets the business date to "01 January 2024"
+ When Admin creates a client with random data
+ When Admin creates a fully customized loan with the following data:
+ | 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 |
+ | LP2_DOWNPAYMENT_ADV_PMT_ALLOC_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL |
01 January 2024 | 1000 | 0 | FLAT |
SAME_AS_REPAYMENT_PERIOD | EQUAL_INSTALLMENTS | 45 | DAYS
| 15 | DAYS | 3 | 0
| 0 | 0 |
ADVANCED_PAYMENT_ALLOCATION |
+ And Admin successfully approves the loan on "01 January 2024" with "1000"
amount and expected disbursement date on "01 January 2024"
+ When Admin successfully disburse the loan on "01 January 2024" with "1000"
EUR transaction amount
+ When Admin adds "LOAN_INSTALLMENT_FEE_FLAT" installment charge with 10
amount
+ Then Loan Repayment schedule has 4 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan | Principal
due | Interest | Fees | Penalties | Due | Paid | In advance | Late |
Outstanding |
+ | | | 01 January 2024 | | 1000.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 0 | 01 January 2024 | | 750.0 | 250.0
| 0.0 | 0.0 | 0.0 | 250.0 | 0.0 | 0.0 | 0.0 | 250.0
|
+ | 2 | 15 | 16 January 2024 | | 500.0 | 250.0
| 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0 | 260.0
|
+ | 3 | 15 | 31 January 2024 | | 250.0 | 250.0
| 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0 | 260.0
|
+ | 4 | 15 | 15 February 2024 | | 0.0 | 250.0
| 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0 | 260.0
|
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 1000.0 | 0.0 | 30.0 | 0.0 | 1030.0 | 0.0 | 0.0
| 0.0 | 1030.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted | Replayed |
+ | 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 |
0.0 | 0.0 | 1000.0 | false | false |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as of |
Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee | | Flat
| 30.0 | 0.0 | 0.0 | 30.0 |
+ When Admin sets the business date to "01 January 2024"
+ And Customer makes "AUTOPAY" repayment on "01 January 2024" with 250 EUR
transaction amount
+ Then Loan Repayment schedule has 4 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan |
Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late
| Outstanding |
+ | | | 01 January 2024 | | 1000.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 |
250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0
| 0.0 |
+ | 2 | 15 | 16 January 2024 | | 500.0 |
250.0 | 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0
| 260.0 |
+ | 3 | 15 | 31 January 2024 | | 250.0 |
250.0 | 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0
| 260.0 |
+ | 4 | 15 | 15 February 2024 | | 0.0 |
250.0 | 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0
| 260.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted |
+ | 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 |
0.0 | 0.0 | 1000.0 | false |
+ | 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 |
0.0 | 0.0 | 750.0 | false |
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 1000.0 | 0.0 | 30.0 | 0.0 | 1030.0 | 250.0 | 0.0
| 0.0 | 780.0 |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as of |
Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee | | Flat
| 30.0 | 0.0 | 0.0 | 30.0 |
+ When Admin sets the business date to "20 February 2024"
+ When Admin makes "REPAYMENT_ADJUSTMENT_CHARGEBACK" chargeback with 125 EUR
transaction amount
+ Then Loan Repayment schedule has 5 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan |
Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late
| Outstanding |
+ | | | 01 January 2024 | | 1000.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 |
250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0
| 0.0 |
+ | 2 | 15 | 16 January 2024 | | 500.0 |
250.0 | 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0
| 260.0 |
+ | 3 | 15 | 31 January 2024 | | 250.0 |
250.0 | 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0
| 260.0 |
+ | 4 | 15 | 15 February 2024 | | 0.0 |
250.0 | 0.0 | 10.0 | 0.0 | 260.0 | 0.0 | 0.0 | 0.0
| 260.0 |
+ | 5 | 5 | 20 February 2024 | | 0.0 |
125.0 | 0.0 | 0.0 | 0.0 | 125.0 | 0.0 | 0.0 | 0.0
| 125.0 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted |
+ | 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 |
0.0 | 0.0 | 1000.0 | false |
+ | 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 |
0.0 | 0.0 | 750.0 | false |
+ | 20 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 |
0.0 | 0.0 | 875.0 | false |
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 1125.0 | 0.0 | 30.0 | 0.0 | 1155.0 | 250.0 | 0.0
| 0.0 | 905.0 |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as of |
Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee | | Flat
| 30.0 | 0.0 | 0.0 | 30.0 |
+ When Admin sets the business date to "21 February 2024"
+ When Admin creates a Loan re-aging transaction by Loan external ID with
the following data:
+ | frequencyNumber | frequencyType | startDate | numberOfInstallments
|
+ | 2 | MONTHS | 10 March 2024 | 3
|
+ Then Loan Repayment schedule has 8 periods, with the following data for
periods:
+ | Nr | Days | Date | Paid date | Balance of loan |
Principal due | Interest | Fees | Penalties | Due | Paid | In advance |
Late | Outstanding |
+ | | | 01 January 2024 | | 1000.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
+ | 1 | 0 | 01 January 2024 | 01 January 2024 | 750.0 |
250.0 | 0.0 | 0.0 | 0.0 | 250.0 | 250.0 | 0.0 | 0.0
| 0.0 |
+ | 2 | 15 | 16 January 2024 | | 750.0 |
0.0 | 0.0 | 10.0 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0
| 10.0 |
+ | 3 | 15 | 31 January 2024 | | 750.0 |
0.0 | 0.0 | 10.0 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0
| 10.0 |
+ | 4 | 15 | 15 February 2024 | | 750.0 |
0.0 | 0.0 | 10.0 | 0.0 | 10.0 | 0.0 | 0.0 | 0.0
| 10.0 |
+ | 5 | 5 | 20 February 2024 | 21 February 2024 | 875.0 |
0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0
| 0.0 |
+ | 6 | 19 | 10 March 2024 | | 583.33 |
291.67 | 0.0 | 0.0 | 0.0 | 291.67 | 0.0 | 0.0 | 0.0
| 291.67 |
+ | 7 | 61 | 10 May 2024 | | 291.66 |
291.67 | 0.0 | 0.0 | 0.0 | 291.67 | 0.0 | 0.0 | 0.0
| 291.67 |
+ | 8 | 61 | 10 July 2024 | | 0.0 |
291.66 | 0.0 | 0.0 | 0.0 | 291.66 | 0.0 | 0.0 | 0.0
| 291.66 |
+ Then Loan Transactions tab has the following data:
+ | Transaction date | Transaction Type | Amount | Principal | Interest |
Fees | Penalties | Loan Balance | Reverted |
+ | 01 January 2024 | Disbursement | 1000.0 | 0.0 | 0.0 |
0.0 | 0.0 | 1000.0 | false |
+ | 01 January 2024 | Repayment | 250.0 | 250.0 | 0.0 |
0.0 | 0.0 | 750.0 | false |
+ | 20 February 2024 | Chargeback | 125.0 | 125.0 | 0.0 |
0.0 | 0.0 | 875.0 | false |
+ | 21 February 2024 | Re-age | 875.0 | 875.0 | 0.0 |
0.0 | 0.0 | 0.0 | false |
+ Then Loan Repayment schedule has the following data in Total row:
+ | Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
+ | 1125.0 | 0.0 | 30.0 | 0.0 | 1155.0 | 250.0 | 0.0
| 0.0 | 905.0 |
+ Then Loan Charges tab has the following data:
+ | Name | isPenalty | Payment due at | Due as of |
Calculation type | Due | Paid | Waived | Outstanding |
+ | Installment flat fee | false | Installment Fee | | Flat
| 30.0 | 0.0 | 0.0 | 30.0 |
\ No newline at end of file
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 07cc2744c0..b878cbf4b7 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -1541,7 +1541,8 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom<Long> {
List<LoanRepaymentScheduleInstallment> installments =
getRepaymentScheduleInstallments();
int numberOfInstallments = 0;
for (final LoanRepaymentScheduleInstallment installment :
installments) {
- if (!installment.isRecalculatedInterestComponent()) {
+ if (!installment.isRecalculatedInterestComponent() &&
!installment.isAdditional() && !installment.isDownPayment()
+ && !installment.isReAged()) {
numberOfInstallments++;
}
}
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
index a41b352ea1..73bc3aeb2b 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
@@ -281,6 +281,19 @@ public interface LoanTransactionRepository extends
JpaRepository<LoanTransaction
""")
BigDecimal findChargeAccrualAmount(@Param("loanCharge") LoanCharge
loanCharge);
+ @Query("""
+ SELECT COALESCE(SUM(CASE WHEN lt.typeOf =
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL
THEN lcpb.amount
+ WHEN lt.typeOf =
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType.ACCRUAL_ADJUSTMENT
THEN -lcpb.amount
+ ELSE 0 END), 0)
+ FROM LoanChargePaidBy lcpb
+ JOIN lcpb.loanTransaction lt
+ WHERE lcpb.loanCharge = :loanCharge
+ AND lcpb.installmentNumber = :installmentNumber
+ AND lt.reversed = false
+ """)
+ BigDecimal findChargeAccrualAmountByInstallment(@Param("loanCharge")
LoanCharge loanCharge,
+ @Param("installmentNumber") Integer installmentNumber);
+
@Query("""
SELECT COALESCE(SUM(lt.unrecognizedIncomePortion), 0)
FROM LoanChargePaidBy lcpb
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
index b733c459da..714366d737 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/AbstractLoanRepaymentScheduleTransactionProcessor.java
@@ -725,6 +725,8 @@ public abstract class
AbstractLoanRepaymentScheduleTransactionProcessor implemen
final Integer installmentNumber) {
Money amountRemaining = chargeAmount;
+ final Set<LoanCharge> chargesThatCannotBeFullyPaidByOneInstallment =
new HashSet<>();
+
while (amountRemaining.isGreaterThanZero()) {
final LoanCharge unpaidCharge =
findEarliestUnpaidChargeFromUnOrderedSet(charges, chargeAmount.getCurrency());
Money feeAmount = chargeAmount.zero();
@@ -734,6 +736,12 @@ public abstract class
AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (unpaidCharge == null) {
break; // All are trache charges
}
+
+ // If we've already determined this charge cannot be fully paid by
one installment, skip it
+ if
(chargesThatCannotBeFullyPaidByOneInstallment.contains(unpaidCharge)) {
+ charges.remove(unpaidCharge);
+ }
+
final Money amountPaidTowardsCharge =
unpaidCharge.updatePaidAmountBy(amountRemaining, installmentNumber, feeAmount);
if (!amountPaidTowardsCharge.isZero()) {
Set<LoanChargePaidBy> chargesPaidBies =
loanTransaction.getLoanChargesPaid();
@@ -750,6 +758,8 @@ public abstract class
AbstractLoanRepaymentScheduleTransactionProcessor implemen
chargesPaidBies.add(loanChargePaidBy);
}
amountRemaining =
amountRemaining.minus(amountPaidTowardsCharge);
+ } else {
+ chargesThatCannotBeFullyPaidByOneInstallment.add(unpaidCharge);
}
}
@@ -786,6 +796,7 @@ public abstract class
AbstractLoanRepaymentScheduleTransactionProcessor implemen
}
}
}
+
if (earliestUnpaidCharge == null || (chargePerInstallment != null &&
DateUtils.isAfter(earliestUnpaidCharge.getDueLocalDate(),
chargePerInstallment.getRepaymentInstallment().getDueDate())))
{
earliestUnpaidCharge = installemntCharge;
diff --git
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java
index 5462781fc5..1297440340 100644
---
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java
+++
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeService.java
@@ -655,7 +655,8 @@ public class LoanChargeService {
private List<LoanInstallmentCharge> generateInstallmentLoanCharges(final
Loan loan, final LoanCharge loanCharge) {
final List<LoanInstallmentCharge> loanChargePerInstallments = new
ArrayList<>();
if (loanCharge.isInstalmentFee()) {
- List<LoanRepaymentScheduleInstallment> installments =
loan.getRepaymentScheduleInstallments();
+ final List<LoanRepaymentScheduleInstallment> installments =
loan.getRepaymentScheduleInstallments().stream()
+ .filter(i -> !i.isDownPayment() && !i.isAdditional() &&
!i.isReAged()).toList();
for (final LoanRepaymentScheduleInstallment installment :
installments) {
BigDecimal amount;
if (loanCharge.getChargeCalculation().isFlat()) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
index 4f3aeb9b04..cd171730cd 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java
@@ -620,7 +620,15 @@ public class LoanAccrualsProcessingServiceImpl implements
LoanAccrualsProcessing
final Money unrecognizedWaived = MathUtil
.toMoney(loanTransactionRepository.findChargeUnrecognizedWaivedAmount(loanCharge,
tillDate), currency);
final Money transactionWaived = MathUtil.minusToZero(waived,
unrecognizedWaived);
- final Money transactionAccrued =
MathUtil.toMoney(loanTransactionRepository.findChargeAccrualAmount(loanCharge),
currency);
+ // For installment fees, use installment-specific accrual amount
+ final Money transactionAccrued;
+ if (installmentFee && installmentChargeId != null) {
+ transactionAccrued = MathUtil.toMoney(
+
loanTransactionRepository.findChargeAccrualAmountByInstallment(loanCharge,
dueInstallment.getInstallmentNumber()),
+ currency);
+ } else {
+ transactionAccrued =
MathUtil.toMoney(loanTransactionRepository.findChargeAccrualAmount(loanCharge),
currency);
+ }
chargeData.setTransactionAccrued(transactionAccrued);
chargeData.setChargeAccrued(MathUtil.minusToZero(transactionAccrued,
transactionWaived));