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);
+            }
         }
     }
 

Reply via email to