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()) //