FINERACT-2148: Update instalments interest with zero after charge off with interest recalculation enabled
This commit is contained in:
committed by
Adam Saghy
parent
136bb0009a
commit
51433ffb66
+1
@@ -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_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_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_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION, //
|
||||||
|
LP2_ADV_PYMNT_INTEREST_DAILY_INTEREST_RECALCULATION_ZERO_INTEREST_CHARGE_OFF_BEHAVIOUR, //
|
||||||
;
|
;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+17
@@ -1088,6 +1088,23 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
|||||||
TestContext.INSTANCE.set(
|
TestContext.INSTANCE.set(
|
||||||
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_CUSTOM_PAYMENT_ALLOCATION_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE,
|
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADVANCED_CUSTOM_PAYMENT_ALLOCATION_INTEREST_RECALCULATION_DAILY_EMI_360_30_MULTIDISBURSE,
|
||||||
responseLoanProductsRequestLP2AdvCustomPaymentAllocationInterestRecalculationDaily36030MultiDisburse);
|
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,
|
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,
|
||||||
|
|||||||
+29
@@ -19,6 +19,7 @@
|
|||||||
package org.apache.fineract.test.stepdef.loan;
|
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.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.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.awaitility.Awaitility.await;
|
import static org.awaitility.Awaitility.await;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
@@ -2766,6 +2767,34 @@ public class LoanStepDef extends AbstractStepDef {
|
|||||||
eventCheckHelper.createLoanEventCheck(response);
|
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)
|
private void performLoanDisbursementAndVerifyStatus(final long loanId, final PostLoansLoanIdRequest disburseRequest)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse")
|
final Response<PostLoansLoanIdResponse> loanDisburseResponse = loansApi.stateTransitions(loanId, disburseRequest, "disburse")
|
||||||
|
|||||||
+1
@@ -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_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_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_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_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_LATE_AMOUNT_PLUS_INTEREST_CREATE_RESPONSE = "ChargeForLoanPercentLateAmountPlusInterestCreateResponse";
|
||||||
public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse";
|
public static final String CHARGE_FOR_LOAN_PERCENT_PROCESSING_CREATE_RESPONSE = "ChargeForLoanPercentProcessingCreateResponse";
|
||||||
|
|||||||
@@ -1611,3 +1611,313 @@ Feature: Charge-off
|
|||||||
Then Loan Repayment schedule has the following data in Total row:
|
Then Loan Repayment schedule has the following data in Total row:
|
||||||
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
|
||||||
| 1000 | 12.22 | 0 | 0 | 1012.22 | 0 | 0 | 0 | 1012.22 |
|
| 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 |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -255,6 +255,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
case WRITEOFF -> handleWriteOff(loanTransaction, ctx.getCurrency(), ctx.getInstallments());
|
case WRITEOFF -> handleWriteOff(loanTransaction, ctx.getCurrency(), ctx.getInstallments());
|
||||||
case REFUND_FOR_ACTIVE_LOAN -> handleRefund(loanTransaction, ctx.getCurrency(), ctx.getInstallments(), ctx.getCharges());
|
case REFUND_FOR_ACTIVE_LOAN -> handleRefund(loanTransaction, ctx.getCurrency(), ctx.getInstallments(), ctx.getCharges());
|
||||||
case CHARGEBACK -> handleChargeback(loanTransaction, ctx);
|
case CHARGEBACK -> handleChargeback(loanTransaction, ctx);
|
||||||
|
case CHARGE_OFF -> handleChargeOff(loanTransaction, ctx);
|
||||||
default -> {
|
default -> {
|
||||||
Money transactionAmountUnprocessed = handleTransactionAndCharges(loanTransaction, ctx.getCurrency(), ctx.getInstallments(),
|
Money transactionAmountUnprocessed = handleTransactionAndCharges(loanTransaction, ctx.getCurrency(), ctx.getInstallments(),
|
||||||
ctx.getCharges(), null, false);
|
ctx.getCharges(), null, false);
|
||||||
@@ -394,7 +395,7 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
|
|||||||
principalPortion = principalPortion.plus(currentInstallment.getPrincipalOutstanding(currency));
|
principalPortion = principalPortion.plus(currentInstallment.getPrincipalOutstanding(currency));
|
||||||
interestPortion = interestPortion.plus(currentInstallment.getInterestOutstanding(currency));
|
interestPortion = interestPortion.plus(currentInstallment.getInterestOutstanding(currency));
|
||||||
feeChargesPortion = feeChargesPortion.plus(currentInstallment.getFeeChargesOutstanding(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());
|
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,
|
protected void handleCreditBalanceRefund(LoanTransaction loanTransaction, MonetaryCurrency currency,
|
||||||
List<LoanRepaymentScheduleInstallment> installments, MoneyHolder overpaidAmountHolder) {
|
List<LoanRepaymentScheduleInstallment> installments, MoneyHolder overpaidAmountHolder) {
|
||||||
processCreditTransaction(loanTransaction, overpaidAmountHolder, currency, installments);
|
processCreditTransaction(loanTransaction, overpaidAmountHolder, currency, installments);
|
||||||
|
|||||||
+62
-1
@@ -32,6 +32,7 @@ import jakarta.validation.constraints.NotNull;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
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.ChangedTransactionDetail;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
|
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.LoanChargePaidBy;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule;
|
import org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule;
|
||||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanPaymentAllocationRule;
|
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();
|
loanTransaction.resetDerivedComponents();
|
||||||
// determine how much is outstanding total and breakdown for principal, interest and charges
|
// determine how much is outstanding total and breakdown for principal, interest and charges
|
||||||
Money principalPortion = Money.zero(transactionCtx.getCurrency());
|
Money principalPortion = Money.zero(transactionCtx.getCurrency());
|
||||||
@@ -1188,6 +1197,58 @@ public class AdvancedPaymentScheduleTransactionProcessor extends AbstractLoanRep
|
|||||||
loanTransaction.updateComponentsAndTotal(principalPortion, interestPortion, feeChargesPortion, penaltychargesPortion);
|
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) {
|
private void handleChargePayment(LoanTransaction loanTransaction, TransactionCtx transactionCtx) {
|
||||||
Money zero = Money.zero(transactionCtx.getCurrency());
|
Money zero = Money.zero(transactionCtx.getCurrency());
|
||||||
Money feeChargesPortion = zero;
|
Money feeChargesPortion = zero;
|
||||||
|
|||||||
+9
-3
@@ -3207,10 +3207,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
|
final List<Long> existingTransactionIds = loan.findExistingTransactionIds();
|
||||||
final List<Long> existingReversedTransactionIds = loan.findExistingReversedTransactionIds();
|
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()
|
if (loan.isInterestBearing() && loan.isInterestRecalculationEnabled()) {
|
||||||
&& DateUtils.isBefore(loan.getInterestRecalculatedOn(), DateUtils.getBusinessLocalDate())) {
|
|
||||||
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan, null, null);
|
||||||
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
loanScheduleService.regenerateRepaymentScheduleWithInterestRecalculation(loan, scheduleGeneratorDTO);
|
||||||
loan.addLoanTransaction(chargeOffTransaction);
|
loan.addLoanTransaction(chargeOffTransaction);
|
||||||
@@ -3225,6 +3224,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loan.addLoanTransaction(chargeOffTransaction);
|
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);
|
loanTransactionRepository.saveAndFlush(chargeOffTransaction);
|
||||||
|
|
||||||
@@ -3292,6 +3295,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
|
|||||||
saveLoanWithDataIntegrityViolationChecks(loan);
|
saveLoanWithDataIntegrityViolationChecks(loan);
|
||||||
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
|
||||||
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoChargeOffBusinessEvent(chargedOffTransaction));
|
businessEventNotifierService.notifyPostBusinessEvent(new LoanUndoChargeOffBusinessEvent(chargedOffTransaction));
|
||||||
|
|
||||||
|
loan.reprocessTransactions();
|
||||||
|
|
||||||
return new CommandProcessingResultBuilder() //
|
return new CommandProcessingResultBuilder() //
|
||||||
.withOfficeId(loan.getOfficeId()) //
|
.withOfficeId(loan.getOfficeId()) //
|
||||||
.withClientId(loan.getClientId()) //
|
.withClientId(loan.getClientId()) //
|
||||||
|
|||||||
Reference in New Issue
Block a user