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 51433ffb6 FINERACT-2148: Update instalments interest with zero after 
charge off with interest recalculation enabled
51433ffb6 is described below

commit 51433ffb6600c97fb26b905b403f36473b50bf7a
Author: Oleksii Novikov <[email protected]>
AuthorDate: Thu Dec 5 18:14:42 2024 +0200

    FINERACT-2148: Update instalments interest with zero after charge off with 
interest recalculation enabled
---
 .../test/data/loanproduct/DefaultLoanProduct.java  |   1 +
 .../global/LoanProductGlobalInitializerStep.java   |  17 ++
 .../fineract/test/stepdef/loan/LoanStepDef.java    |  29 ++
 .../fineract/test/support/TestContextKey.java      |   1 +
 .../test/resources/features/LoanChargeOff.feature  | 310 +++++++++++++++++++++
 ...tLoanRepaymentScheduleTransactionProcessor.java |   8 +-
 ...dvancedPaymentScheduleTransactionProcessor.java |  63 ++++-
 .../LoanWritePlatformServiceJpaRepositoryImpl.java |  12 +-
 8 files changed, 436 insertions(+), 5 deletions(-)

diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
index 0951115bb..5783e6194 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/DefaultLoanProduct.java
@@ -73,6 +73,7 @@ public enum DefaultLoanProduct implements LoanProduct {
     
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM,
 //
     
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_IR_DAILY_TILL_PRECLOSE_LAST_INSTALLMENT_STRATEGY,
 //
     
LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION,
 //
+    
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR,
 //
     ;
 
     @Override
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
index 6200b34ef..5bd692f3a 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
@@ -1088,6 +1088,23 @@ public class LoanProductGlobalInitializerStep implements 
FineractGlobalInitializ
         TestContext.INSTANCE.set(
                 
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_CUSTOM_PAYMENT_ALLOCATION_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE,
                 
responseLoanProductsRequestLP2AdvCustomPaymentAllocationInterestRecalculationDaily36030MultiDisburse);
+
+        // LP2 + interest recalculation + zero-interest chargeOff behaviour + 
progressive loan schedule + horizontal
+        // 
(LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR)
+        final String name51 = 
DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR
+                .getName();
+
+        final PostLoanProductsRequest 
loanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule
 = loanProductsRequestFactory
+                .defaultLoanProductsRequestLP2InterestDailyRecalculation()//
+                .name(name51)//
+                .paymentAllocation(List.of(//
+                        createPaymentAllocation("DEFAULT", 
"NEXT_INSTALLMENT")))
+                .chargeOffBehaviour("ZERO_INTEREST");//
+        final Response<PostLoanProductsResponse> 
responseLoanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule
 = loanProductsApi
+                
.createLoanProduct(loanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule).execute();
+        TestContext.INSTANCE.set(
+                
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR,
+                
responseLoanProductsRequestAdvCustomZeroInterestChargeOffBehaviourProgressiveLoanSchedule);
     }
 
     public static AdvancedPaymentData createPaymentAllocation(String 
transactionType, String futureInstallmentAllocationRule,
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
index e1b4cdcb9..9a28d7454 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.test.stepdef.loan;
 
 import static 
org.apache.fineract.test.data.TransactionProcessingStrategyCode.ADVANCED_PAYMENT_ALLOCATION;
+import static 
org.apache.fineract.test.data.loanproduct.DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.awaitility.Awaitility.await;
 import static org.junit.Assert.assertNotNull;
@@ -2766,6 +2767,34 @@ public class LoanStepDef extends AbstractStepDef {
         eventCheckHelper.createLoanEventCheck(response);
     }
 
+    @When("Admin creates a new zero charge-off Loan with date: {string}")
+    public void 
createLoanWithInterestRecalculationAndZeroChargeOffBehaviour(final String date) 
throws IOException {
+        final Response<PostClientsResponse> clientResponse = 
testContext().get(TestContextKey.CLIENT_CREATE_RESPONSE);
+        final Long clientId = clientResponse.body().getClientId();
+
+        final DefaultLoanProduct product = DefaultLoanProduct
+                
.valueOf(LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR.getName());
+        final Long loanProductId = loanProductResolver.resolve(product);
+
+        final PostLoansRequest loansRequest = 
loanRequestFactory.defaultLoansRequest(clientId).productId(loanProductId)
+                .principal(new 
BigDecimal(100)).numberOfRepayments(6).submittedOnDate(date).expectedDisbursementDate(date)
+                .loanTermFrequency(6)//
+                .loanTermFrequencyType(LoanTermFrequencyType.MONTHS.value)//
+                .repaymentEvery(1)//
+                .repaymentFrequencyType(RepaymentFrequencyType.MONTHS.value)//
+                .interestRateFrequencyType(3)//
+                .interestRatePerPeriod(new BigDecimal(7))//
+                .interestType(InterestType.DECLINING_BALANCE.value)//
+                
.interestCalculationPeriodType(InterestCalculationPeriodTime.DAILY.value)//
+                
.transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION.value);
+
+        final Response<PostLoansResponse> response = 
loansApi.calculateLoanScheduleOrSubmitLoanApplication(loansRequest, 
"").execute();
+        testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
+        ErrorHelper.checkSuccessfulApiCall(response);
+
+        eventCheckHelper.createLoanEventCheck(response);
+    }
+
     private void performLoanDisbursementAndVerifyStatus(final long loanId, 
final PostLoansLoanIdRequest disburseRequest)
             throws IOException {
         final Response<PostLoansLoanIdResponse> loanDisburseResponse = 
loansApi.stateTransitions(loanId, disburseRequest, "disburse")
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
index 81f3aa120..7fe029330 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/support/TestContextKey.java
@@ -104,6 +104,7 @@ public abstract class TestContextKey {
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP1_ADVANCED_PAYMENT_ALLOCATION_PROGRESSIVE_LOAN_SCHEDULE_HORIZONTAL
 = "loanProductCreateResponseLP1ProgressiveLoanScheduleHorizontal";
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_DAILY_TILL_PRECLOSE_WHOLE_TERM
 = 
"loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmi36030InterestRecalculationSameAsRepTillPreCloseWholeTerm";
     public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION
 = 
"loanProductCreateResponseLP2AdvancedPaymentInterestDailyEmiActualActualInterestRefundFInterestRecalculation";
+    public static final String 
DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR
 = 
"loanProductCreateResponseLP2AdvancedPaymentInterestDailyInterestRecalculationZeroInterestChargeOffBehaviour";
     public static final String CHARGE_FOR_LOAN_PERCENT_LATE_CREATE_RESPONSE = 
"ChargeForLoanPercentLateCreateResponse";
     public static final String 
CHARGE_FOR_LOAN_PERCENT_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = 
"ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
     public static final String 
CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = 
"ChargeForLoanPercentProcessingCreateResponse";
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 546cdc657..28bd5583b 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanChargeOff.feature
@@ -1611,3 +1611,313 @@ Feature: Charge-off
     Then Loan Repayment schedule has the following data in Total row:
       | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
       | 1000          | 12.22    | 0    | 0         | 1012.22 | 0    | 0       
   | 0    | 1012.22     |
+
+  Scenario: Charge-off on due date when loan behaviour is zero-interest and 
interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    And Admin does charge-off the loan on "1 March 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.14           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.13           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.12           | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.11           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.11     
    | 0.0      | 0.0   | 0.0       | 16.11      | 0.0  | 0.0        | 0.0  | 
16.11           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 1.16     | 0    | 0         | 101.16  | 0    | 0       
   | 0    | 101.16      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 01 March 2023    | Charge-off       | 101.16  | 100.0     | 1.16     | 
0.0   | 0.0       | 0.0          |
+
+  Scenario: Charge-off after installment date when loan behaviour is 
zero-interest and interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    And Admin does charge-off the loan on "28 February 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.12           | 16.45     
    | 0.56     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.11           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.1            | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.09           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.09     
    | 0.0      | 0.0   | 0.0       | 16.09      | 0.0  | 0.0        | 0.0  | 
16.09           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 1.14     | 0    | 0         | 101.14  | 0    | 0       
   | 0    | 101.14      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 28 February 2023 | Charge-off       | 101.14  | 100.0     | 1.14     | 
0.0   | 0.0       | 0.0          |
+
+  Scenario: Charge-off in the middle of installment period when loan behaviour 
is zero-interest and interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    And Admin does charge-off the loan on "14 February 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 66.83           | 16.74     
    | 0.27     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 49.82           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 32.81           | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 15.8            | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 15.8      
    | 0.0      | 0.0   | 0.0       | 15.8       | 0.0  | 0.0        | 0.0  | 
15.8            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 0.85     | 0    | 0         | 100.85  | 0    | 0       
   | 0    | 100.85      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 14 February 2023 | Charge-off       | 100.85  | 100.0     | 0.85     | 
0.0   | 0.0       | 0.0          |
+
+  Scenario: Charge-off after maturity date when loan behaviour is 
zero-interest and interestRecalculation = true
+    When Admin sets the business date to "1 August 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    And Admin does charge-off the loan on "15 July 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.14           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.71           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 34.28           | 16.43     
       | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 17.85           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 17.85     
    | 0.58     | 0.0   | 0.0       | 18.43      | 0.0  | 0.0        | 0.0  | 
18.43           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 3.48     | 0    | 0         | 103.48  | 0    | 0       
   | 0    | 103.48      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 15 July 2023     | Charge-off       | 103.48  | 100.0     | 3.48     | 
0.0   | 0.0       | 0.0          |
+
+  Scenario: Charge-off when charge is added before the charge-off date, loan 
behaviour is zero-interest and interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    When Admin adds "LOAN_SNOOZE_FEE" due date charge with "27 February 2023" 
due date and 3 EUR transaction amount
+    And Admin does charge-off the loan on "28 February 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.12           | 16.45     
    | 0.56     | 3.0   | 0.0       | 20.01   | 0.0  | 0.0        | 0.0  | 20.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.11           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.1            | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.09           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.09     
    | 0.0      | 0.0   | 0.0       | 16.09      | 0.0  | 0.0        | 0.0  | 
16.09           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 1.14     | 3.0  | 0         | 104.14  | 0    | 0       
   | 0    | 104.14      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 28 February 2023 | Charge-off       | 104.14  | 100.0     | 1.14     | 
3.0   | 0.0       | 0.0          |
+
+  Scenario: Charge-off when charge is added on charge-off date, loan behaviour 
is zero-interest and interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    When Admin adds "LOAN_SNOOZE_FEE" due date charge with "28 February 2023" 
due date and 3 EUR transaction amount
+    And Admin does charge-off the loan on "28 February 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.12           | 16.45     
    | 0.56     | 3.0   | 0.0       | 20.01   | 0.0  | 0.0        | 0.0  | 20.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.11           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.1            | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.09           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.09     
    | 0.0      | 0.0   | 0.0       | 16.09      | 0.0  | 0.0        | 0.0  | 
16.09           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 1.14     | 3.0  | 0         | 104.14  | 0    | 0       
   | 0    | 104.14      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 28 February 2023 | Charge-off       | 104.14  | 100.0     | 1.14     | 
3.0   | 0.0       | 0.0          |
+
+  Scenario: Charge-off when charge is added after the charge off date, loan 
behaviour is zero-interest and interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     |      |            |      | 0.0   
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.05           | 16.52     
    | 0.49     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.43           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.71           | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.9            | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.9      
    | 0.1      | 0.0   | 0.0       | 17.0       | 0.0  | 0.0        | 0.0  | 
17.0            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.05     | 0    | 0         | 102.05  | 0    | 0       
   | 0    | 102.05      |
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
EUR transaction amount
+    When Admin adds "LOAN_SNOOZE_FEE" due date charge with "1 March 2023" due 
date and 3 EUR transaction amount
+    And Admin does charge-off the loan on "28 February 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.12           | 16.45     
    | 0.56     | 3.0   | 0.0       | 20.01   | 0.0  | 0.0        | 0.0  | 20.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.11           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.1            | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.09           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.09     
    | 0.0      | 0.0   | 0.0       | 16.09      | 0.0  | 0.0        | 0.0  | 
16.09           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 1.14     | 3.0  | 0         | 104.14  | 0    | 0       
   | 0    | 104.14      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 28 February 2023 | Charge-off       | 101.14  | 100.0     | 1.14     | 
0.0   | 0.0       | 0.0          |
+
+  Scenario: Undo the charge-off when loan behaviour is zero-interest and 
interestRecalculation = true
+    When Admin sets the business date to "1 March 2023"
+    And Admin creates a client with random data
+    When Admin creates a new zero charge-off Loan with date: "1 January 2023"
+    And Admin successfully approves the loan on "1 January 2023" with "100" 
amount and expected disbursement date on "1 January 2023"
+    And Admin successfully disburse the loan on "1 January 2023" with "100" 
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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.14           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.52           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.8            | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.99           | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.99     
    | 0.1      | 0.0   | 0.0       | 17.09      | 0.0  | 0.0        | 0.0  | 
17.09           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.14     | 0    | 0         | 102.14  | 0    | 0       
   | 0    | 102.14      |
+    And Admin does charge-off the loan on "14 February 2023"
+    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 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 66.83           | 16.74     
    | 0.27     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 49.82           | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 32.81           | 17.01     
       | 0.0      | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 15.8            | 17.01     
    | 0.0      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 15.8      
    | 0.0      | 0.0   | 0.0       | 15.8       | 0.0  | 0.0        | 0.0  | 
15.8            |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 0.85     | 0    | 0         | 100.85  | 0    | 0       
   | 0    | 100.85      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 14 February 2023 | Charge-off       | 100.85  | 100.0     | 0.85     | 
0.0   | 0.0       | 0.0          |
+    And Admin does a charge-off undo the 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 January 2023  |           | 100.0           |           
    |          | 0.0   |           | 0.0     | 0.0  |            |      |       
      |
+      | 1  | 31   | 01 February 2023 |           | 83.57           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 2  | 28   | 01 March 2023    |           | 67.14           | 16.43     
    | 0.58     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 3  | 31   | 01 April 2023    |           | 50.52           | 16.62     
    | 0.39     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 17.01 
      |
+      | 4  | 30   | 01 May 2023      |           | 33.8            | 16.72     
       | 0.29     | 0.0   | 0.0       | 17.01   | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 5  | 31   | 01 June 2023     |           | 16.99           | 16.81     
    | 0.2      | 0.0   | 0.0       | 17.01      | 0.0  | 0.0        | 0.0  | 
17.01           |
+      | 6  | 30   | 01 July 2023     |           | 0.0             | 16.99     
    | 0.1      | 0.0   | 0.0       | 17.09      | 0.0  | 0.0        | 0.0  | 
17.09           |
+    Then Loan Repayment schedule has the following data in Total row:
+      | Principal due | Interest | Fees | Penalties | Due     | Paid | In 
advance | Late | Outstanding |
+      | 100           | 2.14     | 0    | 0         | 102.14  | 0    | 0       
   | 0    | 102.14      |
+    Then Loan Transactions tab has the following data:
+      | Transaction date | Transaction Type | Amount  | Principal | Interest | 
Fees  | Penalties | Loan Balance |
+      | 01 January 2023  | Disbursement     | 100.0   | 0.0       | 0.0      | 
0.0   | 0.0       | 100.0        |
+      | 14 February 2023 | Charge-off       | 100.85  | 100.0     | 0.85     | 
0.0   | 0.0       | 0.0          |
+
+
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 3f1430c11..dbe127bfe 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
@@ -255,6 +255,7 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
             case WRITEOFF -> handleWriteOff(loanTransaction, 
ctx.getCurrency(), ctx.getInstallments());
             case REFUND_FOR_ACTIVE_LOAN -> handleRefund(loanTransaction, 
ctx.getCurrency(), ctx.getInstallments(), ctx.getCharges());
             case CHARGEBACK -> handleChargeback(loanTransaction, ctx);
+            case CHARGE_OFF -> handleChargeOff(loanTransaction, ctx);
             default -> {
                 Money transactionAmountUnprocessed = 
handleTransactionAndCharges(loanTransaction, ctx.getCurrency(), 
ctx.getInstallments(),
                         ctx.getCharges(), null, false);
@@ -394,7 +395,7 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
                 principalPortion = 
principalPortion.plus(currentInstallment.getPrincipalOutstanding(currency));
                 interestPortion = 
interestPortion.plus(currentInstallment.getInterestOutstanding(currency));
                 feeChargesPortion = 
feeChargesPortion.plus(currentInstallment.getFeeChargesOutstanding(currency));
-                penaltychargesPortion = 
penaltychargesPortion.plus(currentInstallment.getPenaltyChargesCharged(currency));
+                penaltychargesPortion = 
penaltychargesPortion.plus(currentInstallment.getPenaltyChargesOutstanding(currency));
             }
         }
 
@@ -786,6 +787,11 @@ public abstract class 
AbstractLoanRepaymentScheduleTransactionProcessor implemen
         processCreditTransaction(loanTransaction, ctx.getOverpaymentHolder(), 
ctx.getCurrency(), ctx.getInstallments());
     }
 
+    private void handleChargeOff(LoanTransaction loanTransaction, 
TransactionCtx transactionCtx) {
+        
recalculateChargeOffTransaction(transactionCtx.getChangedTransactionDetail(), 
loanTransaction, transactionCtx.getCurrency(),
+                transactionCtx.getInstallments());
+    }
+
     protected void handleCreditBalanceRefund(LoanTransaction loanTransaction, 
MonetaryCurrency currency,
             List<LoanRepaymentScheduleInstallment> installments, MoneyHolder 
overpaidAmountHolder) {
         processCreditTransaction(loanTransaction, overpaidAmountHolder, 
currency, installments);
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 c13b33e1f..d08bb6288 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
@@ -32,6 +32,7 @@ import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.time.LocalDate;
+import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -68,6 +69,7 @@ import 
org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsDataWrap
 import 
org.apache.fineract.portfolio.loanaccount.domain.ChangedTransactionDetail;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanChargePaidBy;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanPaymentAllocationRule;
@@ -1168,7 +1170,14 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
         }
     }
 
-    private void handleChargeOff(LoanTransaction loanTransaction, 
TransactionCtx transactionCtx) {
+    private void handleChargeOff(final LoanTransaction loanTransaction, final 
TransactionCtx transactionCtx) {
+        if (transactionCtx instanceof ProgressiveTransactionCtx 
progressiveTransactionCtx) {
+            if 
(LoanChargeOffBehaviour.ZERO_INTEREST.equals(loanTransaction.getLoan().getLoanProductRelatedDetail().getChargeOffBehaviour())
+                    && !loanTransaction.isReversed()) {
+                handleZeroInterestChargeOff(loanTransaction, 
progressiveTransactionCtx);
+            }
+        }
+
         loanTransaction.resetDerivedComponents();
         // determine how much is outstanding total and breakdown for 
principal, interest and charges
         Money principalPortion = Money.zero(transactionCtx.getCurrency());
@@ -1188,6 +1197,58 @@ public class AdvancedPaymentScheduleTransactionProcessor 
extends AbstractLoanRep
         loanTransaction.updateComponentsAndTotal(principalPortion, 
interestPortion, feeChargesPortion, penaltychargesPortion);
     }
 
+    private void handleZeroInterestChargeOff(final LoanTransaction 
loanTransaction,
+            final ProgressiveTransactionCtx progressiveTransactionCtx) {
+        final LocalDate transactionDate = loanTransaction.getTransactionDate();
+        final List<LoanRepaymentScheduleInstallment> installments = 
progressiveTransactionCtx.getInstallments();
+
+        if (!installments.isEmpty()) {
+            if (loanTransaction.getLoan().isInterestRecalculationEnabled()) {
+                installments.stream().filter(installment -> 
!installment.getFromDate().isAfter(transactionDate)
+                        && 
installment.getDueDate().isAfter(transactionDate)).forEach(installment -> {
+                            final BigDecimal newInterest = 
emiCalculator.getPeriodInterestTillDate(progressiveTransactionCtx.getModel(),
+                                    installment.getDueDate(), 
transactionDate).getAmount();
+                            final BigDecimal interestRemoved = 
installment.getInterestCharged().subtract(newInterest);
+                            
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
+                            installment.updateInterestCharged(newInterest);
+                        });
+            } else {
+                calculatePartialPeriodInterest(progressiveTransactionCtx, 
transactionDate);
+            }
+
+            installments.stream().filter(installment -> 
installment.getFromDate().isAfter(transactionDate)).forEach(installment -> {
+                
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(installment.getInterestCharged()));
+                installment.updateInterestCharged(BigDecimal.ZERO);
+            });
+
+            final BigDecimal totalInstallmentsPrincipal = 
installments.stream().map(LoanRepaymentScheduleInstallment::getPrincipal)
+                    .reduce(ZERO, BigDecimal::add);
+            final Money amountToEditLastInstallment = 
loanTransaction.getLoan().getPrincipal().minus(totalInstallmentsPrincipal);
+            final int lastInstallmentIndex = installments.size() - 1;
+            installments.get(lastInstallmentIndex)
+                    
.updatePrincipal(installments.get(lastInstallmentIndex).getPrincipal().add(amountToEditLastInstallment.getAmount()));
+        }
+    }
+
+    private void calculatePartialPeriodInterest(final 
ProgressiveTransactionCtx progressiveTransactionCtx, final LocalDate 
chargeOffDate) {
+        progressiveTransactionCtx.getInstallments().stream()
+                .filter(installment -> 
!installment.getFromDate().isAfter(chargeOffDate) && 
installment.getDueDate().isAfter(chargeOffDate))
+                .forEach(installment -> {
+                    final BigDecimal totalInterest = 
installment.getInterestOutstanding(progressiveTransactionCtx.getCurrency())
+                            .getAmount();
+                    final long totalDaysInPeriod = 
ChronoUnit.DAYS.between(installment.getFromDate(), installment.getDueDate());
+                    final long daysTillChargeOff = 
ChronoUnit.DAYS.between(installment.getFromDate(), chargeOffDate);
+
+                    final BigDecimal interestTillChargeOff = totalInterest
+                            .divide(BigDecimal.valueOf(totalDaysInPeriod), 
MoneyHelper.getMathContext())
+                            .multiply(BigDecimal.valueOf(daysTillChargeOff));
+
+                    final BigDecimal interestRemoved = 
totalInterest.subtract(interestTillChargeOff);
+                    
installment.updatePrincipal(MathUtil.nullToZero(installment.getPrincipal()).add(interestRemoved));
+                    installment.updateInterestCharged(interestTillChargeOff);
+                });
+    }
+
     private void handleChargePayment(LoanTransaction loanTransaction, 
TransactionCtx transactionCtx) {
         Money zero = Money.zero(transactionCtx.getCurrency());
         Money feeChargesPortion = zero;
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index 08040cb1e..b6ed00e67 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -3207,10 +3207,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final List<Long> existingTransactionIds = 
loan.findExistingTransactionIds();
         final List<Long> existingReversedTransactionIds = 
loan.findExistingReversedTransactionIds();
 
-        LoanTransaction chargeOffTransaction = LoanTransaction.chargeOff(loan, 
transactionDate, txnExternalId);
+        final LoanTransaction chargeOffTransaction = 
LoanTransaction.chargeOff(loan, transactionDate, txnExternalId);
 
-        if (loan.isInterestBearing() && loan.isInterestRecalculationEnabled()
-                && DateUtils.isBefore(loan.getInterestRecalculatedOn(), 
DateUtils.getBusinessLocalDate())) {
+        if (loan.isInterestBearing() && loan.isInterestRecalculationEnabled()) 
{
             final ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
             
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, 
scheduleGeneratorDTO);
             loan.addLoanTransaction(chargeOffTransaction);
@@ -3225,6 +3224,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
             }
         } else {
             loan.addLoanTransaction(chargeOffTransaction);
+            
loan.getTransactionProcessor().processLatestTransaction(chargeOffTransaction,
+                    new TransactionCtx(loan.getCurrency(), 
loan.getRepaymentScheduleInstallments(), loan.getActiveCharges(),
+                            new MoneyHolder(loan.getTotalOverpaidAsMoney()), 
null));
+            loan.updateLoanSummaryDerivedFields();
         }
         loanTransactionRepository.saveAndFlush(chargeOffTransaction);
 
@@ -3292,6 +3295,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         saveLoanWithDataIntegrityViolationChecks(loan);
         postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds);
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanUndoChargeOffBusinessEvent(chargedOffTransaction));
+
+        loan.reprocessTransactions();
+
         return new CommandProcessingResultBuilder() //
                 .withOfficeId(loan.getOfficeId()) //
                 .withClientId(loan.getClientId()) //

Reply via email to