Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kjozsa committed Sep 25, 2024
1 parent 7ed0a82 commit bffb225
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.apache.fineract.test.data;

public enum CobBusinessStep {

APPLY_CHARGE_TO_OVERDUE_LOANS("APPLY_CHARGE_TO_OVERDUE_LOANS"),
LOAN_DELINQUENCY_CLASSIFICATION("LOAN_DELINQUENCY_CLASSIFICATION"),
CHECK_LOAN_REPAYMENT_DUE("CHECK_LOAN_REPAYMENT_DUE"),
CHECK_LOAN_REPAYMENT_OVERDUE("CHECK_LOAN_REPAYMENT_OVERDUE"),
UPDATE_LOAN_ARREARS_AGING("UPDATE_LOAN_ARREARS_AGING"),
ADD_PERIODIC_ACCRUAL_ENTRIES("ADD_PERIODIC_ACCRUAL_ENTRIES"),
EXTERNAL_ASSET_OWNER_TRANSFER("EXTERNAL_ASSET_OWNER_TRANSFER"),
CHECK_DUE_INSTALLMENTS("CHECK_DUE_INSTALLMENTS"),
ACCRUAL_ACTIVITY_POSTING("ACCRUAL_ACTIVITY_POSTING"),
LOAN_INTEREST_RECALCULATION("LOAN_INTEREST_RECALCULATION");

public final String value;

CobBusinessStep(String value) {
this.value = value;
}

public String getValue() {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,23 @@
import io.cucumber.java.en.Then;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.BusinessStep;
import org.apache.fineract.client.models.GetBusinessStepConfigResponse;
import org.apache.fineract.client.models.UpdateBusinessStepConfigRequest;
import org.apache.fineract.client.services.BusinessStepConfigurationApi;
import org.apache.fineract.test.data.CobBusinessStep;
import org.apache.fineract.test.helper.ErrorHelper;
import org.apache.fineract.test.stepdef.AbstractStepDef;
import org.springframework.beans.factory.annotation.Autowired;
import retrofit2.Response;

@Slf4j
public class BusinessStepStepDef extends AbstractStepDef {

private static final String WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS = "LOAN_CLOSE_OF_BUSINESS";
Expand Down Expand Up @@ -149,4 +157,54 @@ public void removeCheckDueInstallmentsJobInCOB() throws IOException {
.execute();
ErrorHelper.checkSuccessfulApiCall(response);
}

@Given("Admin puts {string} business step into LOAN_CLOSE_OF_BUSINESS workflow")
public void putGivenJobInCOB(String businessStepName) throws IOException {
List<BusinessStep> businessSteps = retrieveLoanCOBJobSteps();
if (businessSteps.stream().anyMatch(businessStep -> businessStep.getStepName().equals(businessStepName))) {
return;
}

businessSteps.add(new BusinessStep().stepName(businessStepName).order((long) (1 + businessSteps.size())));

UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request).execute();
ErrorHelper.checkSuccessfulApiCall(response);

logChanges();
}

@Then("Admin removes {string} business step into LOAN_CLOSE_OF_BUSINESS workflow")
public void removeGivenJobInCOB(String businessStepName) throws IOException {
List<BusinessStep> businessSteps = retrieveLoanCOBJobSteps();
businessSteps.removeIf(businessStep -> businessStep.getStepName().equals(businessStepName));

UpdateBusinessStepConfigRequest request = new UpdateBusinessStepConfigRequest().businessSteps(businessSteps);
Response<Void> response = businessStepConfigurationApi.updateJobBusinessStepConfig(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS, request).execute();
ErrorHelper.checkSuccessfulApiCall(response);

logChanges();
}

private List<BusinessStep> retrieveLoanCOBJobSteps() throws IOException {
Response<GetBusinessStepConfigResponse> businessStepConfigResponse = businessStepConfigurationApi
.retrieveAllConfiguredBusinessStep(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS).execute();
ErrorHelper.checkSuccessfulApiCall(businessStepConfigResponse);
return businessStepConfigResponse.body().getBusinessSteps();
}

private void logChanges() throws IOException {
// --- log changes ---
Response<GetBusinessStepConfigResponse> changesResponse = businessStepConfigurationApi
.retrieveAllConfiguredBusinessStep(WORKFLOW_NAME_LOAN_CLOSE_OF_BUSINESS).execute();
List<BusinessStep> businessStepsChanged = changesResponse.body().getBusinessSteps();
List<String> changes = businessStepsChanged//
.stream()//
.sorted(Comparator.comparingLong(BusinessStep::getOrder))//
.map(BusinessStep::getStepName)//
.collect(Collectors.toList());//

log.info("Business steps has been CHANGED to the following:");
changes.forEach(e -> log.info(e));
}
}
19 changes: 19 additions & 0 deletions fineract-e2e-tests-runner/src/test/resources/features/Loan.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5657,3 +5657,22 @@ Feature: Loan
| 15 February 2024 | Repayment | 84.06 | 83.57 | 0.49 | 0.0 | 0.0 | 0.0 | false |
Then Loan's all installments have obligations met
When Admin set "LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_REST_FREQUENCY" loan product "DEFAULT" transaction type to "LAST_INSTALLMENT" future installment allocation rule

Scenario: Interest recalculation - daily for overdue loan
When Admin sets the business date to "1 January 2024"
When Admin creates a client with random data
When Admin creates a fully customized loan with the following data:
| LoanProduct | submitted on date | with Principal | ANNUAL interest rate % | interest type | interest calculation period | amortization type | loanTermFrequency | loanTermFrequencyType | repaymentEvery | repaymentFrequencyType | numberOfRepayments | graceOnPrincipalPayment | graceOnInterestPayment | interest free period | Payment strategy |
| LP2_ADV_PYMNT_INTEREST_DAILY_EMI_360_30_INTEREST_RECALCULATION_TILL_PRECLOSE | 01 January 2024 | 100 | 9.9 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "1 January 2024" with "100" amount and expected disbursement date on "1 January 2024"
When Admin successfully disburse the loan on "1 January 2024" with "100" EUR transaction amount
When Admin sets the business date to "1 April 2025"
When Admin puts "LOAN_INTEREST_RECALCULATION" business step into LOAN_CLOSE_OF_BUSINESS workflow
When Admin runs inline COB job for Loan
Then Loan Repayment schedule has 3 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
| 1 | 31 | 01 February 2024 | | 66.94 | 33.06 | 0.82 | 0.0 | 0.0 | 33.88 | 0.0 | 0.0 | 0.0 | 33.88 |
| 2 | 29 | 01 March 2024 | | 33.61 | 33.33 | 0.55 | 0.0 | 0.0 | 33.88 | 0.0 | 0.0 | 0.0 | 33.88 |
| 3 | 31 | 01 April 2024 | | 0.0 | 33.61 | 0.28 | 0.0 | 0.0 | 33.89 | 0.0 | 0.0 | 0.0 | 33.89 |
When Admin removes "LOAN_INTEREST_RECALCULATION" business step into LOAN_CLOSE_OF_BUSINESS workflow
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,8 @@ private void allocateOverpayment(LoanTransaction loanTransaction, TransactionCtx
private List<LoanRepaymentScheduleInstallment> findOverdueInstallmentsBeforeDateSortedByInstallmentNumber(LocalDate currentDate,
ProgressiveTransactionCtx transactionCtx) {
final LocalDate fromDate = transactionCtx.getInstallments().get(0).getLoan().getApprovedOnDate();
return transactionCtx.getInstallments().stream().filter(installment -> !installment.getFromDate().isBefore(fromDate))
return transactionCtx.getInstallments().stream() //
.filter(installment -> !installment.getFromDate().isBefore(fromDate))
.filter(installment -> installment.getDueDate().isBefore(currentDate))
.filter(installment -> installment.isOverdueOn(currentDate))
.sorted(Comparator.comparing(LoanRepaymentScheduleInstallment::getInstallmentNumber)).toList();
Expand Down

0 comments on commit bffb225

Please sign in to comment.