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 68b35024f6 FINERACT-2326: Fix payment allocation when current period
is closed
68b35024f6 is described below
commit 68b35024f66e9b3bc9a2a177a8b9ad0a887559ae
Author: mark.vituska <[email protected]>
AuthorDate: Tue Jul 22 15:29:37 2025 +0200
FINERACT-2326: Fix payment allocation when current period is closed
---
.../test/resources/features/EMICalculation.feature | 22 ++---
.../test/resources/features/LoanChargeOff.feature | 12 +--
.../features/LoanContractTermination.feature | 12 +--
.../resources/features/LoanInterestPause.feature | 21 ++---
...dvancedPaymentScheduleTransactionProcessor.java | 97 ++++++++++++++++------
5 files changed, 104 insertions(+), 60 deletions(-)
diff --git
a/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature
b/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature
index 8ed1a8e9ef..94f9652c2f 100644
---
a/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature
+++
b/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature
@@ -2949,12 +2949,12 @@ Feature: EMI calculation and repayment schedule checks
for interest bearing loan
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 |
16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0
| 0.0 |
| 2 | 29 | 01 March 2024 | | 67.05 |
16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 10.0 | 0.0 | 10.0
| 7.01 |
| 3 | 31 | 01 April 2024 | | 50.53 |
16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
- | 4 | 30 | 01 May 2024 | | 33.91 |
16.62 | 0.39 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
- | 5 | 31 | 01 June 2024 | | 17.19 |
16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
- | 6 | 30 | 01 July 2024 | | 0.0 |
17.19 | 0.2 | 0.0 | 0.0 | 17.39 | 0.0 | 0.0 | 0.0
| 17.39 |
+ | 4 | 30 | 01 May 2024 | | 33.81 |
16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
+ | 5 | 31 | 01 June 2024 | | 17.0 |
16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
+ | 6 | 30 | 01 July 2024 | | 0.0 |
17.0 | 0.1 | 0.0 | 0.0 | 17.1 | 0.0 | 0.0 | 0.0
| 17.1 |
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.44 | 0.0 | 0.0 | 102.44 | 27.01 | 0.0
| 10.0 | 75.43 |
+ | 100.0 | 2.15 | 0.0 | 0.0 | 102.15 | 27.01 | 0.0
| 10.0 | 75.14 |
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 |
@@ -2969,12 +2969,12 @@ Feature: EMI calculation and repayment schedule checks
for interest bearing loan
| 1 | 31 | 01 February 2024 | 01 February 2024 | 83.57 |
16.43 | 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0
| 0.0 |
| 2 | 29 | 01 March 2024 | | 67.05 |
16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 10.0 | 0.0 | 10.0
| 7.01 |
| 3 | 31 | 01 April 2024 | | 50.53 |
16.52 | 0.49 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
- | 4 | 30 | 01 May 2024 | | 33.95 |
16.58 | 0.43 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
- | 5 | 31 | 01 June 2024 | | 17.27 |
16.68 | 0.33 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
- | 6 | 30 | 01 July 2024 | | 0.0 |
17.27 | 0.24 | 0.0 | 0.0 | 17.51 | 0.0 | 0.0 | 0.0
| 17.51 |
+ | 4 | 30 | 01 May 2024 | | 33.81 |
16.72 | 0.29 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
+ | 5 | 31 | 01 June 2024 | | 17.0 |
16.81 | 0.2 | 0.0 | 0.0 | 17.01 | 0.0 | 0.0 | 0.0
| 17.01 |
+ | 6 | 30 | 01 July 2024 | | 0.0 |
17.0 | 0.1 | 0.0 | 0.0 | 17.1 | 0.0 | 0.0 | 0.0
| 17.1 |
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.56 | 0.0 | 0.0 | 102.56 | 27.01 | 0.0
| 10.0 | 75.55 |
+ | 100.0 | 2.15 | 0.0 | 0.0 | 102.15 | 27.01 | 0.0
| 10.0 | 75.14 |
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 |
@@ -7890,10 +7890,10 @@ Feature: EMI calculation and repayment schedule checks
for interest bearing loan
| 3 | 31 | 01 April 2025 | | 4661.9 | 1112.7
| 576.13 | 0.0 | 0.0 | 1688.83 | 0.0 | 0.0 | 0.0 |
1688.83 |
| 4 | 30 | 01 May 2025 | | 3549.2 | 1112.7
| 576.13 | 0.0 | 0.0 | 1688.83 | 0.0 | 0.0 | 0.0 |
1688.83 |
| 5 | 31 | 01 June 2025 | | 2436.5 | 1112.7
| 576.13 | 0.0 | 0.0 | 1688.83 | 0.0 | 0.0 | 0.0 |
1688.83 |
- | 6 | 30 | 01 July 2025 | | 0.0 | 2436.5
| 896.66 | 0.0 | 0.0 | 3333.16 | 0.0 | 0.0 | 0.0 |
3333.16 |
+ | 6 | 30 | 01 July 2025 | | 0.0 | 2436.5
| 576.13 | 0.0 | 0.0 | 3012.63 | 0.0 | 0.0 | 0.0 |
3012.63 |
And Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
- | 8000.0 | 3777.31 | 0.0 | 0.0 | 11777.31 | 0.05 | 0.0
| 0.04 | 11777.26 |
+ | 8000.0 | 3456.78 | 0.0 | 0.0 | 11456.78 | 0.05 | 0.0
| 0.04 | 11456.73 |
@TestRailId:C3657
Scenario: Verify tranche interest bearing progressive loan that expects two
tranches with repayment and undo last disbursement - UC1
@@ -9631,4 +9631,4 @@ Feature: EMI calculation and repayment schedule checks
for interest bearing loan
| Type | Account code | Account name | Debit | Credit
|
| ASSET | 112601 | Loans Receivable | | 906.25
|
| ASSET | 112603 | Interest/Fee Receivable | | 16.87
|
- | LIABILITY | 145023 | Suspense/Clearing account | 923.12 |
|
\ No newline at end of file
+ | LIABILITY | 145023 | Suspense/Clearing account | 923.12 |
|
diff --git
a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
index 777d384c13..50f13bff10 100644
---
a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
+++
b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
@@ -6005,18 +6005,18 @@ Feature: Charge-off
| 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 | 01 March 2024 | 83.57 | 16.43
| 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 17.01 |
0.0 |
- | 2 | 29 | 01 March 2024 | 01 March 2024 | 67.05 | 16.52
| 0.49 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 |
0.0 |
- | 3 | 30 | 31 March 2024 | | 0.0 | 67.05
| 0.18 | 0.0 | 0.0 | 67.23 | 35.98 | 35.98 | 0.0 |
31.25 |
+ | 2 | 29 | 01 March 2024 | 01 March 2024 | 67.14 | 16.43
| 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 |
0.0 |
+ | 3 | 30 | 31 March 2024 | | 0.0 | 67.14
| 0.0 | 0.0 | 0.0 | 67.14 | 35.98 | 35.98 | 0.0 |
31.16 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
- | 100.0 | 1.25 | 0.0 | 0.0 | 101.25 | 70.0 | 35.98
| 17.01 | 31.25 |
+ | 100.0 | 1.16 | 0.0 | 0.0 | 101.16 | 70.0 | 35.98
| 17.01 | 31.16 |
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 March 2024 | Repayment | 70.0 | 68.93 | 1.07
| 0.0 | 0.0 | 31.07 | false | false |
+ | 01 March 2024 | Repayment | 70.0 | 68.84 | 1.16
| 0.0 | 0.0 | 31.16 | false | false |
| 31 March 2024 | Accrual | 1.72 | 0.0 | 1.72
| 0.0 | 0.0 | 0.0 | false | false |
- | 31 March 2024 | Accrual Adjustment | 0.47 | 0.0 | 0.47
| 0.0 | 0.0 | 0.0 | false | false |
- | 31 March 2024 | Charge-off | 31.25 | 31.07 | 0.18
| 0.0 | 0.0 | 0.0 | false | true |
+ | 31 March 2024 | Accrual Adjustment | 0.56 | 0.0 | 0.56
| 0.0 | 0.0 | 0.0 | false | false |
+ | 31 March 2024 | Charge-off | 31.16 | 31.16 | 0.0
| 0.0 | 0.0 | 0.0 | false | true |
And Global configuration
"is-principal-compounding-disabled-for-overdue-loans" is disabled
@TestRailId:C3499 @AdvancedPaymentAllocation
diff --git
a/fineract-e2e-tests-runner/src/test/resources/features/LoanContractTermination.feature
b/fineract-e2e-tests-runner/src/test/resources/features/LoanContractTermination.feature
index 979c704368..65cded5e73 100644
---
a/fineract-e2e-tests-runner/src/test/resources/features/LoanContractTermination.feature
+++
b/fineract-e2e-tests-runner/src/test/resources/features/LoanContractTermination.feature
@@ -1035,18 +1035,18 @@ Feature: Contract Termination
| 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 | 01 March 2024 | 83.57 | 16.43
| 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 17.01 |
0.0 |
- | 2 | 29 | 01 March 2024 | 01 March 2024 | 67.05 | 16.52
| 0.49 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 |
0.0 |
- | 3 | 30 | 31 March 2024 | | 0.0 | 67.05
| 0.18 | 0.0 | 0.0 | 67.23 | 35.98 | 35.98 | 0.0 |
31.25 |
+ | 2 | 29 | 01 March 2024 | 01 March 2024 | 67.14 | 16.43
| 0.58 | 0.0 | 0.0 | 17.01 | 17.01 | 0.0 | 0.0 |
0.0 |
+ | 3 | 30 | 31 March 2024 | | 0.0 | 67.14
| 0.0 | 0.0 | 0.0 | 67.14 | 35.98 | 35.98 | 0.0 |
31.16 |
Then Loan Repayment schedule has the following data in Total row:
| Principal due | Interest | Fees | Penalties | Due | Paid | In
advance | Late | Outstanding |
- | 100.0 | 1.25 | 0.0 | 0.0 | 101.25 | 70.0 | 35.98
| 17.01 | 31.25 |
+ | 100.0 | 1.16 | 0.0 | 0.0 | 101.16 | 70.0 | 35.98
| 17.01 | 31.16 |
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 March 2024 | Repayment | 70.0 | 68.93 | 1.07
| 0.0 | 0.0 | 31.07 | false | false |
+ | 01 March 2024 | Repayment | 70.0 | 68.84 | 1.16
| 0.0 | 0.0 | 31.16 | false | false |
| 31 March 2024 | Accrual | 1.72 | 0.0 | 1.72
| 0.0 | 0.0 | 0.0 | false | false |
- | 31 March 2024 | Accrual Adjustment | 0.47 | 0.0 | 0.47
| 0.0 | 0.0 | 0.0 | false | false |
- | 31 March 2024 | Contract Termination | 31.25 | 31.07 | 0.18
| 0.0 | 0.0 | 0.0 | false | true |
+ | 31 March 2024 | Accrual Adjustment | 0.56 | 0.0 | 0.56
| 0.0 | 0.0 | 0.0 | false | false |
+ | 31 March 2024 | Contract Termination | 31.16 | 31.16 | 0.0
| 0.0 | 0.0 | 0.0 | false | true |
And Global configuration
"is-principal-compounding-disabled-for-overdue-loans" is disabled
@TestRailId:C3738
diff --git
a/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestPause.feature
b/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestPause.feature
index e4a936805b..ca9806375f 100644
---
a/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestPause.feature
+++
b/fineract-e2e-tests-runner/src/test/resources/features/LoanInterestPause.feature
@@ -639,21 +639,21 @@ Feature: Loan interest pause on repayment schedule
And Customer makes "PAYOUT_REFUND" transaction with "AUTOPAY" payment type
on "22 April 2025" with 400 EUR transaction amount and self-generated
Idempotency key
When Admin sets the business date to "23 April 2025"
And Admin runs inline COB job for Loan
- And Admin makes Credit Balance Refund transaction on "23 April 2025" with
165.25 EUR transaction amount
+ And Admin makes Credit Balance Refund transaction on "23 April 2025" with
164.19 EUR transaction amount
When Admin sets the business date to "01 May 2025"
And Admin runs inline COB job for Loan
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 April 2025 | | 1000.0 |
| | 0.0 | | 0.0 | 0.0 | | |
|
- | 1 | 30 | 01 May 2025 | 21 April 2025 | 829.71 |
170.29 | 9.75 | 0.0 | 25.0 | 205.04 | 205.04 | 205.04 |
0.0 | 0.0 |
- | 2 | 31 | 01 June 2025 | 21 April 2025 | 649.67 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
- | 3 | 30 | 01 July 2025 | 21 April 2025 | 469.63 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
- | 4 | 31 | 01 August 2025 | 21 April 2025 | 289.59 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
- | 5 | 31 | 01 September 2025 | 22 April 2025 | 109.55 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
- | 6 | 30 | 01 October 2025 | 22 April 2025 | 0.0 |
109.55 | 0.0 | 0.0 | 0.0 | 109.55 | 109.55 | 109.55 |
0.0 | 0.0 |
+ | 1 | 30 | 01 May 2025 | 22 April 2025 | 828.65 |
171.35 | 9.75 | 0.0 | 25.0 | 206.1 | 206.1 | 206.1 |
0.0 | 0.0 |
+ | 2 | 31 | 01 June 2025 | 21 April 2025 | 648.61 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
+ | 3 | 30 | 01 July 2025 | 21 April 2025 | 468.57 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
+ | 4 | 31 | 01 August 2025 | 21 April 2025 | 288.53 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
+ | 5 | 31 | 01 September 2025 | 22 April 2025 | 108.49 |
180.04 | 0.0 | 0.0 | 0.0 | 180.04 | 180.04 | 180.04 |
0.0 | 0.0 |
+ | 6 | 30 | 01 October 2025 | 22 April 2025 | 0.0 |
108.49 | 1.06 | 0.0 | 0.0 | 109.55 | 109.55 | 109.55 |
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 |
- | 1000.0 | 9.75 | 0.0 | 25.0 | 1034.75 | 1034.75 |
1034.75 | 0.0 | 0.0 |
+ | 1000.0 | 10.81 | 0.0 | 25.0 | 1035.81 | 1035.81 |
1035.81 | 0.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 April 2025 | Disbursement | 1000.0 | 0.0 | 0.0
| 0.0 | 0.0 | 1000.0 | false | false |
@@ -672,8 +672,9 @@ Feature: Loan interest pause on repayment schedule
| 14 April 2025 | Accrual | 0.75 | 0.0 | 0.75
| 0.0 | 0.0 | 0.0 | false | false |
| 20 April 2025 | Accrual | 25.0 | 0.0 | 0.0
| 0.0 | 25.0 | 0.0 | false | false |
| 21 April 2025 | Repayment | 800.0 | 765.25 | 9.75
| 0.0 | 25.0 | 234.75 | false | false |
- | 22 April 2025 | Payout Refund | 400.0 | 234.75 | 0.0
| 0.0 | 0.0 | 0.0 | false | false |
- | 23 April 2025 | Credit Balance Refund | 165.25 | 0.0 | 0.0
| 0.0 | 0.0 | 0.0 | false | false |
+ | 22 April 2025 | Payout Refund | 400.0 | 234.75 | 1.06
| 0.0 | 0.0 | 0.0 | false | false |
+ | 22 April 2025 | Accrual | 1.06 | 0.0 | 1.06
| 0.0 | 0.0 | 0.0 | false | false |
+ | 23 April 2025 | Credit Balance Refund | 164.19 | 0.0 | 0.0
| 0.0 | 0.0 | 0.0 | false | false |
Then Loan status will be "CLOSED_OBLIGATIONS_MET"
@TestRailId:C3627
diff --git
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
index 1802981c13..f6e934adbc 100644
---
a/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
+++
b/fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/transactionprocessor/impl/AdvancedPaymentScheduleTransactionProcessor.java
@@ -1570,10 +1570,8 @@ public class AdvancedPaymentScheduleTransactionProcessor
extends AbstractLoanRep
} else {
lastOverdueBalanceChange = currentDate;
}
- if
(DateUtils.isBefore(ctx.getModel().lastOverdueBalanceChange(), toDate)) {
- emiCalculator.addBalanceCorrection(ctx.getModel(),
lastOverdueBalanceChange, aggregatedOverDuePrincipal.negated());
-
ctx.getModel().lastOverdueBalanceChange(lastOverdueBalanceChange);
- }
+ emiCalculator.addBalanceCorrection(ctx.getModel(),
lastOverdueBalanceChange, aggregatedOverDuePrincipal.negated());
+
ctx.getModel().lastOverdueBalanceChange(lastOverdueBalanceChange);
}
}
@@ -1599,10 +1597,32 @@ public class
AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
if (loanTransaction.isRepaymentLikeType() ||
loanTransaction.isInterestWaiver() || loanTransaction.isRecoveryRepayment()) {
loanTransaction.resetDerivedComponents();
}
+
calculateUnrecognizedInterestForClosedPeriodByInterestRecalculationStrategy(loanTransaction,
transactionCtx);
+
Money transactionAmountUnprocessed =
loanTransaction.getAmount(transactionCtx.getCurrency());
processTransaction(loanTransaction, transactionCtx,
transactionAmountUnprocessed);
}
+ private void
calculateUnrecognizedInterestForClosedPeriodByInterestRecalculationStrategy(LoanTransaction
loanTransaction,
+ TransactionCtx transactionCtx) {
+ if (transactionCtx instanceof ProgressiveTransactionCtx
progressiveTransactionCtx && progressiveTransactionCtx.isPrepayAttempt()
+ && loanTransaction.isRepaymentLikeType() &&
loanTransaction.getLoan().getLoanInterestRecalculationDetails()
+
.getPreCloseInterestCalculationStrategy().calculateTillRestFrequencyEnabled()) {
+ Optional<RepaymentPeriod> oCurrentRepaymentPeriod =
progressiveTransactionCtx.getModel().repaymentPeriods().stream()
+ .filter(rm ->
DateUtils.isDateInRangeFromInclusiveToExclusive(rm.getFromDate(),
rm.getDueDate(),
+ loanTransaction.getTransactionDate()))
+ .findFirst();
+ if (oCurrentRepaymentPeriod.isPresent() &&
oCurrentRepaymentPeriod.get().isFullyPaid()) {
+ RepaymentPeriod currentRepaymentPeriod =
oCurrentRepaymentPeriod.get();
+ OutstandingDetails outstandingAmountsTillDate = emiCalculator
+
.getOutstandingAmountsTillDate(progressiveTransactionCtx.getModel(),
currentRepaymentPeriod.getDueDate());
+ if
(outstandingAmountsTillDate.getOutstandingInterest().isGreaterThanZero()) {
+
currentRepaymentPeriod.setFutureUnrecognizedInterest(outstandingAmountsTillDate.getOutstandingInterest());
+ }
+ }
+ }
+ }
+
private LoanTransactionToRepaymentScheduleMapping getTransactionMapping(
List<LoanTransactionToRepaymentScheduleMapping>
transactionMappings, LoanTransaction loanTransaction,
LoanRepaymentScheduleInstallment currentInstallment,
MonetaryCurrency currency) {
@@ -1751,26 +1771,28 @@ public class
AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
final LoanRepaymentScheduleInstallment currentInstallment =
loan.getRelatedRepaymentScheduleInstallment(transactionDate);
if (!installments.isEmpty() &&
transactionDate.isBefore(loan.getMaturityDate())) {
- if (transactionCtx instanceof ProgressiveTransactionCtx
progressiveTransactionCtx
- &&
loanTransaction.getLoan().isInterestBearingAndInterestRecalculationEnabled()) {
- final BigDecimal interestOutstanding =
currentInstallment.getInterestOutstanding(loan.getCurrency()).getAmount();
- final BigDecimal newInterest =
emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
- currentInstallment.getDueDate(), transactionDate,
true).getAmount();
- if (interestOutstanding.compareTo(BigDecimal.ZERO) > 0 ||
newInterest.compareTo(BigDecimal.ZERO) > 0) {
- currentInstallment.updateInterestCharged(newInterest);
- }
- } else {
- final BigDecimal totalInterest =
currentInstallment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
- if (totalInterest.compareTo(BigDecimal.ZERO) > 0) {
- final long totalDaysInPeriod =
ChronoUnit.DAYS.between(currentInstallment.getFromDate(),
- currentInstallment.getDueDate());
- final long daysTillChargeOff =
ChronoUnit.DAYS.between(currentInstallment.getFromDate(), transactionDate);
+ if (currentInstallment.isNotFullyPaidOff()) {
+ if (transactionCtx instanceof ProgressiveTransactionCtx
progressiveTransactionCtx
+ &&
loanTransaction.getLoan().isInterestBearingAndInterestRecalculationEnabled()) {
+ final BigDecimal interestOutstanding =
currentInstallment.getInterestOutstanding(loan.getCurrency()).getAmount();
+ final BigDecimal newInterest =
emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
+ currentInstallment.getDueDate(), transactionDate,
true).getAmount();
+ if (interestOutstanding.compareTo(BigDecimal.ZERO) > 0 ||
newInterest.compareTo(BigDecimal.ZERO) > 0) {
+ currentInstallment.updateInterestCharged(newInterest);
+ }
+ } else {
+ final BigDecimal totalInterest =
currentInstallment.getInterestOutstanding(transactionCtx.getCurrency()).getAmount();
+ if (totalInterest.compareTo(BigDecimal.ZERO) > 0) {
+ final long totalDaysInPeriod =
ChronoUnit.DAYS.between(currentInstallment.getFromDate(),
+ currentInstallment.getDueDate());
+ final long daysTillChargeOff =
ChronoUnit.DAYS.between(currentInstallment.getFromDate(), transactionDate);
- final MathContext mc = MoneyHelper.getMathContext();
- final Money interestTillChargeOff =
Money.of(transactionCtx.getCurrency(), totalInterest
- .divide(BigDecimal.valueOf(totalDaysInPeriod),
mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc), mc);
+ final MathContext mc = MoneyHelper.getMathContext();
+ final Money interestTillChargeOff =
Money.of(transactionCtx.getCurrency(), totalInterest
+ .divide(BigDecimal.valueOf(totalDaysInPeriod),
mc).multiply(BigDecimal.valueOf(daysTillChargeOff), mc), mc);
-
currentInstallment.updateInterestCharged(interestTillChargeOff.getAmount());
+
currentInstallment.updateInterestCharged(interestTillChargeOff.getAmount());
+ }
}
}
@@ -1790,6 +1812,21 @@ public class AdvancedPaymentScheduleTransactionProcessor
extends AbstractLoanRep
currentInstallment.updatePrincipal(MathUtil.nullToZero(currentInstallment.getPrincipal()).add(futurePrincipal));
+ if (currentInstallment.isObligationsMet()) {
+ final BigDecimal futureOutstandingPrincipal =
futureInstallments.stream()
+ .map(installment ->
installment.getPrincipalOutstanding(transactionCtx.getCurrency()).getAmount())
+ .filter(Objects::nonNull).reduce(BigDecimal.ZERO,
BigDecimal::add);
+
+ final BigDecimal futureTotalPaidInAdvance =
futureInstallments.stream()
+
.map(LoanRepaymentScheduleInstallment::getTotalPaidInAdvance).filter(Objects::nonNull)
+ .reduce(ZERO, BigDecimal::add);
+
+ currentInstallment
+
.setPrincipalCompleted(MathUtil.nullToZero(currentInstallment.getPrincipal()).subtract(futureOutstandingPrincipal));
+ currentInstallment.setTotalPaidInAdvance(
+
MathUtil.nullToZero(currentInstallment.getTotalPaidInAdvance()).add(futureTotalPaidInAdvance));
+ }
+
final List<LoanRepaymentScheduleInstallment>
installmentsUpToTransactionDate = installments.stream()
.filter(installment ->
transactionDate.isAfter(installment.getFromDate()))
.collect(Collectors.toCollection(ArrayList::new));
@@ -1817,7 +1854,8 @@ public class AdvancedPaymentScheduleTransactionProcessor
extends AbstractLoanRep
}
}
- transactionCtx.getInstallments().stream().filter(installment ->
installment.getFromDate().isBefore(transactionDate))
+ transactionCtx.getInstallments().stream()
+ .filter(installment ->
installment.getFromDate().isBefore(transactionDate) &&
installment.isNotFullyPaidOff())
.filter(installment -> transactionsToBeReprocessed.stream()
.anyMatch(transaction ->
transaction.getLoanTransactionToRepaymentScheduleMappings().stream().anyMatch(
mapping ->
mapping.getInstallment().getInstallmentNumber().equals(installment.getInstallmentNumber()))))
@@ -1835,8 +1873,8 @@ public class AdvancedPaymentScheduleTransactionProcessor
extends AbstractLoanRep
newTransaction.updateLoan(loan);
loan.getLoanTransactions().add(newTransaction);
}
- loanBalanceService.updateLoanSummaryDerivedFields(loan);
}
+ loanBalanceService.updateLoanSummaryDerivedFields(loan);
}
}
@@ -2870,9 +2908,14 @@ public class AdvancedPaymentScheduleTransactionProcessor
extends AbstractLoanRep
.filter(repaymentPeriod ->
previousInstallmentsMapping.stream()
.anyMatch(installment ->
installment.getFromDate().equals(repaymentPeriod.getFromDate())))
.forEach(RepaymentPeriod::resetDerivedComponents);
- emiCalculator.addBalanceCorrection(transactionCtx.getModel(),
processTransaction.getTransactionDate(),
-
processTransaction.getPrincipalPortion(transactionCtx.getCurrency()));
- processSingleTransaction(processTransaction, transactionCtx);
+
+ LoanRepaymentScheduleInstallment installment =
processTransaction.getLoan()
+
.getRelatedRepaymentScheduleInstallment(processTransaction.getTransactionDate());
+ if (installment == null || installment.isNotFullyPaidOff()) {
+ emiCalculator.addBalanceCorrection(transactionCtx.getModel(),
processTransaction.getTransactionDate(),
+
processTransaction.getPrincipalPortion(transactionCtx.getCurrency()));
+ processSingleTransaction(processTransaction, transactionCtx);
+ }
}
}