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 157a492bc FINERACT-1981: fix progressive accruals on late repayment
157a492bc is described below

commit 157a492bcc59dd93327f60e787a2cf7b924ef570
Author: adam.magyari <[email protected]>
AuthorDate: Mon Feb 3 15:42:58 2025 +0100

    FINERACT-1981: fix progressive accruals on late repayment
---
 .../infrastructure/core/service/MathUtil.java      |   4 +
 .../test/resources/features/EMICalculation.feature | 125 +++++++++++++++++++++
 .../domain/LoanRepaymentScheduleInstallment.java   |  12 ++
 .../loanaccount/data/AccrualBalances.java          |  32 ++++++
 .../service/LoanAccrualsProcessingServiceImpl.java |  54 +++++++--
 5 files changed, 220 insertions(+), 7 deletions(-)

diff --git 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
index 9eab9a85e..a60b7e736 100644
--- 
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
+++ 
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/service/MathUtil.java
@@ -217,6 +217,10 @@ public final class MathUtil {
         return nullToZero(first).compareTo(nullToZero(second)) < 0;
     }
 
+    public static boolean isLessThanOrEqualTo(BigDecimal first, BigDecimal 
second) {
+        return nullToZero(first).compareTo(second) <= 0;
+    }
+
     public static boolean isGreaterThanOrEqualTo(BigDecimal first, BigDecimal 
second) {
         return nullToZero(first).compareTo(nullToZero(second)) >= 0;
     }
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 131e769c5..e9ae211db 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/EMICalculation.feature
@@ -5335,3 +5335,128 @@ Feature: EMI calculation and repayment schedule checks 
for interest bearing loan
       | 22 January 2021  | Accrual                | 5.7     | 0.0       | 5.7  
    | 0.0  | 0.0       | 0.0          | false    | false    |
     Then In Loan Transactions the "2"th Transaction has Transaction 
type="Merchant Issued Refund" and is reverted
     Then In Loan Transactions the "3"th Transaction has Transaction 
type="Interest Refund" and is reverted
+
+  @TestRailId:C3313
+  Scenario: Verify that due date charges after maturity date is recognized on 
repayment schedule
+    When Global config "charge-accrual-date" value set to "submitted-date"
+    When Admin sets the business date to "01 January 2024"
+    And Admin creates a client with random data
+    And Admin set 
"LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE"
 loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future 
installment allocation rule
+    And 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_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE
 | 01 January 2024   | 100            | 7                      | 
DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 4        
         | MONTHS                | 1              | MONTHS                 | 4  
                | 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"
+    And Admin successfully disburse the loan on "01 January 2024" with "100" 
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  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 31   | 01 February 2024 |           | 75.21           | 24.79     
    | 0.58     | 0.0  | 0.0       | 25.37 | 0.0  | 0.0        | 0.0  | 25.37    
   |
+      | 2  | 29   | 01 March 2024    |           | 50.28           | 24.93     
    | 0.44     | 0.0  | 0.0       | 25.37 | 0.0  | 0.0        | 0.0  | 25.37    
   |
+      | 3  | 31   | 01 April 2024    |           | 25.2            | 25.08     
    | 0.29     | 0.0  | 0.0       | 25.37 | 0.0  | 0.0        | 0.0  | 25.37    
   |
+      | 4  | 30   | 01 May 2024      |           | 0.0             | 25.2      
    | 0.15     | 0.0  | 0.0       | 25.35 | 0.0  | 0.0        | 0.0  | 25.35    
   |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In 
advance | Late | Outstanding |
+      | 100.0         | 1.46     | 0.0  | 0.0       | 101.46 | 0.0  | 0.0      
  | 0.0  | 101.46      |
+    And 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    |
+    When Admin sets the business date to "1 May 2024"
+    And Admin runs inline COB job for Loan
+    And Admin adds "LOAN_NSF_FEE" due date charge with "15 May 2024" due date 
and 10 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  |           | 100.0           |           
    |          | 0.0  |           | 0.0   | 0.0  |            |      |          
   |
+      | 1  | 31   | 01 February 2024 |           | 75.21           | 24.79     
    | 0.58     | 0.0  | 0.0       | 25.37 | 0.0  | 0.0        | 0.0  | 25.37    
   |
+      | 2  | 29   | 01 March 2024    |           | 50.42           | 24.79     
    | 0.58     | 0.0  | 0.0       | 25.37 | 0.0  | 0.0        | 0.0  | 25.37    
   |
+      | 3  | 31   | 01 April 2024    |           | 25.63           | 24.79     
    | 0.58     | 0.0  | 0.0       | 25.37 | 0.0  | 0.0        | 0.0  | 25.37    
   |
+      | 4  | 30   | 01 May 2024      |           | 0.0             | 25.63     
    | 0.58     | 0.0  | 0.0       | 26.21 | 0.0  | 0.0        | 0.0  | 26.21    
   |
+      | 5  | 14   | 15 May 2024      |           | 0.0             | 0.0       
    | 0.0      | 0.0  | 10.0      | 10.0  | 0.0  | 0.0        | 0.0  | 10.0     
   |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In 
advance | Late | Outstanding |
+      | 100.0         | 2.32     | 0.0  | 10.0      | 112.32 | 0.0  | 0.0      
  | 0.0  | 112.32      |
+    And 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    |
+      | 30 April 2024      | Accrual        | 1.87   | 0.0       | 1.87     | 
0.0  | 0.0       | 0.0          | false    | false    |
+    And Loan Charges tab has the following data:
+      | Name    | isPenalty | Payment due at     | Due as of   | Calculation 
type | Due  | Paid | Waived | Outstanding |
+      | NSF fee | true      | Specified due date | 15 May 2024 | Flat          
   | 10.0 | 0.0  | 0.0    | 10.0        |
+    When Admin sets the business date to "02 May 2024"
+    And Admin runs inline COB job for Loan
+    And 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    |
+      | 30 April 2024    | Accrual          | 1.87   | 0.0       | 1.87     | 
0.0  | 0.0       | 0.0          | false    | false    |
+      | 01 May 2024      | Accrual          | 10.45  | 0.0       | 0.45     | 
0.0  | 10.0      | 0.0          | false    | false    |
+
+  @TestRailId:C3333
+  Scenario: Verify that due date charges after maturity date with inline COB 
run is recognized on repayment schedule
+    When Admin sets the business date to "01 January 2024"
+    And Admin creates a client with random data
+    And Admin set 
"LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE"
 loan product "DEFAULT" transaction type to "NEXT_INSTALLMENT" future 
installment allocation rule
+    And 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_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE
 | 01 January 2024   | 100            | 7                      | 
DECLINING_BALANCE | DAILY                       | EQUAL_INSTALLMENTS | 1        
         | MONTHS                | 1              | MONTHS                 | 1  
                | 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"
+    And Admin successfully disburse the loan on "01 January 2024" with "100" 
EUR transaction amount
+    And Admin runs inline COB job for Loan
+    Then Loan Repayment schedule has 1 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 |           | 0.0             | 100.0     
    | 0.58     | 0.0  | 0.0       | 100.58 | 0.0  | 0.0        | 0.0  | 100.58  
    |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In 
advance | Late | Outstanding |
+      | 100.0         | 0.58     | 0.0  | 0.0       | 100.58 | 0.0  | 0.0      
  | 0.0  | 100.58      |
+    And 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    |
+    When Admin sets the business date to "15 February 2024"
+    And Admin adds "LOAN_NSF_FEE" due date charge with "15 February 2024" due 
date and 10 EUR transaction amount
+    When Admin sets the business date to "16 February 2024"
+    And Admin runs inline COB job for Loan
+    Then Loan Repayment schedule has 2 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 |           | 0.0             | 100.0     
    | 0.58     | 0.0  | 0.0       | 100.58 | 0.0  | 0.0        | 0.0  | 100.58  
    |
+      | 2  | 14   | 15 February 2024 |           | 0.0             | 0.0       
    | 0.0      | 0.0  | 10.0      | 10.0   | 0.0  | 0.0        | 0.0  | 10.0    
    |
+    And Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due    | Paid | In 
advance | Late | Outstanding |
+      | 100.0         | 0.58     | 0.0  | 10.0      | 110.58 | 0.0  | 0.0      
  | 0.0  | 110.58      |
+    And 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          | 0.02   | 0.0       | 0.02     | 
0.0  | 0.0       | 0.0          | false    | false    |
+      | 15 February 2024 | Accrual          | 10.0   | 0.0       | 0.0      | 
0.0  | 10.0      | 0.0          | false    | false    |
+    And Loan Charges tab has the following data:
+      | Name    | isPenalty | Payment due at     | Due as of        | 
Calculation type | Due  | Paid | Waived | Outstanding |
+      | NSF fee | true      | Specified due date | 15 February 2024 | Flat     
        | 10.0 | 0.0  | 0.0    | 10.0        |
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
index 00e2687e7..76d223337 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallment.java
@@ -721,6 +721,18 @@ public class LoanRepaymentScheduleInstallment extends 
AbstractAuditableWithUTCDa
         this.penaltyAccrued = 
MathUtil.zeroToNull(MathUtil.toBigDecimal(penalityCharges));
     }
 
+    public void setInterestAccrued(BigDecimal interestAccrued) {
+        this.interestAccrued = interestAccrued;
+    }
+
+    public void setFeeAccrued(BigDecimal feeAccrued) {
+        this.feeAccrued = feeAccrued;
+    }
+
+    public void setPenaltyAccrued(BigDecimal penaltyAccrued) {
+        this.penaltyAccrued = penaltyAccrued;
+    }
+
     public void updateObligationsMet(final MonetaryCurrency currency, final 
LocalDate transactionDate) {
         if (!this.obligationsMet && getTotalOutstanding(currency).isZero()) {
             this.obligationsMet = true;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/AccrualBalances.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/AccrualBalances.java
new file mode 100644
index 000000000..52b9e7cb0
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/AccrualBalances.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.loanaccount.data;
+
+import java.math.BigDecimal;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class AccrualBalances {
+
+    private BigDecimal interestPortion = BigDecimal.ZERO;
+    private BigDecimal feePortion = BigDecimal.ZERO;
+    private BigDecimal penaltyPortion = BigDecimal.ZERO;
+}
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 b33a17f11..c07eccad4 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
@@ -56,6 +56,7 @@ import 
org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
 import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import org.apache.fineract.organisation.monetary.domain.Money;
+import org.apache.fineract.portfolio.loanaccount.data.AccrualBalances;
 import org.apache.fineract.portfolio.loanaccount.data.AccrualChargeData;
 import org.apache.fineract.portfolio.loanaccount.data.AccrualPeriodData;
 import org.apache.fineract.portfolio.loanaccount.data.AccrualPeriodsData;
@@ -698,13 +699,52 @@ public class LoanAccrualsProcessingServiceImpl implements 
LoanAccrualsProcessing
         LoanRepaymentScheduleInstallment lastInstallment = 
loan.getLastLoanRepaymentScheduleInstallment();
         LocalDate lastDueDate = lastInstallment.getDueDate();
         if (isProgressiveAccrual(loan)) {
-            AccrualPeriodsData accrualPeriods = calculateAccrualAmounts(loan, 
lastDueDate, true);
-            for (AccrualPeriodData period : accrualPeriods.getPeriods()) {
-                Money interestAccrued = period.getTransactionAccrued();
-                Money feeAccrued = period.getFeeTransactionAccrued();
-                Money penaltyAccrued = period.getPenaltyTransactionAccrued();
-                LoanRepaymentScheduleInstallment installment = 
loan.fetchRepaymentScheduleInstallment(period.getInstallmentNumber());
-                installment.updateAccrualPortion(interestAccrued, feeAccrued, 
penaltyAccrued);
+            AccrualBalances accrualBalances = new AccrualBalances();
+            accrualTransactions.forEach(lt -> {
+                switch (lt.getTypeOf()) {
+                    case ACCRUAL -> {
+                        
accrualBalances.setFeePortion(MathUtil.add(accrualBalances.getFeePortion(), 
lt.getFeeChargesPortion()));
+                        
accrualBalances.setPenaltyPortion(MathUtil.add(accrualBalances.getPenaltyPortion(),
 lt.getPenaltyChargesPortion()));
+                        
accrualBalances.setInterestPortion(MathUtil.add(accrualBalances.getInterestPortion(),
 lt.getInterestPortion()));
+                    }
+                    case ACCRUAL_ADJUSTMENT -> {
+                        
accrualBalances.setFeePortion(MathUtil.subtract(accrualBalances.getFeePortion(),
 lt.getFeeChargesPortion()));
+                        accrualBalances
+                                
.setPenaltyPortion(MathUtil.subtract(accrualBalances.getPenaltyPortion(), 
lt.getPenaltyChargesPortion()));
+                        accrualBalances
+                                
.setInterestPortion(MathUtil.subtract(accrualBalances.getInterestPortion(), 
lt.getInterestPortion()));
+                    }
+                    default -> throw new IllegalStateException("Unexpected 
value: " + lt.getTypeOf());
+                }
+            });
+            for (LoanRepaymentScheduleInstallment installment : 
loan.getRepaymentScheduleInstallments()) {
+                BigDecimal maximumAccruableInterest = 
MathUtil.nullToZero(installment.getInterestCharged());
+                BigDecimal maximumAccruableFee = 
MathUtil.nullToZero(installment.getFeeChargesCharged());
+                BigDecimal maximumAccruablePenalty = 
MathUtil.nullToZero(installment.getPenaltyCharges());
+
+                if (MathUtil.isLessThanOrEqualTo(maximumAccruableInterest, 
accrualBalances.getInterestPortion())) {
+                    installment.setInterestAccrued(maximumAccruableInterest);
+                    
accrualBalances.setInterestPortion(accrualBalances.getInterestPortion().subtract(maximumAccruableInterest));
+                } else {
+                    
installment.setInterestAccrued(accrualBalances.getInterestPortion());
+                    accrualBalances.setInterestPortion(BigDecimal.ZERO);
+                }
+
+                if (MathUtil.isLessThanOrEqualTo(maximumAccruableFee, 
accrualBalances.getFeePortion())) {
+                    installment.setFeeAccrued(maximumAccruableFee);
+                    
accrualBalances.setFeePortion(accrualBalances.getFeePortion().subtract(maximumAccruableFee));
+                } else {
+                    installment.setFeeAccrued(accrualBalances.getFeePortion());
+                    accrualBalances.setFeePortion(BigDecimal.ZERO);
+                }
+
+                if (MathUtil.isLessThanOrEqualTo(maximumAccruablePenalty, 
accrualBalances.getPenaltyPortion())) {
+                    installment.setPenaltyAccrued(maximumAccruablePenalty);
+                    
accrualBalances.setPenaltyPortion(accrualBalances.getPenaltyPortion().subtract(maximumAccruablePenalty));
+                } else {
+                    
installment.setPenaltyAccrued(accrualBalances.getPenaltyPortion());
+                    accrualBalances.setPenaltyPortion(BigDecimal.ZERO);
+                }
             }
         } else {
             List<LoanRepaymentScheduleInstallment> installments = 
loan.getRepaymentScheduleInstallments();

Reply via email to