Skip to content

Commit 539fc7b

Browse files
ruzeynalovAvtansh88
authored andcommitted
FINERACT-2455: Added e2e tests for Working Capital loan delinquency grace days
1 parent c054651 commit 539fc7b

File tree

10 files changed

+426
-13
lines changed

10 files changed

+426
-13
lines changed

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalProductLoanAccountStepDef.java

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.ArrayList;
3737
import java.util.List;
3838
import java.util.Map;
39+
import java.util.Optional;
3940
import lombok.RequiredArgsConstructor;
4041
import lombok.extern.slf4j.Slf4j;
4142
import org.apache.fineract.client.feign.FineractFeignClient;
@@ -44,6 +45,8 @@
4445
import org.apache.fineract.client.models.GetDisbursementDetail;
4546
import org.apache.fineract.client.models.GetWorkingCapitalLoansLoanIdResponse;
4647
import org.apache.fineract.client.models.PostClientsResponse;
48+
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsRequest;
49+
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsResponse;
4750
import org.apache.fineract.client.models.PostWorkingCapitalLoansLoanIdRequest;
4851
import org.apache.fineract.client.models.PostWorkingCapitalLoansLoanIdResponse;
4952
import org.apache.fineract.client.models.PostWorkingCapitalLoansRequest;
@@ -54,6 +57,7 @@
5457
import org.apache.fineract.test.data.workingcapitalproduct.DefaultWorkingCapitalLoanProduct;
5558
import org.apache.fineract.test.data.workingcapitalproduct.WorkingCapitalLoanProductResolver;
5659
import org.apache.fineract.test.factory.WorkingCapitalLoanRequestFactory;
60+
import org.apache.fineract.test.factory.WorkingCapitalRequestFactory;
5761
import org.apache.fineract.test.helper.ErrorMessageHelper;
5862
import org.apache.fineract.test.helper.Utils;
5963
import org.apache.fineract.test.messaging.event.EventCheckHelper;
@@ -71,6 +75,7 @@ public class WorkingCapitalProductLoanAccountStepDef extends AbstractStepDef {
7175
private final FineractFeignClient fineractClient;
7276
private final WorkingCapitalLoanProductResolver workingCapitalLoanProductResolver;
7377
private final WorkingCapitalLoanRequestFactory workingCapitalLoanRequestFactory;
78+
private final WorkingCapitalRequestFactory workingCapitalProductRequestFactory;
7479
private final EventCheckHelper eventCheckHelper;
7580

7681
@When("Admin creates a working capital loan with the following data:")
@@ -846,4 +851,125 @@ public void disburseWCLoanFailure(String actualDisbursementDate, String transact
846851
assertThat(exception.getDeveloperMessage()).contains(errorMessage);
847852
}
848853

854+
@When("Admin creates a Working Capital Loan Product with delinquencyGraceDays {int} and delinquencyStartType {string} for loan test")
855+
public void createProductWithGraceDaysForLoanTest(int graceDays, String startType) {
856+
final String name = "WCLP-GD-" + Utils.randomStringGenerator("", 8);
857+
final PostWorkingCapitalLoanProductsRequest request = workingCapitalProductRequestFactory.defaultWorkingCapitalLoanProductRequest() //
858+
.name(name) //
859+
.delinquencyGraceDays(graceDays) //
860+
.delinquencyStartType(startType);
861+
final PostWorkingCapitalLoanProductsResponse response = ok(
862+
() -> fineractClient.workingCapitalLoanProducts().createWorkingCapitalLoanProduct(request, Map.of()));
863+
testContext().set(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_CREATE_RESPONSE, response);
864+
testContext().set(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_FOR_LOAN_TEST, response.getResourceId());
865+
log.info("Created WC Loan Product with grace days for loan test, ID: {}", response.getResourceId());
866+
}
867+
868+
@When("Admin creates a working capital loan with the grace days product and the following data:")
869+
public void createLoanWithGraceDaysProduct(final DataTable table) {
870+
final Map<String, String> row = table.asMaps().get(0);
871+
submitLoanAndStore(buildGraceDaysLoanRequest(row));
872+
}
873+
874+
@When("Admin creates a working capital loan with grace days override and the following data:")
875+
public void createLoanWithGraceDaysOverride(final DataTable table) {
876+
final Map<String, String> row = table.asMaps().get(0);
877+
final PostWorkingCapitalLoansRequest request = buildGraceDaysLoanRequest(row) //
878+
.delinquencyGraceDays(
879+
Optional.ofNullable(row.get("delinquencyGraceDays")).filter(s -> !s.isEmpty()).map(Integer::valueOf).orElse(null)) //
880+
.delinquencyStartType(row.get("delinquencyStartType"));
881+
submitLoanAndStore(request);
882+
}
883+
884+
private PostWorkingCapitalLoansRequest buildGraceDaysLoanRequest(final Map<String, String> row) {
885+
final Long clientId = extractClientId();
886+
final Long productId = testContext().get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_FOR_LOAN_TEST);
887+
return workingCapitalLoanRequestFactory.defaultWorkingCapitalLoansRequest(clientId) //
888+
.productId(productId) //
889+
.submittedOnDate(row.get("submittedOnDate")) //
890+
.expectedDisbursementDate(row.get("expectedDisbursementDate")) //
891+
.principalAmount(new BigDecimal(row.get("principalAmount"))) //
892+
.totalPayment(new BigDecimal(row.get("totalPayment"))) //
893+
.periodPaymentRate(new BigDecimal(row.get("periodPaymentRate"))) //
894+
.discount(Optional.ofNullable(row.get("discount")).filter(s -> !s.isEmpty()).map(BigDecimal::new).orElse(null));
895+
}
896+
897+
private void submitLoanAndStore(final PostWorkingCapitalLoansRequest request) {
898+
final PostWorkingCapitalLoansResponse response = ok(
899+
() -> fineractClient.workingCapitalLoans().submitWorkingCapitalLoanApplication(request));
900+
testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
901+
log.info("Working Capital Loan created, loan ID: {}", response.getLoanId());
902+
}
903+
904+
@Then("Working capital loan account has delinquencyGraceDays {int} and delinquencyStartType {string}")
905+
public void verifyLoanGraceDays(int expectedGraceDays, String expectedStartType) {
906+
final PostWorkingCapitalLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
907+
final Long loanId = loanResponse.getLoanId();
908+
909+
final GetWorkingCapitalLoansLoanIdResponse response = ok(
910+
() -> fineractClient.workingCapitalLoans().retrieveWorkingCapitalLoanById(loanId));
911+
912+
assertThat(response.getDelinquencyGraceDays()).as("delinquencyGraceDays").isEqualTo(expectedGraceDays);
913+
assertThat(response.getDelinquencyStartType()).as("delinquencyStartType").isNotNull();
914+
assertThat(response.getDelinquencyStartType().getCode()).as("delinquencyStartType code").isEqualTo(expectedStartType);
915+
}
916+
917+
@When("Admin modifies the working capital loan with grace days:")
918+
public void modifyLoanWithGraceDays(final DataTable table) {
919+
final Map<String, String> row = table.asMaps().get(0);
920+
final PostWorkingCapitalLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
921+
final Long loanId = loanResponse.getLoanId();
922+
923+
final PutWorkingCapitalLoansLoanIdRequest modifyRequest = workingCapitalLoanRequestFactory.defaultModifyWorkingCapitalLoansRequest() //
924+
.delinquencyGraceDays(
925+
Optional.ofNullable(row.get("delinquencyGraceDays")).filter(s -> !s.isEmpty()).map(Integer::valueOf).orElse(null)) //
926+
.delinquencyStartType(row.get("delinquencyStartType"));
927+
928+
final PutWorkingCapitalLoansLoanIdResponse response = ok(
929+
() -> fineractClient.workingCapitalLoans().modifyWorkingCapitalLoanApplicationById(loanId, modifyRequest, ""));
930+
testContext().set(TestContextKey.LOAN_MODIFY_RESPONSE, response);
931+
}
932+
933+
@When("Admin approves the working capital loan on {string}")
934+
public void approveWorkingCapitalLoan(final String approvedOnDate) {
935+
final PostWorkingCapitalLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
936+
final Long loanId = loanResponse.getLoanId();
937+
938+
final PostWorkingCapitalLoansLoanIdRequest approveRequest = new PostWorkingCapitalLoansLoanIdRequest() //
939+
.approvedOnDate(approvedOnDate) //
940+
.expectedDisbursementDate(approvedOnDate) //
941+
.dateFormat(DATE_FORMAT) //
942+
.locale(WorkingCapitalLoanRequestFactory.DEFAULT_LOCALE);
943+
944+
ok(() -> fineractClient.workingCapitalLoans().stateTransitionWorkingCapitalLoanById(loanId, "approve", approveRequest));
945+
log.info("Approved working capital loan {}", loanId);
946+
}
947+
948+
@Then("Creating a working capital loan with invalid delinquencyGraceDays {int} will result with status code {int}")
949+
public void createLoanWithInvalidGraceDays(int graceDays, int expectedStatus) {
950+
final Long clientId = extractClientId();
951+
final Long productId = testContext().get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_FOR_LOAN_TEST);
952+
953+
final PostWorkingCapitalLoansRequest request = workingCapitalLoanRequestFactory.defaultWorkingCapitalLoansRequest(clientId)
954+
.productId(productId) //
955+
.delinquencyGraceDays(graceDays);
956+
957+
final CallFailedRuntimeException exception = fail(
958+
() -> fineractClient.workingCapitalLoans().submitWorkingCapitalLoanApplication(request));
959+
assertThat(exception.getStatus()).as("HTTP status").isEqualTo(expectedStatus);
960+
}
961+
962+
@Then("Creating a working capital loan with invalid delinquencyStartType {string} will result with status code {int}")
963+
public void createLoanWithInvalidStartType(String startType, int expectedStatus) {
964+
final Long clientId = extractClientId();
965+
final Long productId = testContext().get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_FOR_LOAN_TEST);
966+
967+
final PostWorkingCapitalLoansRequest request = workingCapitalLoanRequestFactory.defaultWorkingCapitalLoansRequest(clientId)
968+
.productId(productId) //
969+
.delinquencyStartType(startType);
970+
971+
final CallFailedRuntimeException exception = fail(
972+
() -> fineractClient.workingCapitalLoans().submitWorkingCapitalLoanApplication(request));
973+
assertThat(exception.getStatus()).as("HTTP status").isEqualTo(expectedStatus);
974+
}
849975
}

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/WorkingCapitalStepDef.java

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@
2222
import static org.apache.fineract.client.feign.util.FeignCalls.ok;
2323
import static org.assertj.core.api.Assertions.assertThat;
2424

25+
import io.cucumber.datatable.DataTable;
2526
import io.cucumber.java.en.Then;
2627
import io.cucumber.java.en.When;
2728
import java.math.BigDecimal;
29+
import java.util.List;
2830
import java.util.Map;
2931
import java.util.UUID;
3032
import lombok.RequiredArgsConstructor;
@@ -36,12 +38,15 @@
3638
import org.apache.fineract.client.models.GetConfigurableAttributes;
3739
import org.apache.fineract.client.models.GetPaymentAllocation;
3840
import org.apache.fineract.client.models.GetWorkingCapitalLoanProductsProductIdResponse;
41+
import org.apache.fineract.client.models.GetWorkingCapitalLoanProductsTemplateResponse;
3942
import org.apache.fineract.client.models.PostAllowAttributeOverrides;
4043
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsRequest;
4144
import org.apache.fineract.client.models.PostWorkingCapitalLoanProductsResponse;
4245
import org.apache.fineract.client.models.PutWorkingCapitalLoanProductsProductIdRequest;
4346
import org.apache.fineract.client.models.PutWorkingCapitalLoanProductsProductIdResponse;
47+
import org.apache.fineract.client.models.StringEnumOptionData;
4448
import org.apache.fineract.test.data.workingcapitalproduct.DefaultWorkingCapitalLoanProduct;
49+
import org.apache.fineract.test.factory.LoanProductsRequestFactory;
4550
import org.apache.fineract.test.factory.WorkingCapitalRequestFactory;
4651
import org.apache.fineract.test.helper.ErrorMessageHelper;
4752
import org.apache.fineract.test.helper.Utils;
@@ -77,6 +82,8 @@ public class WorkingCapitalStepDef extends AbstractStepDef {
7782
public static final String REPAYMENT_EVERY_FIELD_NAME = "repaymentEvery";
7883
public static final String EXTERNAL_ID_FIELD_NAME = "externalId";
7984
public static final String DELINQUENCY_BUCKET_ID_FIELD_NAME = "delinquencyBucketId";
85+
public static final String DELINQUENCY_GRACE_DAYS_FIELD_NAME = "delinquencyGraceDays";
86+
public static final String DELINQUENCY_START_TYPE_FIELD_NAME = "delinquencyStartType";
8087
public static final String LOCALE_FIELD_NAME = "locale";
8188

8289
private WorkingCapitalLoanProductsApi workingCapitalApi() {
@@ -607,7 +614,8 @@ public PostWorkingCapitalLoanProductsRequest setWorkingCapitalLoanProductsCreate
607614
Integer valueInteger = null;
608615
BigDecimal valueBigDecimal = null;
609616
if (fieldName.equalsIgnoreCase(DIGITS_AFTER_DECIMAL_FIELD_NAME) || fieldName.equalsIgnoreCase(IN_MULTIPLES_OF_FIELD_NAME)
610-
|| fieldName.equalsIgnoreCase(NPV_DAY_COUNT_FIELD_NAME) || fieldName.equalsIgnoreCase(REPAYMENT_EVERY_FIELD_NAME)) {
617+
|| fieldName.equalsIgnoreCase(NPV_DAY_COUNT_FIELD_NAME) || fieldName.equalsIgnoreCase(REPAYMENT_EVERY_FIELD_NAME)
618+
|| fieldName.equalsIgnoreCase(DELINQUENCY_GRACE_DAYS_FIELD_NAME)) {
611619
valueInteger = fieldValue != null ? Integer.valueOf(fieldValue) : null;
612620
}
613621
if (fieldName.equalsIgnoreCase(PRINCIPAL_FIELD_NAME) || fieldName.equalsIgnoreCase(MIN_PRINCIPAL_FIELD_NAME)
@@ -675,6 +683,12 @@ public PostWorkingCapitalLoanProductsRequest setWorkingCapitalLoanProductsCreate
675683
defaultWorkingCapitalLoanProductCreateRequest
676684
.setDelinquencyBucketId(fieldValue != null ? Long.parseLong(fieldValue) : null);
677685
break;
686+
case DELINQUENCY_GRACE_DAYS_FIELD_NAME:
687+
defaultWorkingCapitalLoanProductCreateRequest.setDelinquencyGraceDays(valueInteger);
688+
break;
689+
case DELINQUENCY_START_TYPE_FIELD_NAME:
690+
defaultWorkingCapitalLoanProductCreateRequest.setDelinquencyStartType(fieldValue);
691+
break;
678692
case LOCALE_FIELD_NAME:
679693
defaultWorkingCapitalLoanProductCreateRequest.setLocale(fieldValue);
680694
break;
@@ -716,7 +730,8 @@ public PutWorkingCapitalLoanProductsProductIdRequest setWorkingCapitalLoanProduc
716730
Integer valueInteger = null;
717731
BigDecimal valueBigDecimal = null;
718732
if (fieldName.equalsIgnoreCase(DIGITS_AFTER_DECIMAL_FIELD_NAME) || fieldName.equalsIgnoreCase(IN_MULTIPLES_OF_FIELD_NAME)
719-
|| fieldName.equalsIgnoreCase(NPV_DAY_COUNT_FIELD_NAME) || fieldName.equalsIgnoreCase(REPAYMENT_EVERY_FIELD_NAME)) {
733+
|| fieldName.equalsIgnoreCase(NPV_DAY_COUNT_FIELD_NAME) || fieldName.equalsIgnoreCase(REPAYMENT_EVERY_FIELD_NAME)
734+
|| fieldName.equalsIgnoreCase(DELINQUENCY_GRACE_DAYS_FIELD_NAME)) {
720735
valueInteger = fieldValue != null ? Integer.valueOf(fieldValue) : null;
721736
}
722737
if (fieldName.equalsIgnoreCase(PRINCIPAL_FIELD_NAME) || fieldName.equalsIgnoreCase(MIN_PRINCIPAL_FIELD_NAME)
@@ -784,6 +799,12 @@ public PutWorkingCapitalLoanProductsProductIdRequest setWorkingCapitalLoanProduc
784799
defaultWorkingCapitalLoanProductUpdateRequest
785800
.setDelinquencyBucketId(fieldValue != null ? Long.parseLong(fieldValue) : null);
786801
break;
802+
case DELINQUENCY_GRACE_DAYS_FIELD_NAME:
803+
defaultWorkingCapitalLoanProductUpdateRequest.setDelinquencyGraceDays(valueInteger);
804+
break;
805+
case DELINQUENCY_START_TYPE_FIELD_NAME:
806+
defaultWorkingCapitalLoanProductUpdateRequest.setDelinquencyStartType(fieldValue);
807+
break;
787808
case LOCALE_FIELD_NAME:
788809
defaultWorkingCapitalLoanProductUpdateRequest.setLocale(fieldValue);
789810
break;
@@ -800,4 +821,70 @@ public void checkWorkingCapitalLoanProductDeleteFailure(Long productId) {
800821
.contains(ErrorMessageHelper.workingCapitalLoanProductIdentifiedDoesNotExistFailure(String.valueOf(productId)));
801822
}
802823

824+
@When("Admin creates a new Working Capital Loan Product with delinquencyGraceDays {int} and delinquencyStartType {string}")
825+
public void createWorkingCapitalLoanProductWithGraceDays(int graceDays, String startType) {
826+
final String name = DefaultWorkingCapitalLoanProduct.WCLP.getName() + Utils.randomStringGenerator("_", 10);
827+
final PostWorkingCapitalLoanProductsRequest request = workingCapitalRequestFactory.defaultWorkingCapitalLoanProductRequest() //
828+
.name(name) //
829+
.delinquencyGraceDays(graceDays) //
830+
.delinquencyStartType(startType);
831+
final PostWorkingCapitalLoanProductsResponse response = createWorkingCapitalLoanProduct(request);
832+
testContext().set(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_CREATE_RESPONSE, response);
833+
testContext().set(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_CREATE_REQUEST, request);
834+
}
835+
836+
@Then("Working Capital Loan Product has delinquencyGraceDays {int} and delinquencyStartType {string}")
837+
public void verifyProductGraceDays(int expectedGraceDays, String expectedStartType) {
838+
final GetWorkingCapitalLoanProductsProductIdResponse product = retrieveCreatedProduct();
839+
assertThat(product.getDelinquencyGraceDays()).isEqualTo(expectedGraceDays);
840+
assertThat(product.getDelinquencyStartType()).isNotNull();
841+
assertThat(product.getDelinquencyStartType().getCode()).isEqualTo(expectedStartType);
842+
}
843+
844+
@Then("Working Capital Loan Product has null delinquencyGraceDays and null delinquencyStartType")
845+
public void verifyProductNullGraceDays() {
846+
final GetWorkingCapitalLoanProductsProductIdResponse product = retrieveCreatedProduct();
847+
assertThat(product.getDelinquencyGraceDays()).isNull();
848+
assertThat(product.getDelinquencyStartType()).isNull();
849+
}
850+
851+
private GetWorkingCapitalLoanProductsProductIdResponse retrieveCreatedProduct() {
852+
final PostWorkingCapitalLoanProductsResponse productResponse = testContext()
853+
.get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_CREATE_RESPONSE);
854+
return workingCapitalApi().retrieveOneWorkingCapitalLoanProduct(productResponse.getResourceId(), Map.of());
855+
}
856+
857+
@When("Admin updates Working Capital Loan Product with delinquencyGraceDays {int} and delinquencyStartType {string}")
858+
public void updateProductGraceDays(int graceDays, String startType) {
859+
final Long resourceId = retrieveCreatedProductId();
860+
final PutWorkingCapitalLoanProductsProductIdRequest updateRequest = new PutWorkingCapitalLoanProductsProductIdRequest() //
861+
.delinquencyGraceDays(graceDays) //
862+
.delinquencyStartType(startType) //
863+
.locale(LoanProductsRequestFactory.LOCALE_EN);
864+
ok(() -> workingCapitalApi().updateWorkingCapitalLoanProduct(resourceId, updateRequest, Map.of()));
865+
}
866+
867+
private Long retrieveCreatedProductId() {
868+
final PostWorkingCapitalLoanProductsResponse productResponse = testContext()
869+
.get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_CREATE_RESPONSE);
870+
return productResponse.getResourceId();
871+
}
872+
873+
@When("Admin retrieves the Working Capital Loan Product template")
874+
public void retrieveProductTemplate() {
875+
final GetWorkingCapitalLoanProductsTemplateResponse template = ok(
876+
() -> workingCapitalApi().retrieveTemplateWorkingCapitalLoanProduct(Map.of()));
877+
testContext().set(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_TEMPLATE_RESPONSE, template);
878+
}
879+
880+
@Then("Working Capital Loan Product template has delinquencyStartTypeOptions containing:")
881+
public void verifyTemplateDelinquencyStartTypeOptions(final DataTable table) {
882+
final List<String> expectedOptions = table.asList();
883+
final GetWorkingCapitalLoanProductsTemplateResponse template = testContext()
884+
.get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_TEMPLATE_RESPONSE);
885+
assertThat(template.getDelinquencyStartTypeOptions()).isNotNull().isNotEmpty();
886+
final List<String> actualCodes = template.getDelinquencyStartTypeOptions().stream().map(StringEnumOptionData::getCode).toList();
887+
assertThat(actualCodes).containsAll(expectedOptions);
888+
}
889+
803890
}

0 commit comments

Comments
 (0)