From daf174361af53cbd9ee654ca68299c70316e3b49 Mon Sep 17 00:00:00 2001 From: DeathGun44 Date: Thu, 10 Sep 2026 23:38:36 +0530 Subject: [PATCH 1/6] FINERACT-2824: add externalId to the loan product response schema GET /loanproducts/{id} returns the product's external id - LoanProductData carries the field - but GetLoanProductsProductIdResponse never declared it, so the generated model had no getter and a test that retrieves a product by its external id could not check the value round-tripped. LoanProductExternalIdTest now asserts it. --- .../loanproduct/api/LoanProductsApiResourceSwagger.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java index 917ae10e668..605fd2c0eae 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java @@ -1426,6 +1426,8 @@ private GetWriteOffReasonToExpenseAccountMappings() {} public Boolean useBorrowerCycle; @Schema(example = "loanProduct.active") public String status; + @Schema(example = "2075e308-d4a8-44d9-8203-f5a947b8c2f4") + public String externalId; public GetLoanProductsResponse.GetLoanProductsCurrency currency; @Schema(example = "10000.000000") public Double principal; From 1cdf84ed5a2ceaf7f25a53134fad34e08665a2db Mon Sep 17 00:00:00 2001 From: DeathGun44 Date: Thu, 10 Sep 2026 23:38:36 +0530 Subject: [PATCH 2/6] FINERACT-2824: add Feign helpers for the loan lifecycle and product tests FeignRoleHelper is new: createRole and addPermissionsToRole, mirroring the REST Assured RolesHelper that the working capital loan originator test used. FeignUserHelper gains a createUser overload taking a full PostUsersRequest, for callers that set the office and roles themselves; the existing convenience overload now delegates to it. FeignLoanHelper gains retrieveLoanProductByExternalId and updateLoanProductByExternalId. FeignLoanTestBase gains extractErrorCount, the sibling of extractErrorGlobalisationCode. A validation failure reports one entry per rejected field, and LoanValidationIntegrationTest pinned that count with a REST Assured body matcher that has no typed equivalent. extractErrorGlobalisationCode also unwraps error.msg.resource.not.found now. That code is an envelope like the two the method already skipped: every AbstractPlatformResourceNotFoundException reports it at the top of the body and the entity-specific code - error.msg.loanproduct.id.invalid, say - in the nested errors array. Without it, a 404 assertion could only be made against the raw message text. The three codes move into a named constant. --- .../client/feign/FeignLoanTestBase.java | 30 +++++++++- .../client/feign/helpers/FeignLoanHelper.java | 9 +++ .../client/feign/helpers/FeignRoleHelper.java | 56 +++++++++++++++++++ .../client/feign/helpers/FeignUserHelper.java | 15 +++-- 4 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignRoleHelper.java diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/FeignLoanTestBase.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/FeignLoanTestBase.java index 04ac93ca582..49b9e41d17f 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/FeignLoanTestBase.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/FeignLoanTestBase.java @@ -36,6 +36,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; @@ -678,6 +679,15 @@ protected void checkJournalEntryForExpenseAccount(Account account, String date, journalHelper.checkJournalEntryForExpenseAccount(account, date, entries); } + /** + * Codes the server puts at the top of an error body purely as an envelope; the code that names the actual failure + * is then the first entry of the nested {@code errors} array. A resource-not-found reply is one of these: every + * {@code AbstractPlatformResourceNotFoundException} reports {@code error.msg.resource.not.found} at the top and the + * entity-specific code underneath. + */ + private static final Set GENERIC_ERROR_ENVELOPE_CODES = Set.of("validation.msg.validation.errors.exist", + "validation.msg.domain.rule.violation", "error.msg.resource.not.found"); + protected static void assertErrorGlobalisationCode(CallFailedRuntimeException exception, String expectedCode) { assertEquals(expectedCode, extractErrorGlobalisationCode(exception)); } @@ -687,8 +697,7 @@ protected static String extractErrorGlobalisationCode(CallFailedRuntimeException return exception.getUserMessageGlobalisationCode(); } String topLevelCode = feignException.getUserMessageGlobalisationCode(); - if (topLevelCode != null && !topLevelCode.equals("validation.msg.validation.errors.exist") - && !topLevelCode.equals("validation.msg.domain.rule.violation")) { + if (topLevelCode != null && !GENERIC_ERROR_ENVELOPE_CODES.contains(topLevelCode)) { return topLevelCode; } try { @@ -704,6 +713,23 @@ protected static String extractErrorGlobalisationCode(CallFailedRuntimeException return topLevelCode; } + /** + * The number of entries in the failed response's {@code errors} array. A validation failure reports one entry per + * rejected field, so a test that pinned the count with a REST Assured body matcher keeps that assertion here. + */ + protected static int extractErrorCount(CallFailedRuntimeException exception) { + if (!(exception.getCause() instanceof FeignException feignException)) { + return 0; + } + try { + Map body = ObjectMapperFactory.getShared().readValue(feignException.responseBodyAsString(), + new TypeReference>() {}); + return body.get("errors") instanceof List errorList ? errorList.size() : 0; + } catch (Exception e) { + throw new IllegalStateException("Could not read the errors array from: " + feignException.responseBodyAsString(), e); + } + } + protected LoanTestData.Journal journalEntry(double amount, Account account, String type) { return "DEBIT".equals(type) ? LoanTestData.Journal.debit(account.getAccountID().longValue(), amount) : LoanTestData.Journal.credit(account.getAccountID().longValue(), amount); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignLoanHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignLoanHelper.java index 8f1e7b60ff0..cadd3be0d38 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignLoanHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignLoanHelper.java @@ -187,6 +187,15 @@ public PutLoanProductsProductIdResponse updateLoanProduct(Long productId, PutLoa return ok(() -> fineractClient.loanProducts().updateLoanProduct(productId, request)); } + public GetLoanProductsProductIdResponse retrieveLoanProductByExternalId(String externalProductId) { + return ok(() -> fineractClient.loanProducts().retrieveLoanProductDetailsByExternalId(externalProductId)); + } + + public PutLoanProductsProductIdResponse updateLoanProductByExternalId(String externalProductId, + PutLoanProductsProductIdRequest request) { + return ok(() -> fineractClient.loanProducts().updateLoanProductByExternalId(externalProductId, request)); + } + public GetLoanProductsTemplateResponse getLoanProductTemplate(Boolean isProductMixTemplate) { return ok(() -> fineractClient.loanProducts().retrieveTemplateLoanProduct(isProductMixTemplate)); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignRoleHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignRoleHelper.java new file mode 100644 index 00000000000..470033676aa --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignRoleHelper.java @@ -0,0 +1,56 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.integrationtests.client.feign.helpers; + +import static org.apache.fineract.client.feign.util.FeignCalls.ok; + +import java.util.Map; +import org.apache.fineract.client.feign.FineractFeignClient; +import org.apache.fineract.client.models.PostRolesRequest; +import org.apache.fineract.client.models.PostRolesResponse; +import org.apache.fineract.client.models.PutRolesRoleIdPermissionsRequest; +import org.apache.fineract.client.models.PutRolesRoleIdPermissionsResponse; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; +import org.apache.fineract.integrationtests.common.Utils; + +/** Typed Feign helper for role and role-permission operations. */ +public final class FeignRoleHelper { + + private FeignRoleHelper() {} + + private static FineractFeignClient client() { + return FineractFeignClientHelper.getFineractFeignClient(); + } + + /** Creates a role with a generated name and description, and returns its id. */ + public static Long createRole() { + PostRolesResponse response = ok( + () -> client().roles().createRole(new PostRolesRequest().name(Utils.uniqueRandomStringGenerator("Role_Name_", 5)) + .description(Utils.randomStringGenerator("Role_Description_", 10)))); + return response.getResourceId(); + } + + /** + * Grants or revokes the named permissions on a role. The endpoint merges the map into the role's existing + * permissions, so a call only has to name the ones it changes. + */ + public static PutRolesRoleIdPermissionsResponse addPermissionsToRole(Long roleId, Map permissions) { + return ok(() -> client().roles().updateRolePermissions(roleId, new PutRolesRoleIdPermissionsRequest().permissions(permissions))); + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignUserHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignUserHelper.java index 0f763ed3de8..cdb35dca86b 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignUserHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/client/feign/helpers/FeignUserHelper.java @@ -64,11 +64,18 @@ public static FineractFeignClient getSimpleUserWithoutBypassPermissionClient() { * the generated user id. */ public static PostUsersResponse createUser(Long roleId, Long staffId, String username, String password) { + return createUser(new PostUsersRequest().username(username).firstname("Test").lastname("User").email("whatever@mifos.org") + .officeId(OfficeHelper.getHeadOffice().getId()).staffId(staffId).roles(List.of(roleId)).password(password) + .repeatPassword(password).sendPasswordToEmail(false)); + } + + /** + * Creates a user from a fully specified request, for callers that need to control the office, roles or name fields + * the convenience overload fixes. Mirrors {@code UserHelper.createUser(requestSpec, responseSpec, request)}. + */ + public static PostUsersResponse createUser(PostUsersRequest request) { FineractFeignClient adminClient = FineractFeignClientHelper.getFineractFeignClient(); - return ok(() -> adminClient.users() - .createUser(new PostUsersRequest().username(username).firstname("Test").lastname("User").email("whatever@mifos.org") - .officeId(OfficeHelper.getHeadOffice().getId()).staffId(staffId).roles(List.of(roleId)).password(password) - .repeatPassword(password).sendPasswordToEmail(false))); + return ok(() -> adminClient.users().createUser(request)); } private static void createSimpleUser(String username) { From 47a0a57dd89aeab4b5f8c9bbeba52b28aafd95ef Mon Sep 17 00:00:00 2001 From: DeathGun44 Date: Thu, 10 Sep 2026 23:38:36 +0530 Subject: [PATCH 3/6] FINERACT-2824: migrate the loan product configuration tests to Feign LoanProductExternalIdTest, LoanProductUpdateApiTest, LoanProductWithRepaymentDueEventConfigurationTest and LoanProductRepaymentStartDateConfigurationTest move onto FeignLoanTestBase. Products are built with LoanProductTestBuilder.buildRequest rather than its JSON build(), so the request is typed end to end. The two schedule tests replace the hand-written enable-business-date / update / finally-disable block with the base runAt helper, which performs the same three steps. Delinquency buckets come from FeignDelinquencyHelper rather than DelinquencyBucketsHelper, which still calls the retrofit client. Three unused locals are dropped from LoanProductWithRepaymentDueEventConfigurationTest: a loan external id, a client and a delinquency bucket lookup that no assertion read. --- .../LoanProductExternalIdTest.java | 55 +-- ...ctRepaymentStartDateConfigurationTest.java | 343 ++++++------------ .../LoanProductUpdateApiTest.java | 100 ++--- ...ithRepaymentDueEventConfigurationTest.java | 104 ++---- 4 files changed, 170 insertions(+), 432 deletions(-) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java index ba8fb09252d..f254f1f5650 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductExternalIdTest.java @@ -21,77 +21,52 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; -import java.util.HashMap; import java.util.UUID; +import org.apache.fineract.client.feign.util.CallFailedRuntimeException; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.PutLoanProductsProductIdRequest; import org.apache.fineract.client.models.PutLoanProductsProductIdResponse; -import org.apache.fineract.client.util.CallFailedRuntimeException; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; import org.apache.fineract.integrationtests.common.Utils; -import org.apache.fineract.integrationtests.common.loans.LoanProductHelper; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class LoanProductExternalIdTest { - - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; - private LoanProductHelper loanProductHelper; - - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); - this.loanProductHelper = new LoanProductHelper(); - } +public class LoanProductExternalIdTest extends FeignLoanTestBase { @Test public void testLoanProductWithExternalId() { String externalId = UUID.randomUUID().toString(); - HashMap request = new LoanProductTestBuilder().withExternalId(externalId).build(null, null); - Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(request)); + Long loanProductId = createLoanProduct(new LoanProductTestBuilder().withExternalId(externalId).buildRequest(null, null)); assertNotNull(loanProductId); - GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = loanProductHelper.retrieveLoanProductByExternalId(externalId); + GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = loanHelper.retrieveLoanProductByExternalId(externalId); assertNotNull(getLoanProductsProductIdResponse.getId()); - assertEquals(loanProductId, getLoanProductsProductIdResponse.getId().intValue()); + assertEquals(loanProductId, getLoanProductsProductIdResponse.getId()); + assertEquals(externalId, getLoanProductsProductIdResponse.getExternalId()); final PutLoanProductsProductIdRequest requestModifyLoan = new PutLoanProductsProductIdRequest() .shortName(Utils.uniqueRandomStringGenerator("", 3)); - PutLoanProductsProductIdResponse putLoanProductsProductIdResponse = loanProductHelper.updateLoanProductByExternalId(externalId, + PutLoanProductsProductIdResponse putLoanProductsProductIdResponse = loanHelper.updateLoanProductByExternalId(externalId, requestModifyLoan); assertNotNull(putLoanProductsProductIdResponse.getResourceId()); - assertEquals(loanProductId, putLoanProductsProductIdResponse.getResourceId().intValue()); + assertEquals(loanProductId, putLoanProductsProductIdResponse.getResourceId()); } @Test public void testLoanProductWithInvalidExternalId() { String externalId = UUID.randomUUID().toString(); - HashMap request = new LoanProductTestBuilder().withExternalId(externalId).build(null, null); - Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(request)); + Long loanProductId = createLoanProduct(new LoanProductTestBuilder().withExternalId(externalId).buildRequest(null, null)); assertNotNull(loanProductId); - GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = loanProductHelper.retrieveLoanProductByExternalId(externalId); + GetLoanProductsProductIdResponse getLoanProductsProductIdResponse = loanHelper.retrieveLoanProductByExternalId(externalId); assertNotNull(getLoanProductsProductIdResponse.getId()); - assertEquals(loanProductId, getLoanProductsProductIdResponse.getId().intValue()); + assertEquals(loanProductId, getLoanProductsProductIdResponse.getId()); CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, - () -> loanProductHelper.retrieveLoanProductByExternalId(externalId.substring(2))); - assertEquals(404, exception.getResponse().code()); - assertTrue(exception.getMessage().contains("error.msg.loanproduct.id.invalid")); + () -> loanHelper.retrieveLoanProductByExternalId(externalId.substring(2))); + assertEquals(404, exception.getStatus()); + assertErrorGlobalisationCode(exception, "error.msg.loanproduct.id.invalid"); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java index 19c55e2f507..027c4735083 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductRepaymentStartDateConfigurationTest.java @@ -21,80 +21,54 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; import java.time.LocalDate; -import java.util.HashMap; import java.util.UUID; -import org.apache.fineract.client.models.DelinquencyBucketResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.GetLoansLoanIdResponse; -import org.apache.fineract.client.models.PutGlobalConfigurationsRequest; import org.apache.fineract.client.models.PutLoanProductsProductIdRequest; import org.apache.fineract.client.models.PutLoanProductsProductIdResponse; -import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; -import org.apache.fineract.infrastructure.configuration.api.GlobalConfigurationConstants; -import org.apache.fineract.integrationtests.common.BusinessDateHelper; -import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignDelinquencyHelper; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; +import org.apache.fineract.integrationtests.client.feign.modules.LoanTestData; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; import org.apache.fineract.integrationtests.common.Utils; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class LoanProductRepaymentStartDateConfigurationTest { - - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; - private ClientHelper clientHelper; - private GlobalConfigurationHelper globalConfigurationHelper; - - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); - this.globalConfigurationHelper = new GlobalConfigurationHelper(); - } +public class LoanProductRepaymentStartDateConfigurationTest extends FeignLoanTestBase { + + private static final Integer REPAYMENT_START_DATE_TYPE_DISBURSEMENT_DATE = 1; + private static final Integer REPAYMENT_START_DATE_TYPE_SUBMITTED_ON_DATE = 2; + + private final FeignDelinquencyHelper delinquencyHelper = new FeignDelinquencyHelper(FineractFeignClientHelper.getFineractFeignClient()); @Test public void loanProductWithRepaymentStartDateTypeConfigurationCreateAndModifyTest() { // create product with repayment start date configuration, get , modify // Delinquency Bucket - final Long delinquencyBucketId = DelinquencyBucketsHelper.createDefaultBucket(); - final DelinquencyBucketResponse delinquencyBucket = DelinquencyBucketsHelper.getBucket(delinquencyBucketId); - - final Integer repaymentStartDateType = 2; + final Long delinquencyBucketId = delinquencyHelper.createDefaultBucket(); // create loan product with repayment start date configuration - Integer loanProductId = createLoanProductWithRepaymentStartDateTypeConfiguration(loanTransactionHelper, delinquencyBucketId, - repaymentStartDateType); + Long loanProductId = createLoanProductWithRepaymentStartDateTypeConfiguration(delinquencyBucketId, + REPAYMENT_START_DATE_TYPE_SUBMITTED_ON_DATE); - GetLoanProductsProductIdResponse getLoanProductsProductResponse = loanTransactionHelper.getLoanProduct(loanProductId); + GetLoanProductsProductIdResponse getLoanProductsProductResponse = retrieveLoanProduct(loanProductId); assertNotNull(getLoanProductsProductResponse); - assertEquals(repaymentStartDateType, getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); + assertEquals(REPAYMENT_START_DATE_TYPE_SUBMITTED_ON_DATE, + getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); assertEquals("repaymentStartDateType.submittedOnDate", getLoanProductsProductResponse.getRepaymentStartDateType().getCode()); // modify loan product repayment start date configuration to disbursement date - PutLoanProductsProductIdResponse loanProductModifyResponse = updateLoanProduct(loanTransactionHelper, - getLoanProductsProductResponse.getId()); + PutLoanProductsProductIdResponse loanProductModifyResponse = updateRepaymentStartDateType(getLoanProductsProductResponse.getId()); assertNotNull(loanProductModifyResponse); - getLoanProductsProductResponse = loanTransactionHelper.getLoanProduct(loanProductId); + getLoanProductsProductResponse = retrieveLoanProduct(loanProductId); assertNotNull(getLoanProductsProductResponse); - assertEquals(1, getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); + assertEquals(REPAYMENT_START_DATE_TYPE_DISBURSEMENT_DATE, + getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); assertEquals("repaymentStartDateType.disbursementDate", getLoanProductsProductResponse.getRepaymentStartDateType().getCode()); } @@ -104,18 +78,15 @@ public void loanProductWithNoRepaymentStartDateTypeConfigurationDefaultsToDisbur // create loan product with no configuration for repayment start date and verify that it is disbursement date by // default // Delinquency Bucket - final Long delinquencyBucketId = DelinquencyBucketsHelper.createDefaultBucket(); - final DelinquencyBucketResponse delinquencyBucket = DelinquencyBucketsHelper.getBucket(delinquencyBucketId); - - final Integer repaymentStartDateType = null; + final Long delinquencyBucketId = delinquencyHelper.createDefaultBucket(); // create loan product with repayment start date configuration - Integer loanProductId = createLoanProductWithRepaymentStartDateTypeConfiguration(loanTransactionHelper, delinquencyBucketId, - repaymentStartDateType); + Long loanProductId = createLoanProductWithRepaymentStartDateTypeConfiguration(delinquencyBucketId, null); - GetLoanProductsProductIdResponse getLoanProductsProductResponse = loanTransactionHelper.getLoanProduct(loanProductId); + GetLoanProductsProductIdResponse getLoanProductsProductResponse = retrieveLoanProduct(loanProductId); assertNotNull(getLoanProductsProductResponse); - assertEquals(1, getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); + assertEquals(REPAYMENT_START_DATE_TYPE_DISBURSEMENT_DATE, + getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); assertEquals("repaymentStartDateType.disbursementDate", getLoanProductsProductResponse.getRepaymentStartDateType().getCode()); } @@ -123,39 +94,30 @@ public void loanProductWithNoRepaymentStartDateTypeConfigurationDefaultsToDisbur public void loanAccountWithLoanProductRepaymentStartDateTypeAsSubmittedOnDateScheduleTest() { // create loan account with product with repayment start date type configuration as submitted on date, verify // repayment schedule is according to submitted on date, before and after disbursements - try { - - // Set business date - LocalDate businessDate = LocalDate.of(2023, 3, 3); - - globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE, - new PutGlobalConfigurationsRequest().enabled(true)); - BusinessDateHelper.updateBusinessDate(BusinessDateType.BUSINESS_DATE, businessDate); + runAt("2023-03-03", () -> { // Loan ExternalId String loanExternalIdStr = UUID.randomUUID().toString(); - final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); - - // set repayment start date type as submittedOn date - final Integer repaymentStartDateType = 2; + final Long clientId = createClient(); // Loan Product creation with repayment start date type configuration final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProductWithRepaymentStartDateTypeConfigurationAndMultipleDisbursements( - loanTransactionHelper, repaymentStartDateType); + REPAYMENT_START_DATE_TYPE_SUBMITTED_ON_DATE); assertNotNull(getLoanProductsProductResponse); - assertEquals(repaymentStartDateType, getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); + assertEquals(REPAYMENT_START_DATE_TYPE_SUBMITTED_ON_DATE, + getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); assertEquals("repaymentStartDateType.submittedOnDate", getLoanProductsProductResponse.getRepaymentStartDateType().getCode()); // create loan account with submitted date as business date (03 March 2023) and expected disbursement date // as future date (07 March 2023) - final Integer loanId = createLoanAccountMultipleRepaymentsDisbursement(clientId, getLoanProductsProductResponse.getId(), + final Long loanId = createLoanAccountMultipleRepaymentsDisbursement(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr); // Retrieve Loan with loanId - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + GetLoansLoanIdResponse loanDetails = getLoanDetails(loanId); assertNotNull(loanDetails); @@ -163,7 +125,7 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsSubmittedOnDateSch assertNotNull(loanDetails.getRepaymentSchedule()); // loan term - assertEquals(92, loanDetails.getRepaymentSchedule().getLoanTermInDays()); + assertEquals(92L, loanDetails.getRepaymentSchedule().getLoanTermInDays()); assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); @@ -171,41 +133,27 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsSubmittedOnDateSch assertEquals(1000.0, Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getTotalPrincipalExpected())); // first period [2023-03-03 to 2023-04-03] - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 1, 1, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3), 333.33); // second period [2023-04-03 to 2023-05-03] - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 2, 2, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3), 333.33); // third period [2023-05-03 to 2023-06-03] - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 6, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(333.34, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 3, 3, LocalDate.of(2023, 5, 3), LocalDate.of(2023, 6, 3), 333.34); // first disbursement on a future date (7 March 2023) - LocalDate disbursementDate = LocalDate.of(2023, 3, 7); + updateBusinessDate("07 March 2023"); - BusinessDateHelper.updateBusinessDate(BusinessDateType.BUSINESS_DATE, disbursementDate); + disburseLoan(loanId, LoanRequestBuilders.disburseLoan(500.0, "07 March 2023")); - loanTransactionHelper.disburseLoanWithTransactionAmount("07 March 2023", loanId, "500"); - - loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + loanDetails = getLoanDetails(loanId); // verify loan schedule is according to submitted on date after first disbursement assertNotNull(loanDetails); assertNotNull(loanDetails.getRepaymentSchedule()); // loan term - assertEquals(92, loanDetails.getRepaymentSchedule().getLoanTermInDays()); + assertEquals(92L, loanDetails.getRepaymentSchedule().getLoanTermInDays()); assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); // verify amounts @@ -213,42 +161,28 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsSubmittedOnDateSch assertEquals(500.0, Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getTotalPrincipalDisbursed())); // first period [2023-03-03 to 2023-04-03] - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(166.67, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 1, 1, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3), 166.67); // second period [2023-04-03 to 2023-05-03] - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(166.67, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 2, 2, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3), 166.67); // third period [2023-05-03 to 2023-06-03] - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 6, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(166.66, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 3, 3, LocalDate.of(2023, 5, 3), LocalDate.of(2023, 6, 3), 166.66); // second disbursement next month (7 April 2023) - disbursementDate = LocalDate.of(2023, 4, 7); - - BusinessDateHelper.updateBusinessDate(BusinessDateType.BUSINESS_DATE, disbursementDate); + updateBusinessDate("07 April 2023"); - loanTransactionHelper.disburseLoanWithTransactionAmount("07 April 2023", loanId, "500"); + disburseLoan(loanId, LoanRequestBuilders.disburseLoan(500.0, "07 April 2023")); - loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + loanDetails = getLoanDetails(loanId); // verify loan schedule is according to submitted on date after second disbursement assertNotNull(loanDetails); assertNotNull(loanDetails.getRepaymentSchedule()); // loan term - assertEquals(92, loanDetails.getRepaymentSchedule().getLoanTermInDays()); + assertEquals(92L, loanDetails.getRepaymentSchedule().getLoanTermInDays()); assertEquals(5, loanDetails.getRepaymentSchedule().getPeriods().size()); // verify amounts @@ -256,30 +190,14 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsSubmittedOnDateSch assertEquals(1000.0, Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getTotalPrincipalDisbursed())); // first period [2023-03-03 to 2023-04-03] - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 1, 1, LocalDate.of(2023, 3, 3), LocalDate.of(2023, 4, 3), 333.33); // second period [2023-04-03 to 2023-05-03] - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 3, 2, LocalDate.of(2023, 4, 3), LocalDate.of(2023, 5, 3), 333.33); // third period [2023-05-03 to 2023-06-03] - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 5, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 6, 3), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(333.34, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod())); - - } finally { - globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE, - new PutGlobalConfigurationsRequest().enabled(false)); - } + verifyPeriod(loanDetails, 4, 3, LocalDate.of(2023, 5, 3), LocalDate.of(2023, 6, 3), 333.34); + }); } @@ -288,39 +206,30 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsDisbursementDateSc // create loan account with loan product with repayment start date type configuration as disbursement date , // verify repayment schedule is as per disbursement date before and after disbursements - try { - - // Set business date - LocalDate businessDate = LocalDate.of(2023, 3, 3); - - globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE, - new PutGlobalConfigurationsRequest().enabled(true)); - BusinessDateHelper.updateBusinessDate(BusinessDateType.BUSINESS_DATE, businessDate); + runAt("2023-03-03", () -> { // Loan ExternalId String loanExternalIdStr = UUID.randomUUID().toString(); - final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); - - // set repayment start date type as default, disbursement date - final Integer repaymentStartDateType = 1; + final Long clientId = createClient(); // Loan Product creation with repayment date type configuration final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProductWithRepaymentStartDateTypeConfigurationAndMultipleDisbursements( - loanTransactionHelper, repaymentStartDateType); + REPAYMENT_START_DATE_TYPE_DISBURSEMENT_DATE); assertNotNull(getLoanProductsProductResponse); - assertEquals(repaymentStartDateType, getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); + assertEquals(REPAYMENT_START_DATE_TYPE_DISBURSEMENT_DATE, + getLoanProductsProductResponse.getRepaymentStartDateType().getId().intValue()); assertEquals("repaymentStartDateType.disbursementDate", getLoanProductsProductResponse.getRepaymentStartDateType().getCode()); // create loan account with submitted date as business date (03 March 2023) and expected disbursement date // (07 March 2023) - final Integer loanId = createLoanAccountMultipleRepaymentsDisbursement(clientId, getLoanProductsProductResponse.getId(), + final Long loanId = createLoanAccountMultipleRepaymentsDisbursement(clientId, getLoanProductsProductResponse.getId(), loanExternalIdStr); // Retrieve Loan with loanId - GetLoansLoanIdResponse loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + GetLoansLoanIdResponse loanDetails = getLoanDetails(loanId); assertNotNull(loanDetails); @@ -329,7 +238,7 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsDisbursementDateSc assertNotNull(loanDetails.getRepaymentSchedule()); // loan term - assertEquals(92, loanDetails.getRepaymentSchedule().getLoanTermInDays()); + assertEquals(92L, loanDetails.getRepaymentSchedule().getLoanTermInDays()); assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); @@ -337,42 +246,28 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsDisbursementDateSc assertEquals(1000.0, Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getTotalPrincipalExpected())); // first period [2023-03-07 to 2023-04-07] - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 1, 1, LocalDate.of(2023, 3, 7), LocalDate.of(2023, 4, 7), 333.33); // second period [2023-04-07 to 2023-05-07] - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 2, 2, LocalDate.of(2023, 4, 7), LocalDate.of(2023, 5, 7), 333.33); // third period [2023-05-07 to 2023-06-07] - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 6, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(333.34, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 3, 3, LocalDate.of(2023, 5, 7), LocalDate.of(2023, 6, 7), 333.34); // first disbursement (7 March 2023) - LocalDate disbursementDate = LocalDate.of(2023, 3, 7); - - BusinessDateHelper.updateBusinessDate(BusinessDateType.BUSINESS_DATE, disbursementDate); + updateBusinessDate("07 March 2023"); - loanTransactionHelper.disburseLoanWithTransactionAmount("07 March 2023", loanId, "500"); + disburseLoan(loanId, LoanRequestBuilders.disburseLoan(500.0, "07 March 2023")); - loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + loanDetails = getLoanDetails(loanId); // verify loan schedule is according to disbursement date assertNotNull(loanDetails); assertNotNull(loanDetails.getRepaymentSchedule()); // loan term - assertEquals(92, loanDetails.getRepaymentSchedule().getLoanTermInDays()); + assertEquals(92L, loanDetails.getRepaymentSchedule().getLoanTermInDays()); assertEquals(4, loanDetails.getRepaymentSchedule().getPeriods().size()); // verify amounts @@ -380,35 +275,21 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsDisbursementDateSc assertEquals(500.0, Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getTotalPrincipalDisbursed())); // first period [2023-03-07 to 2023-04-07] - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(1).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(1).getDueDate()); - assertEquals(166.67, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(1).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 1, 1, LocalDate.of(2023, 3, 7), LocalDate.of(2023, 4, 7), 166.67); // second period [2023-04-07 to 2023-05-07] - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(166.67, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 2, 2, LocalDate.of(2023, 4, 7), LocalDate.of(2023, 5, 7), 166.67); // third period [2023-05-07 to 2023-06-07] - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 6, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(166.66, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 3, 3, LocalDate.of(2023, 5, 7), LocalDate.of(2023, 6, 7), 166.66); // second disbursement next month (7 April 2023) - disbursementDate = LocalDate.of(2023, 4, 7); + updateBusinessDate("07 April 2023"); - BusinessDateHelper.updateBusinessDate(BusinessDateType.BUSINESS_DATE, disbursementDate); + disburseLoan(loanId, LoanRequestBuilders.disburseLoan(500.0, "07 April 2023")); - loanTransactionHelper.disburseLoanWithTransactionAmount("07 April 2023", loanId, "500"); - - loanDetails = loanTransactionHelper.getLoanDetails(loanId.longValue()); + loanDetails = getLoanDetails(loanId); // verify loan schedule is according to disbursement after second disbursement @@ -416,7 +297,7 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsDisbursementDateSc assertNotNull(loanDetails.getRepaymentSchedule()); // loan term - assertEquals(92, loanDetails.getRepaymentSchedule().getLoanTermInDays()); + assertEquals(92L, loanDetails.getRepaymentSchedule().getLoanTermInDays()); assertEquals(5, loanDetails.getRepaymentSchedule().getPeriods().size()); // verify amounts @@ -424,75 +305,57 @@ public void loanAccountWithLoanProductRepaymentStartDateTypeAsDisbursementDateSc assertEquals(1000.0, Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getTotalPrincipalDisbursed())); // first period [2023-03-07 to 2023-04-07] - assertEquals(1, loanDetails.getRepaymentSchedule().getPeriods().get(2).getPeriod()); - assertEquals(LocalDate.of(2023, 3, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getFromDate()); - assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(2).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(2).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 2, 1, LocalDate.of(2023, 3, 7), LocalDate.of(2023, 4, 7), 333.33); // second period [2023-04-07 to 2023-05-07] - assertEquals(2, loanDetails.getRepaymentSchedule().getPeriods().get(3).getPeriod()); - assertEquals(LocalDate.of(2023, 4, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getFromDate()); - assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(3).getDueDate()); - assertEquals(333.33, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(3).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 3, 2, LocalDate.of(2023, 4, 7), LocalDate.of(2023, 5, 7), 333.33); // third period [2023-05-07 to 2023-06-07] - assertEquals(3, loanDetails.getRepaymentSchedule().getPeriods().get(4).getPeriod()); - assertEquals(LocalDate.of(2023, 5, 7), loanDetails.getRepaymentSchedule().getPeriods().get(4).getFromDate()); - assertEquals(LocalDate.of(2023, 6, 7), loanDetails.getRepaymentSchedule().getPeriods().get(4).getDueDate()); - assertEquals(333.34, - Utils.getDoubleValue(loanDetails.getRepaymentSchedule().getPeriods().get(4).getTotalInstallmentAmountForPeriod())); + verifyPeriod(loanDetails, 4, 3, LocalDate.of(2023, 5, 7), LocalDate.of(2023, 6, 7), 333.34); + }); - } finally { - globalConfigurationHelper.updateGlobalConfiguration(GlobalConfigurationConstants.ENABLE_BUSINESS_DATE, - new PutGlobalConfigurationsRequest().enabled(false)); - } + } + private void verifyPeriod(GetLoansLoanIdResponse loanDetails, int index, int expectedPeriod, LocalDate expectedFromDate, + LocalDate expectedDueDate, double expectedInstallmentAmount) { + var period = loanDetails.getRepaymentSchedule().getPeriods().get(index); + assertEquals(expectedPeriod, period.getPeriod()); + assertEquals(expectedFromDate, period.getFromDate()); + assertEquals(expectedDueDate, period.getDueDate()); + assertEquals(expectedInstallmentAmount, Utils.getDoubleValue(period.getTotalInstallmentAmountForPeriod())); } - private PutLoanProductsProductIdResponse updateLoanProduct(LoanTransactionHelper loanTransactionHelper, Long id) { + private PutLoanProductsProductIdResponse updateRepaymentStartDateType(Long id) { // repayment start date configuration - final Integer repaymentStartDateType = 1; final PutLoanProductsProductIdRequest requestModifyLoan = new PutLoanProductsProductIdRequest() - .repaymentStartDateType(repaymentStartDateType).locale("en"); - return loanTransactionHelper.updateLoanProduct(id, requestModifyLoan); + .repaymentStartDateType(REPAYMENT_START_DATE_TYPE_DISBURSEMENT_DATE).locale("en"); + return updateLoanProduct(id, requestModifyLoan); } - private Integer createLoanProductWithRepaymentStartDateTypeConfiguration(final LoanTransactionHelper loanTransactionHelper, - final Long delinquencyBucketId, final Integer repaymentStartDateType) { - final HashMap loanProductMap = new LoanProductTestBuilder().withRepaymentStartDateType(repaymentStartDateType) - .build(null, delinquencyBucketId); - final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); - return loanProductId; - + private Long createLoanProductWithRepaymentStartDateTypeConfiguration(final Long delinquencyBucketId, + final Integer repaymentStartDateType) { + return createLoanProduct( + new LoanProductTestBuilder().withRepaymentStartDateType(repaymentStartDateType).buildRequest(null, delinquencyBucketId)); } - private Integer createLoanAccountMultipleRepaymentsDisbursement(final Integer clientID, final Long loanProductID, - final String externalId) { - - String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("3") - .withLoanTermFrequencyAsMonths().withNumberOfRepayments("3").withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsDecliningBalance() - .withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod() - .withExpectedDisbursementDate("07 March 2023").withSubmittedOnDate("03 March 2023").withLoanType("individual") - .withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null); - - final Integer loanId = loanTransactionHelper.getLoanId(loanApplicationJSON); - loanTransactionHelper.approveLoan("03 March 2023", "1000", loanId, null); + private Long createLoanAccountMultipleRepaymentsDisbursement(final Long clientId, final Long loanProductId, final String externalId) { + final Long loanId = applyForLoan(LoanRequestBuilders.applyLoan(clientId, loanProductId, "03 March 2023", 1000.0, 3)// + .expectedDisbursementDate("07 March 2023")// + .amortizationType(LoanTestData.AmortizationType.EQUAL_PRINCIPAL)// + .externalId(externalId)); + approveLoan(loanId, LoanRequestBuilders.approveLoan(1000.0, "03 March 2023")); return loanId; } private GetLoanProductsProductIdResponse createLoanProductWithRepaymentStartDateTypeConfigurationAndMultipleDisbursements( - LoanTransactionHelper loanTransactionHelper, final Integer repaymentStartDateType) { - final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth() + final Integer repaymentStartDateType) { + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth() .withRepaymentAfterEvery("1").withNumberOfRepayments("3").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0") .withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsDecliningBalance() .withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withDaysInMonth("30").withDaysInYear("365") .withMoratorium("0", "0").withMultiDisburse().withDisallowExpectedDisbursements(true) - .withRepaymentStartDateType(repaymentStartDateType).build(null); - final Integer loanProductId = loanTransactionHelper.getLoanProductId(loanProductJSON); - return loanTransactionHelper.getLoanProduct(loanProductId); + .withRepaymentStartDateType(repaymentStartDateType).buildRequest()); + return retrieveLoanProduct(loanProductId); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductUpdateApiTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductUpdateApiTest.java index 7127f349f88..09d69616485 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductUpdateApiTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductUpdateApiTest.java @@ -18,43 +18,22 @@ */ package org.apache.fineract.integrationtests; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; import java.util.Arrays; -import java.util.List; import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; import org.apache.fineract.client.models.AdvancedPaymentData; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; -import org.apache.fineract.client.models.PaymentAllocationOrder; import org.apache.fineract.client.models.PutLoanProductsProductIdRequest; -import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType; import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType; -import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -public class LoanProductUpdateApiTest { +public class LoanProductUpdateApiTest extends FeignLoanTestBase { - private static LoanTransactionHelper LOAN_TRANSACTION_HELPER; - private static ResponseSpecification RESPONSE_SPEC; - private static RequestSpecification REQUEST_SPEC; - - @BeforeAll - public static void setupTests() { - Utils.initializeRESTAssured(); - REQUEST_SPEC = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - REQUEST_SPEC.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - RESPONSE_SPEC = new ResponseSpecBuilder().expectStatusCode(200).build(); - LOAN_TRANSACTION_HELPER = new LoanTransactionHelper(REQUEST_SPEC, RESPONSE_SPEC); - } + private static final String DEFAULT_TRANSACTION_TYPE = "DEFAULT"; + private static final String ADVANCED_PAYMENT_ALLOCATION_STRATEGY = "advanced-payment-allocation-strategy"; @Test public void loanProductModifyForAdvancedPaymentAllocationRuleTest() { @@ -63,15 +42,15 @@ public void loanProductModifyForAdvancedPaymentAllocationRuleTest() { String futureInstallmentAllocationRule = "NEXT_INSTALLMENT"; AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation(futureInstallmentAllocationRule); - Integer loanProductId = createLoanProduct(defaultAllocation); + Long loanProductId = createAdvancedPaymentAllocationProduct(defaultAllocation); Assertions.assertNotNull(loanProductId); // verify allocation rule - GetLoanProductsProductIdResponse loanProduct = LOAN_TRANSACTION_HELPER.getLoanProduct(loanProductId); + GetLoanProductsProductIdResponse loanProduct = retrieveLoanProduct(loanProductId); Assertions.assertNotNull(loanProduct.getPaymentAllocation()); Optional defaultAllocationAfterCreate = loanProduct.getPaymentAllocation().stream() - .filter(advancedPaymentData -> "DEFAULT".equals(advancedPaymentData.getTransactionType())).findFirst(); + .filter(advancedPaymentData -> DEFAULT_TRANSACTION_TYPE.equals(advancedPaymentData.getTransactionType())).findFirst(); Assertions.assertTrue(defaultAllocationAfterCreate.isPresent()); Assertions.assertEquals(futureInstallmentAllocationRule, defaultAllocationAfterCreate.get().getFutureInstallmentAllocationRule()); @@ -79,15 +58,15 @@ public void loanProductModifyForAdvancedPaymentAllocationRuleTest() { futureInstallmentAllocationRule = "LAST_INSTALLMENT"; defaultAllocation = createDefaultPaymentAllocation(futureInstallmentAllocationRule); - loanProductId = updateLoanProduct(loanProductId, defaultAllocation); + loanProductId = updatePaymentAllocation(loanProductId, defaultAllocation); Assertions.assertNotNull(loanProductId); - loanProduct = LOAN_TRANSACTION_HELPER.getLoanProduct(loanProductId); + loanProduct = retrieveLoanProduct(loanProductId); Assertions.assertNotNull(loanProduct.getPaymentAllocation()); // verify allocation rule Optional defaultAllocationAfterUpdate = loanProduct.getPaymentAllocation().stream() - .filter(advancedPaymentData -> "DEFAULT".equals(advancedPaymentData.getTransactionType())).findFirst(); + .filter(advancedPaymentData -> DEFAULT_TRANSACTION_TYPE.equals(advancedPaymentData.getTransactionType())).findFirst(); Assertions.assertTrue(defaultAllocationAfterUpdate.isPresent()); Assertions.assertEquals(futureInstallmentAllocationRule, defaultAllocationAfterUpdate.get().getFutureInstallmentAllocationRule()); @@ -100,15 +79,15 @@ public void loanProductWithInterestCalculationTypeDailyModifyForAdvancedPaymentA String futureInstallmentAllocationRule = "NEXT_INSTALLMENT"; AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation(futureInstallmentAllocationRule); - Integer loanProductId = createLoanProductWithInterestCalculationPeriodTypeDaily(defaultAllocation); + Long loanProductId = createAdvancedPaymentAllocationProductWithInterestCalculationPeriodTypeDaily(defaultAllocation); Assertions.assertNotNull(loanProductId); // verify allocation rule - GetLoanProductsProductIdResponse loanProduct = LOAN_TRANSACTION_HELPER.getLoanProduct(loanProductId); + GetLoanProductsProductIdResponse loanProduct = retrieveLoanProduct(loanProductId); Assertions.assertNotNull(loanProduct.getPaymentAllocation()); Optional defaultAllocationAfterCreate = loanProduct.getPaymentAllocation().stream() - .filter(advancedPaymentData -> "DEFAULT".equals(advancedPaymentData.getTransactionType())).findFirst(); + .filter(advancedPaymentData -> DEFAULT_TRANSACTION_TYPE.equals(advancedPaymentData.getTransactionType())).findFirst(); Assertions.assertTrue(defaultAllocationAfterCreate.isPresent()); Assertions.assertEquals(futureInstallmentAllocationRule, defaultAllocationAfterCreate.get().getFutureInstallmentAllocationRule()); @@ -116,70 +95,41 @@ public void loanProductWithInterestCalculationTypeDailyModifyForAdvancedPaymentA futureInstallmentAllocationRule = "LAST_INSTALLMENT"; defaultAllocation = createDefaultPaymentAllocation(futureInstallmentAllocationRule); - loanProductId = updateLoanProduct(loanProductId, defaultAllocation); + loanProductId = updatePaymentAllocation(loanProductId, defaultAllocation); Assertions.assertNotNull(loanProductId); - loanProduct = LOAN_TRANSACTION_HELPER.getLoanProduct(loanProductId); + loanProduct = retrieveLoanProduct(loanProductId); Assertions.assertNotNull(loanProduct.getPaymentAllocation()); // verify allocation rule Optional defaultAllocationAfterUpdate = loanProduct.getPaymentAllocation().stream() - .filter(advancedPaymentData -> "DEFAULT".equals(advancedPaymentData.getTransactionType())).findFirst(); + .filter(advancedPaymentData -> DEFAULT_TRANSACTION_TYPE.equals(advancedPaymentData.getTransactionType())).findFirst(); Assertions.assertTrue(defaultAllocationAfterUpdate.isPresent()); Assertions.assertEquals(futureInstallmentAllocationRule, defaultAllocationAfterUpdate.get().getFutureInstallmentAllocationRule()); } - private Integer updateLoanProduct(Integer loanProductId, AdvancedPaymentData... advancedPaymentData) { + private Long updatePaymentAllocation(Long loanProductId, AdvancedPaymentData... advancedPaymentData) { final PutLoanProductsProductIdRequest requestModifyLoan = new PutLoanProductsProductIdRequest() - .transactionProcessingStrategyCode("advanced-payment-allocation-strategy") + .transactionProcessingStrategyCode(ADVANCED_PAYMENT_ALLOCATION_STRATEGY) .paymentAllocation(Arrays.stream(advancedPaymentData).toList()).locale("en"); - return LOAN_TRANSACTION_HELPER.updateLoanProduct(loanProductId.longValue(), requestModifyLoan).getResourceId().intValue(); + return updateLoanProduct(loanProductId, requestModifyLoan).getResourceId(); } - private Integer createLoanProduct(AdvancedPaymentData... advancedPaymentData) { - String loanProductCreateJSON = new LoanProductTestBuilder().withPrincipal("15,000.00").withNumberOfRepayments("4") + private Long createAdvancedPaymentAllocationProduct(AdvancedPaymentData... advancedPaymentData) { + return createLoanProduct(new LoanProductTestBuilder().withPrincipal("15,000.00").withNumberOfRepayments("4") .withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("1") .withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestTypeAsDecliningBalance() .addAdvancedPaymentAllocation(advancedPaymentData).withLoanScheduleType(LoanScheduleType.PROGRESSIVE) - .withLoanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL).build(); - return LOAN_TRANSACTION_HELPER.getLoanProductId(loanProductCreateJSON); - + .withLoanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL).buildRequest()); } - private Integer createLoanProductWithInterestCalculationPeriodTypeDaily(AdvancedPaymentData... advancedPaymentData) { - String loanProductCreateJSON = new LoanProductTestBuilder().withPrincipal("15,000.00").withNumberOfRepayments("4") + private Long createAdvancedPaymentAllocationProductWithInterestCalculationPeriodTypeDaily(AdvancedPaymentData... advancedPaymentData) { + return createLoanProduct(new LoanProductTestBuilder().withPrincipal("15,000.00").withNumberOfRepayments("4") .withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("1") .withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestTypeAsDecliningBalance() .withInterestCalculationPeriodTypeAsDays().withAllowPartialPeriodInterestCalculation(false) .addAdvancedPaymentAllocation(advancedPaymentData).withLoanScheduleType(LoanScheduleType.PROGRESSIVE) - .withLoanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL).build(); - return LOAN_TRANSACTION_HELPER.getLoanProductId(loanProductCreateJSON); - - } - - private AdvancedPaymentData createDefaultPaymentAllocation(String futureInstallmentAllocationRule) { - AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData(); - advancedPaymentData.setTransactionType("DEFAULT"); - advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule); - - List paymentAllocationOrders = getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY, - PaymentAllocationType.PAST_DUE_FEE, PaymentAllocationType.PAST_DUE_PRINCIPAL, PaymentAllocationType.PAST_DUE_INTEREST, - PaymentAllocationType.DUE_PENALTY, PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL, - PaymentAllocationType.DUE_INTEREST, PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE, - PaymentAllocationType.IN_ADVANCE_PRINCIPAL, PaymentAllocationType.IN_ADVANCE_INTEREST); - - advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders); - return advancedPaymentData; - } - - private List getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) { - AtomicInteger integer = new AtomicInteger(1); - return Arrays.stream(paymentAllocationTypes).map(pat -> { - PaymentAllocationOrder paymentAllocationOrder = new PaymentAllocationOrder(); - paymentAllocationOrder.setPaymentAllocationRule(pat.name()); - paymentAllocationOrder.setOrder(integer.getAndIncrement()); - return paymentAllocationOrder; - }).toList(); + .withLoanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL).buildRequest()); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithRepaymentDueEventConfigurationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithRepaymentDueEventConfigurationTest.java index 4832f348cda..619f3359a4f 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithRepaymentDueEventConfigurationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithRepaymentDueEventConfigurationTest.java @@ -21,113 +21,63 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; -import java.util.HashMap; -import java.util.UUID; -import org.apache.fineract.client.models.DelinquencyBucketResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; import org.apache.fineract.client.models.PutLoanProductsProductIdRequest; import org.apache.fineract.client.models.PutLoanProductsProductIdResponse; -import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignDelinquencyHelper; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class LoanProductWithRepaymentDueEventConfigurationTest { +public class LoanProductWithRepaymentDueEventConfigurationTest extends FeignLoanTestBase { - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private ClientHelper clientHelper; - private LoanTransactionHelper loanTransactionHelper; + private static final Integer DUE_DAYS_FOR_REPAYMENT_EVENT = 1; + private static final Integer OVER_DUE_DAYS_FOR_REPAYMENT_EVENT = 2; - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - } + private final FeignDelinquencyHelper delinquencyHelper = new FeignDelinquencyHelper(FineractFeignClientHelper.getFineractFeignClient()); @Test public void loanProductCreationWithDueDaysConfigurationForRepaymentEventTest() { - // Loan ExternalId - String loanExternalIdStr = UUID.randomUUID().toString(); - - // Delinquency Bucket - final Long delinquencyBucketId = DelinquencyBucketsHelper.createDefaultBucket(); - final DelinquencyBucketResponse delinquencyBucket = DelinquencyBucketsHelper.getBucket(delinquencyBucketId); - - // event days configuration - Integer dueDaysForRepaymentEvent = 1; - Integer overDueDaysForRepaymentEvent = 2; - - // Client and Loan account creation + final Long delinquencyBucketId = delinquencyHelper.createDefaultBucket(); - final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); - Integer loanProductId = createLoanProductWithDueDaysForRepaymentEvent(loanTransactionHelper, delinquencyBucketId, - dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent); - final GetLoanProductsProductIdResponse getLoanProductsProductResponse = loanTransactionHelper.getLoanProduct(loanProductId); + Long loanProductId = createLoanProductWithDueDaysForRepaymentEvent(delinquencyBucketId, DUE_DAYS_FOR_REPAYMENT_EVENT, + OVER_DUE_DAYS_FOR_REPAYMENT_EVENT); + final GetLoanProductsProductIdResponse getLoanProductsProductResponse = retrieveLoanProduct(loanProductId); assertNotNull(getLoanProductsProductResponse); assertNotNull(getLoanProductsProductResponse.getDueDaysForRepaymentEvent()); assertNotNull(getLoanProductsProductResponse.getOverDueDaysForRepaymentEvent()); - assertEquals(getLoanProductsProductResponse.getDueDaysForRepaymentEvent(), dueDaysForRepaymentEvent); - assertEquals(getLoanProductsProductResponse.getOverDueDaysForRepaymentEvent(), overDueDaysForRepaymentEvent); + assertEquals(DUE_DAYS_FOR_REPAYMENT_EVENT, getLoanProductsProductResponse.getDueDaysForRepaymentEvent()); + assertEquals(OVER_DUE_DAYS_FOR_REPAYMENT_EVENT, getLoanProductsProductResponse.getOverDueDaysForRepaymentEvent()); } @Test public void loanProductUpdateWithDueDaysConfigurationForRepaymentEventTest() { - // Loan ExternalId - String loanExternalIdStr = UUID.randomUUID().toString(); + final Long delinquencyBucketId = delinquencyHelper.createDefaultBucket(); - // Delinquency Bucket - final Long delinquencyBucketId = DelinquencyBucketsHelper.createDefaultBucket(); - final DelinquencyBucketResponse delinquencyBucket = DelinquencyBucketsHelper.getBucket(delinquencyBucketId); - - // Client and Loan account creation - - final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); - final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper, - delinquencyBucketId); + final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createDefaultLoanProduct(delinquencyBucketId); assertNotNull(getLoanProductsProductResponse); - // Modify Loan Product - PutLoanProductsProductIdResponse loanProductModifyResponse = updateLoanProduct(loanTransactionHelper, - getLoanProductsProductResponse.getId()); + PutLoanProductsProductIdResponse loanProductModifyResponse = updateDueDaysForRepaymentEvent(getLoanProductsProductResponse.getId()); assertNotNull(loanProductModifyResponse); - } - private PutLoanProductsProductIdResponse updateLoanProduct(LoanTransactionHelper loanTransactionHelper, Long id) { - // event days configuration - Integer dueDaysForRepaymentEvent = 1; - Integer overDueDaysForRepaymentEvent = 2; + private PutLoanProductsProductIdResponse updateDueDaysForRepaymentEvent(Long id) { final PutLoanProductsProductIdRequest requestModifyLoan = new PutLoanProductsProductIdRequest() - .dueDaysForRepaymentEvent(dueDaysForRepaymentEvent).overDueDaysForRepaymentEvent(overDueDaysForRepaymentEvent).locale("en"); - return loanTransactionHelper.updateLoanProduct(id, requestModifyLoan); + .dueDaysForRepaymentEvent(DUE_DAYS_FOR_REPAYMENT_EVENT).overDueDaysForRepaymentEvent(OVER_DUE_DAYS_FOR_REPAYMENT_EVENT) + .locale("en"); + return updateLoanProduct(id, requestModifyLoan); } - private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper, - final Long delinquencyBucketId) { - final HashMap loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId); - final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); - return loanTransactionHelper.getLoanProduct(loanProductId); + private GetLoanProductsProductIdResponse createDefaultLoanProduct(final Long delinquencyBucketId) { + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder().buildRequest(null, delinquencyBucketId)); + return retrieveLoanProduct(loanProductId); } - private Integer createLoanProductWithDueDaysForRepaymentEvent(final LoanTransactionHelper loanTransactionHelper, - final Long delinquencyBucketId, Integer dueDaysForRepaymentEvent, Integer overDueDaysForRepaymentEvent) { - final HashMap loanProductMap = new LoanProductTestBuilder().withDueDaysForRepaymentEvent(dueDaysForRepaymentEvent) - .withOverDueDaysForRepaymentEvent(overDueDaysForRepaymentEvent).build(null, delinquencyBucketId); - final Integer loanProductId = loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap)); - return loanProductId; + private Long createLoanProductWithDueDaysForRepaymentEvent(final Long delinquencyBucketId, Integer dueDaysForRepaymentEvent, + Integer overDueDaysForRepaymentEvent) { + return createLoanProduct(new LoanProductTestBuilder().withDueDaysForRepaymentEvent(dueDaysForRepaymentEvent) + .withOverDueDaysForRepaymentEvent(overDueDaysForRepaymentEvent).buildRequest(null, delinquencyBucketId)); } } From ffc781e2de51e035d94fc1cb475121064a93838e Mon Sep 17 00:00:00 2001 From: DeathGun44 Date: Thu, 10 Sep 2026 23:38:36 +0530 Subject: [PATCH 4/6] FINERACT-2824: migrate the loan application tests to Feign LoanApplicationApprovalTest, LoanApplicationScheduleMonthlyTest, LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest and LoanValidationIntegrationTest. Applications use LoanRequestBuilders.legacyIndividualApplication, which reproduces the defaults LoanApplicationTestBuilder.build() emitted without any call site naming them: maxOutstandingLoanBalance, an empty collateral list, the default strategy and the en_GB locale. Error cases keep the status their response spec pinned and now also assert the globalisation code rather than only reading it out of an error map: approval above the demanded amount is 403, the multi-disburse sum check is 400. Repayment schedule due dates are compared as LocalDate rather than the [year, month, day] lists REST Assured produced. @SuppressWarnings("rawtypes") is gone from LoanApplicationApprovalTest: the raw HashMap tranche and collateral maps it covered are typed models now. --- .../LoanApplicationApprovalTest.java | 319 ++++++---------- ...ductWithPeriodicAccrualAccountingTest.java | 93 ++--- .../LoanApplicationScheduleMonthlyTest.java | 353 ++++++------------ .../LoanValidationIntegrationTest.java | 113 ++---- 4 files changed, 289 insertions(+), 589 deletions(-) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java index 190b241d2aa..a46f9490660 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationApprovalTest.java @@ -19,53 +19,32 @@ package org.apache.fineract.integrationtests; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.CollateralManagementHelper; -import org.apache.fineract.integrationtests.common.CommonConstants; -import org.apache.fineract.integrationtests.common.Utils; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; +import org.apache.fineract.client.feign.util.CallFailedRuntimeException; +import org.apache.fineract.client.models.GetLoansLoanIdResponse; +import org.apache.fineract.client.models.PostLoansDisbursementData; +import org.apache.fineract.client.models.PostLoansLoanIdDisbursementData; +import org.apache.fineract.client.models.PostLoansRequest; +import org.apache.fineract.client.models.PostLoansRequestCollateralData; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignCollateralHelper; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; +import org.apache.fineract.integrationtests.client.feign.modules.LoanTestData; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; -import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -@SuppressWarnings("rawtypes") -@ExtendWith(LoanTestLifecycleExtension.class) @Slf4j -public class LoanApplicationApprovalTest { - - private ResponseSpecification responseSpec; - private ResponseSpecification responseSpecForStatusCode403; - private ResponseSpecification responseSpecForStatusCode400; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; - - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.responseSpecForStatusCode403 = new ResponseSpecBuilder().expectStatusCode(403).build(); - this.responseSpecForStatusCode400 = new ResponseSpecBuilder().expectStatusCode(400).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - } +public class LoanApplicationApprovalTest extends FeignLoanTestBase { + + private final FeignCollateralHelper collateralHelper = new FeignCollateralHelper(FineractFeignClientHelper.getFineractFeignClient()); /* * Positive test case: Approved amount non zero is less than proposed amount @@ -74,21 +53,17 @@ public void setup() { public void loanApplicationApprovedAmountLessThanProposedAmount() { final String proposedAmount = "8000"; - final String approvalAmount = "5000"; + final Double approvalAmount = 5000.0; final String approveDate = "20 September 2012"; - final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012"); - final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder().build(null)); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount); + final Long clientId = createClient("01 January 2012"); + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder().buildRequest(null)); + final Long loanId = applyForLoanApplicationWithCollateral(clientId, loanProductId, proposedAmount); - HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); - LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + verifyLoanStatus(getLoanDetails(loanId), status -> status.getPendingApproval()); - final String expectedDisbursementDate = null; - List approveTranches = null; - loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount, - loanID, approveTranches); - LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + approveLoan(loanId, LoanRequestBuilders.approveLoan(approvalAmount, approveDate)); + verifyLoanStatus(getLoanDetails(loanId), status -> status.getWaitingForDisbursal()); } @@ -99,222 +74,174 @@ public void loanApplicationApprovedAmountLessThanProposedAmount() { public void loanApplicationApprovedAmountGreaterThanProposedAmount() { final String proposedAmount = "5000"; - final String approvalAmount = "9000"; + final Double approvalAmount = 9000.0; final String approveDate = "2 April 2012"; - final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012"); - final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder().build(null)); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, proposedAmount); + final Long clientId = createClient("01 January 2012"); + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder().buildRequest(null)); + final Long loanId = applyForLoanApplicationWithCollateral(clientId, loanProductId, proposedAmount); - HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); - LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + verifyLoanStatus(getLoanDetails(loanId), status -> status.getPendingApproval()); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode403); + CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, + () -> approveLoan(loanId, LoanRequestBuilders.approveLoan(approvalAmount, approveDate))); - @SuppressWarnings("unchecked") - List error = (List) this.loanTransactionHelper.approveLoan(approveDate, approvalAmount, loanID, - CommonConstants.RESPONSE_ERROR); - - assertEquals("error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded", - error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + assertEquals(403, exception.getStatus()); + assertErrorGlobalisationCode(exception, "error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded"); } - public HashMap createTrancheDetail(final String date, final String amount) { - HashMap detail = new HashMap<>(); - detail.put("expectedDisbursementDate", date); - detail.put("principal", amount); + public PostLoansDisbursementData createTrancheDetail(final String date, final double amount) { + return LoanRequestBuilders.applyTrancheDetail(date, amount); + } - return detail; + public PostLoansLoanIdDisbursementData approveTrancheDetail(final String date, final double amount) { + return LoanRequestBuilders.approveTrancheDetail(date, amount); } @Test public void loanApplicationApprovalAndValidationForMultiDisburseLoans() { - List createTranches = new ArrayList<>(); - createTranches.add(createTrancheDetail("01 March 2014", "1000")); - createTranches.add(createTrancheDetail("23 March 2014", "4000")); + List createTranches = List.of(// + createTrancheDetail("01 March 2014", 1000), // + createTrancheDetail("23 March 2014", 4000)); - final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014"); - log.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientID); + final Long clientId = createClient("01 January 2014"); + log.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientId); - final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(new LoanProductTestBuilder() // + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder() // .withInterestTypeAsDecliningBalance() // .withTranches(true) // .withInterestCalculationPeriodTypeAsRepaymentPeriod(true) // - .build(null)); + .buildRequest(null)); log.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}", - loanProductID); + loanProductId); - trancheLoansApprovedAmountLesserThanProposedAmount(clientID, loanProductID, createTranches); - trancheLoansApprovalValidation(clientID, loanProductID, createTranches); + trancheLoansApprovedAmountLesserThanProposedAmount(clientId, loanProductId, createTranches); + trancheLoansApprovalValidation(clientId, loanProductId, createTranches); } @Test public void loanApplicationShouldFailIfTransactionProcessingStrategyIsAdvancedPaymentAllocationButItIsNotConfiguredOnProduct() { - final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2014"); + final Long clientId = createClient("01 January 2014"); log.info("---------------------------------CLIENT CREATED WITH ID--------------------------------------------------- {}", clientId); - final Integer loanProductId = this.loanTransactionHelper - .getLoanProductId(new LoanProductTestBuilder().withInterestTypeAsDecliningBalance().withTranches(false) - .withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null)); + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder().withInterestTypeAsDecliningBalance().withTranches(false) + .withInterestCalculationPeriodTypeAsRepaymentPeriod(true).buildRequest(null)); log.info("----------------------------------LOAN PRODUCT CREATED WITH ID------------------------------------------- {}", loanProductId); - loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode403); - final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1") - .withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance() - .withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod() - .withExpectedDisbursementDate("01 March 2022").withSubmittedOnDate("01 March 2022").withLoanType("individual") - .withRepaymentStrategy(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY) - .build(clientId.toString(), loanProductId.toString(), null); - List error = (List) loanTransactionHelper.createLoanAccount(loanApplicationJSON, CommonConstants.RESPONSE_ERROR); - assertEquals("strategy.cannot.be.advanced.payment.allocation.if.not.configured", - error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, + () -> applyForLoan(LoanRequestBuilders.applyLoan(clientId, loanProductId, "01 March 2022", 1000.0, 1)// + .interestType(LoanTestData.InterestType.FLAT)// + .amortizationType(LoanTestData.AmortizationType.EQUAL_PRINCIPAL)// + .transactionProcessingStrategyCode( + AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY))); + + assertEquals(403, exception.getStatus()); + assertErrorGlobalisationCode(exception, "strategy.cannot.be.advanced.payment.allocation.if.not.configured"); } - private void trancheLoansApprovedAmountLesserThanProposedAmount(Integer clientID, Integer loanProductID, List createTranches) { + private void trancheLoansApprovedAmountLesserThanProposedAmount(Long clientId, Long loanProductId, + List createTranches) { final String proposedAmount = "5000"; - final String approvalAmount = "2000"; + final Double approvalAmount = 2000.0; final String approveDate = "01 March 2014"; final String expectedDisbursementDate = "01 March 2014"; - List approveTranches = new ArrayList<>(); - approveTranches.add(createTrancheDetail("01 March 2014", "1000")); - approveTranches.add(createTrancheDetail("23 March 2014", "1000")); + List approveTranches = List.of(// + approveTrancheDetail("01 March 2014", 1000), // + approveTrancheDetail("23 March 2014", 1000)); - final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches); - log.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}", loanID); + final Long loanId = applyForLoanApplicationWithTranches(clientId, loanProductId, proposedAmount, createTranches); + log.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}", loanId); - HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); - LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + verifyLoanStatus(getLoanDetails(loanId), status -> status.getPendingApproval()); log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------"); - loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(approveDate, expectedDisbursementDate, approvalAmount, - loanID, approveTranches); - LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); - LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + approveLoan(loanId, + LoanRequestBuilders.approveLoanWithTranches(approvalAmount, approveDate, expectedDisbursementDate, approveTranches)); + GetLoansLoanIdResponse loanDetails = getLoanDetails(loanId); + assertFalse(loanDetails.getStatus().getPendingApproval()); + verifyLoanStatus(loanDetails, status -> status.getWaitingForDisbursal()); log.info("-----------------------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY---------------------------------------"); } - private void trancheLoansApprovalValidation(Integer clientID, Integer loanProductID, List createTranches) { + private void trancheLoansApprovalValidation(Long clientId, Long loanProductId, List createTranches) { final String proposedAmount = "5000"; - final String approvalAmount1 = "10000"; - final String approvalAmount3 = "400"; - final String approvalAmount4 = "200"; + final Double approvalAmount1 = 10000.0; + final Double approvalAmount3 = 400.0; + final Double approvalAmount4 = 200.0; final String approveDate = "01 March 2014"; final String expectedDisbursementDate = "01 March 2014"; - List approveTranche1 = new ArrayList<>(); - approveTranche1.add(createTrancheDetail("01 March 2014", "5000")); - approveTranche1.add(createTrancheDetail("23 March 2014", "5000")); + List approveTranche1 = List.of(// + approveTrancheDetail("01 March 2014", 5000), // + approveTrancheDetail("23 March 2014", 5000)); - List approveTranche3 = new ArrayList<>(); - approveTranche3.add(createTrancheDetail("01 March 2014", "100")); - approveTranche3.add(createTrancheDetail("23 March 2014", "100")); - approveTranche3.add(createTrancheDetail("24 March 2014", "100")); - approveTranche3.add(createTrancheDetail("25 March 2014", "100")); + List approveTranche3 = List.of(// + approveTrancheDetail("01 March 2014", 100), // + approveTrancheDetail("23 March 2014", 100), // + approveTrancheDetail("24 March 2014", 100), // + approveTrancheDetail("25 March 2014", 100)); - List approveTranche4 = new ArrayList<>(); - approveTranche4.add(createTrancheDetail("01 March 2014", "100")); - approveTranche4.add(createTrancheDetail("23 March 2014", "100")); - approveTranche4.add(createTrancheDetail("24 March 2014", "100")); + List approveTranche4 = List.of(// + approveTrancheDetail("01 March 2014", 100), // + approveTrancheDetail("23 March 2014", 100), // + approveTrancheDetail("24 March 2014", 100)); - final Integer loanID = applyForLoanApplicationWithTranches(clientID, loanProductID, proposedAmount, createTranches); - log.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}", loanID); + final Long loanId = applyForLoanApplicationWithTranches(clientId, loanProductId, proposedAmount, createTranches); + log.info("-----------------------------------LOAN CREATED WITH LOANID------------------------------------------------- {}", loanId); - HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); - LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + verifyLoanStatus(getLoanDetails(loanId), status -> status.getPendingApproval()); log.info("-----------------------------------APPROVE LOAN-----------------------------------------------------------"); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode400); /* Sum of tranches is greater than approved amount */ - List> error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, - approvalAmount4, loanID, approveTranche4, CommonConstants.RESPONSE_ERROR); - assertEquals("validation.msg.loan.principal.sum.of.multi.disburse.amounts.must.be.equal.to.or.lesser.than.approved.principal", - error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); - - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpecForStatusCode403); + CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, () -> approveLoan(loanId, + LoanRequestBuilders.approveLoanWithTranches(approvalAmount4, approveDate, expectedDisbursementDate, approveTranche4))); + assertEquals(400, exception.getStatus()); + assertErrorGlobalisationCode(exception, + "validation.msg.loan.principal.sum.of.multi.disburse.amounts.must.be.equal.to.or.lesser.than.approved.principal"); /* Sum of tranches exceeds the proposed amount */ - error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, approvalAmount1, loanID, - approveTranche1, CommonConstants.RESPONSE_ERROR); - assertEquals("error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded", - error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + exception = assertThrows(CallFailedRuntimeException.class, () -> approveLoan(loanId, + LoanRequestBuilders.approveLoanWithTranches(approvalAmount1, approveDate, expectedDisbursementDate, approveTranche1))); + assertEquals(403, exception.getStatus()); + assertErrorGlobalisationCode(exception, "error.msg.loan.approval.amount.can't.be.greater.than.loan.amount.demanded"); /* No. of tranches exceeds the max tranche count at product level */ - error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, approvalAmount3, loanID, - approveTranche3, CommonConstants.RESPONSE_ERROR); - assertEquals("error.msg.disbursementData.exceeding.max.tranche.count", - error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); - - /* If tranches are not specified for a multi-disburse loan */ - /* - * error = this.loanTransactionHelper.approveLoanForTranches(approveDate, expectedDisbursementDate, - * approvalAmount5, loanID, approveTranche5, CommonConstants.RESPONSE_ERROR); - * assertEquals("error.msg.disbursementData.required", - * error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); - */ + exception = assertThrows(CallFailedRuntimeException.class, () -> approveLoan(loanId, + LoanRequestBuilders.approveLoanWithTranches(approvalAmount3, approveDate, expectedDisbursementDate, approveTranche3))); + assertEquals(403, exception.getStatus()); + assertErrorGlobalisationCode(exception, "error.msg.disbursementData.exceeding.max.tranche.count"); } - private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, final String proposedAmount) { - List collaterals = new ArrayList<>(); - final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); - Assertions.assertNotNull(collateralId); - final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, - clientID.toString(), collateralId); - Assertions.assertNotNull(clientCollateralId); - addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); - - final String loanApplication = new LoanApplicationTestBuilder().withPrincipal(proposedAmount).withLoanTermFrequency("5") - .withLoanTermFrequencyAsMonths().withNumberOfRepayments("5").withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate("20 September 2012") - .withCollaterals(collaterals).withSubmittedOnDate("02 April 2012") - .build(clientID.toString(), loanProductID.toString(), null); - return this.loanTransactionHelper.getLoanId(loanApplication); - } - - private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { - collaterals.add(collaterals(collateralId, quantity)); + private Long applyForLoanApplicationWithCollateral(final Long clientId, final Long loanProductId, final String proposedAmount) { + final PostLoansRequest application = LoanRequestBuilders + .legacyIndividualApplication(clientId, loanProductId, proposedAmount, 5, BigDecimal.valueOf(2), "20 September 2012")// + .submittedOnDate("02 April 2012")// + .collateral(collateralFor(clientId)); + return applyForLoan(application); } - private HashMap collaterals(Integer collateralId, BigDecimal quantity) { - HashMap collateral = new HashMap(2); - collateral.put("clientCollateralId", collateralId.toString()); - collateral.put("quantity", quantity.toString()); - return collateral; + public Long applyForLoanApplicationWithTranches(final Long clientId, final Long loanProductId, String principal, + List tranches) { + log.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); + final PostLoansRequest application = LoanRequestBuilders + .legacyIndividualApplication(clientId, loanProductId, principal, 5, BigDecimal.valueOf(2), "01 March 2014")// + .collateral(collateralFor(clientId))// + .disbursementData(tranches); + return applyForLoan(application); } - public Integer applyForLoanApplicationWithTranches(final Integer clientID, final Integer loanProductID, String principal, - List tranches) { - log.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); - List collaterals = new ArrayList<>(); - final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + private List collateralFor(final Long clientId) { + final Long collateralId = collateralHelper.createCollateralProduct().getResourceId(); Assertions.assertNotNull(collateralId); - final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, - clientID.toString(), collateralId); + final Long clientCollateralId = collateralHelper.createClientCollateral(clientId, collateralId).getResourceId(); Assertions.assertNotNull(clientCollateralId); - addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); - final String loanApplicationJSON = new LoanApplicationTestBuilder() - // - .withPrincipal(principal) - // - .withLoanTermFrequency("5") - // - .withLoanTermFrequencyAsMonths() - // - .withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths() // - .withInterestRatePerPeriod("2") // - .withExpectedDisbursementDate("01 March 2014") // - .withTranches(tranches) // - .withInterestTypeAsDecliningBalance() // - .withSubmittedOnDate("01 March 2014") // - .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); - - return this.loanTransactionHelper.getLoanId(loanApplicationJSON); + return List.of(new PostLoansRequestCollateralData().clientCollateralId(clientCollateralId).quantity(BigDecimal.ONE)); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest.java index e5958436830..88d4422d2fe 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest.java @@ -18,104 +18,67 @@ */ package org.apache.fineract.integrationtests; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; import java.util.UUID; import org.apache.fineract.client.models.GetLoansLoanIdResponse; -import org.apache.fineract.client.models.PostLoansLoanIdRequest; import org.apache.fineract.client.models.PostLoansLoanIdResponse; -import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; +import org.apache.fineract.integrationtests.client.feign.modules.LoanTestData; import org.apache.fineract.integrationtests.common.accounting.Account; -import org.apache.fineract.integrationtests.common.accounting.AccountHelper; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -@ExtendWith(LoanTestLifecycleExtension.class) -public class LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest { - - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private ClientHelper clientHelper; - private LoanTransactionHelper loanTransactionHelper; - private AccountHelper accountHelper; - - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec); - this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); - } + +public class LoanApplicationRejectionForLoanProductWithPeriodicAccrualAccountingTest extends FeignLoanTestBase { @Test public void loanApplicationRejectionForPeriodicAccrualAccountingLoanProductTest() { - Account assetAccount = this.accountHelper.createAssetAccount(); - Account incomeAccount = this.accountHelper.createIncomeAccount(); - Account expenseAccount = this.accountHelper.createExpenseAccount(); - Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + Account assetAccount = accountHelper.createAssetAccount(); + Account incomeAccount = accountHelper.createIncomeAccount(); + Account expenseAccount = accountHelper.createExpenseAccount(); + Account overpaymentAccount = accountHelper.createLiabilityAccount(); // Create Loan Product with Periodic Accrual accounting - final Integer loanProductID = createLoanProductWithPeriodicAccrualAccounting(assetAccount, incomeAccount, expenseAccount, + final Long loanProductId = createLoanProductWithPeriodicAccrualAccounting(assetAccount, incomeAccount, expenseAccount, overpaymentAccount); // Loan ExternalId String loanExternalIdStr = UUID.randomUUID().toString(); // Client and Loan account creation - final Integer clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue(); + final Long clientId = createClient(); - final Integer loanId = createLoanAccount(clientId, loanProductID, loanExternalIdStr); + final Long loanId = createLoanAccount(clientId, loanProductId, loanExternalIdStr); // verify Loan status as submitted and pending approval - GetLoansLoanIdResponse loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanId); + GetLoansLoanIdResponse loanDetails = getLoanDetails(loanId); assertTrue(loanDetails.getStatus().getPendingApproval()); // Reject Loan application - PostLoansLoanIdResponse result = this.loanTransactionHelper.rejectLoan(loanExternalIdStr, - new PostLoansLoanIdRequest().rejectedOnDate("3 September 2022").locale("en").dateFormat("dd MMMM yyyy")); + PostLoansLoanIdResponse result = loanHelper.rejectLoanByExternalId(loanExternalIdStr, + LoanRequestBuilders.rejectLoan("3 September 2022")); // Verify Loan application status is Rejected - assertTrue(result.getChanges().getStatus().getValue().equals("Rejected")); + assertEquals("Rejected", result.getChanges().getStatus().getValue()); } - private Integer createLoanProductWithPeriodicAccrualAccounting(final Account... accounts) { - - final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("1000").withRepaymentAfterEvery("1") - .withNumberOfRepayments("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0") - .withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat() - .withAccountingRulePeriodicAccrual(accounts).withDaysInMonth("30").withDaysInYear("365").withMoratorium("0", "0") - .build(null); - - return this.loanTransactionHelper.getLoanProductId(loanProductJSON); + private Long createLoanProductWithPeriodicAccrualAccounting(final Account... accounts) { + return createLoanProduct(new LoanProductTestBuilder().withPrincipal("1000").withRepaymentAfterEvery("1").withNumberOfRepayments("1") + .withRepaymentTypeAsMonth().withinterestRatePerPeriod("0").withInterestRateFrequencyTypeAsMonths() + .withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts) + .withDaysInMonth("30").withDaysInYear("365").withMoratorium("0", "0").buildRequest(null)); } - private Integer createLoanAccount(final Integer clientID, final Integer loanProductID, final String externalId) { - - String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1") - .withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance() - .withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod() - .withExpectedDisbursementDate("03 September 2022").withSubmittedOnDate("01 September 2022").withLoanType("individual") - .withExternalId(externalId).build(clientID.toString(), loanProductID.toString(), null); - - final Integer loanId = loanTransactionHelper.getLoanId(loanApplicationJSON); - return loanId; + private Long createLoanAccount(final Long clientId, final Long loanProductId, final String externalId) { + return applyForLoan(LoanRequestBuilders.applyLoan(clientId, loanProductId, "01 September 2022", 1000.0, 1)// + .expectedDisbursementDate("03 September 2022")// + .interestType(LoanTestData.InterestType.FLAT)// + .amortizationType(LoanTestData.AmortizationType.EQUAL_PRINCIPAL)// + .externalId(externalId)); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationScheduleMonthlyTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationScheduleMonthlyTest.java index fec4fb19c27..81eea608e11 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationScheduleMonthlyTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationScheduleMonthlyTest.java @@ -20,295 +20,154 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.Utils; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class LoanApplicationScheduleMonthlyTest { +public class LoanApplicationScheduleMonthlyTest extends FeignLoanTestBase { - private static final Logger LOG = LoggerFactory.getLogger(LoanApplicationScheduleMonthlyTest.class); public static final Integer TOTAL_REPAYMENTS = 14; public static final String NUMBER_OF_REPAYMENTS = String.valueOf(TOTAL_REPAYMENTS); public static final String DISBURSEMENT_DATE = "30 December 2022"; public static final String CLIENT_ACTIVATION_DATE = "13 October 2022"; - public static final String DUE_DATE = "dueDate"; - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - } - - @SuppressWarnings({ "unchecked" }) @Test public void validateSeedDate31() { - final Integer clientId = createClient(CLIENT_ACTIVATION_DATE); + final Long clientId = createClient(CLIENT_ACTIVATION_DATE); String firstRepaymentDate = "31 January 2023"; - Integer loanProductId = createLoanProductEntity(); - - Integer loanId = applyForLoanApplication(clientId, loanProductId, firstRepaymentDate); - - final ArrayList repaymentPeriods = (ArrayList) this.loanTransactionHelper - .getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanId); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 1, 31)), repaymentPeriods.get(1).get(DUE_DATE), - "Checking for Due Date for 1st Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 2, 28)), repaymentPeriods.get(2).get(DUE_DATE), - "Checking for Due Date for 2nd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 3, 31)), repaymentPeriods.get(3).get(DUE_DATE), - "Checking for Due Date for 3rd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 4, 30)), repaymentPeriods.get(4).get(DUE_DATE), - "Checking for Due Date for 4th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 5, 31)), repaymentPeriods.get(5).get(DUE_DATE), - "Checking for Due Date for 5th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 6, 30)), repaymentPeriods.get(6).get(DUE_DATE), - "Checking for Due Date for 6th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 7, 31)), repaymentPeriods.get(7).get(DUE_DATE), - "Checking for Due Date for 7th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 8, 31)), repaymentPeriods.get(8).get(DUE_DATE), - "Checking for Due Date for 8th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 9, 30)), repaymentPeriods.get(9).get(DUE_DATE), - "Checking for Due Date for 9th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 10, 31)), repaymentPeriods.get(10).get(DUE_DATE), - "Checking for Due Date for 10th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 11, 30)), repaymentPeriods.get(11).get(DUE_DATE), - "Checking for Due Date for 11th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 12, 31)), repaymentPeriods.get(12).get(DUE_DATE), - "Checking for Due Date for 12th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 1, 31)), repaymentPeriods.get(13).get(DUE_DATE), - "Checking for Due Date for 13th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 2, 29)), repaymentPeriods.get(14).get(DUE_DATE), - "Checking for Due Date for 14th Month"); + Long loanProductId = createLoanProductEntity(); + + Long loanId = applyForLoanApplicationWithFirstRepaymentDate(clientId, loanProductId, firstRepaymentDate); + + verifyDueDates(loanId, List.of(// + LocalDate.of(2023, 1, 31), // + LocalDate.of(2023, 2, 28), // + LocalDate.of(2023, 3, 31), // + LocalDate.of(2023, 4, 30), // + LocalDate.of(2023, 5, 31), // + LocalDate.of(2023, 6, 30), // + LocalDate.of(2023, 7, 31), // + LocalDate.of(2023, 8, 31), // + LocalDate.of(2023, 9, 30), // + LocalDate.of(2023, 10, 31), // + LocalDate.of(2023, 11, 30), // + LocalDate.of(2023, 12, 31), // + LocalDate.of(2024, 1, 31), // + LocalDate.of(2024, 2, 29))); } - private Integer createClient(String activationDate) { - final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, activationDate); - return clientId; - } - - @SuppressWarnings({ "unchecked" }) @Test public void validateSeedDate30() { - final Integer clientId = createClient(CLIENT_ACTIVATION_DATE); + final Long clientId = createClient(CLIENT_ACTIVATION_DATE); String firstRepaymentDate = "30 January 2023"; - Integer loanProductId = createLoanProductEntity(); - - Integer loanId = applyForLoanApplication(clientId, loanProductId, firstRepaymentDate); - - final ArrayList repaymentPeriods = (ArrayList) this.loanTransactionHelper - .getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanId); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 1, 30)), repaymentPeriods.get(1).get(DUE_DATE), - "Checking for Due Date for 1st Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 2, 28)), repaymentPeriods.get(2).get(DUE_DATE), - "Checking for Due Date for 2nd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 3, 30)), repaymentPeriods.get(3).get(DUE_DATE), - "Checking for Due Date for 3rd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 4, 30)), repaymentPeriods.get(4).get(DUE_DATE), - "Checking for Due Date for 4th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 5, 30)), repaymentPeriods.get(5).get(DUE_DATE), - "Checking for Due Date for 5th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 6, 30)), repaymentPeriods.get(6).get(DUE_DATE), - "Checking for Due Date for 6th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 7, 30)), repaymentPeriods.get(7).get(DUE_DATE), - "Checking for Due Date for 7th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 8, 30)), repaymentPeriods.get(8).get(DUE_DATE), - "Checking for Due Date for 8th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 9, 30)), repaymentPeriods.get(9).get(DUE_DATE), - "Checking for Due Date for 9th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 10, 30)), repaymentPeriods.get(10).get(DUE_DATE), - "Checking for Due Date for 10th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 11, 30)), repaymentPeriods.get(11).get(DUE_DATE), - "Checking for Due Date for 11th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 12, 30)), repaymentPeriods.get(12).get(DUE_DATE), - "Checking for Due Date for 12th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 1, 30)), repaymentPeriods.get(13).get(DUE_DATE), - "Checking for Due Date for 13th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 2, 29)), repaymentPeriods.get(14).get(DUE_DATE), - "Checking for Due Date for 14th Month"); + Long loanProductId = createLoanProductEntity(); + + Long loanId = applyForLoanApplicationWithFirstRepaymentDate(clientId, loanProductId, firstRepaymentDate); + + verifyDueDates(loanId, List.of(// + LocalDate.of(2023, 1, 30), // + LocalDate.of(2023, 2, 28), // + LocalDate.of(2023, 3, 30), // + LocalDate.of(2023, 4, 30), // + LocalDate.of(2023, 5, 30), // + LocalDate.of(2023, 6, 30), // + LocalDate.of(2023, 7, 30), // + LocalDate.of(2023, 8, 30), // + LocalDate.of(2023, 9, 30), // + LocalDate.of(2023, 10, 30), // + LocalDate.of(2023, 11, 30), // + LocalDate.of(2023, 12, 30), // + LocalDate.of(2024, 1, 30), // + LocalDate.of(2024, 2, 29))); } - @SuppressWarnings({ "unchecked" }) @Test public void validateSeedDate28() { - final Integer clientId = createClient(CLIENT_ACTIVATION_DATE); + final Long clientId = createClient(CLIENT_ACTIVATION_DATE); String firstRepaymentDate = "28 January 2023"; - Integer loanProductId = createLoanProductEntity(); - - Integer loanId = applyForLoanApplication(clientId, loanProductId, firstRepaymentDate); - - final ArrayList repaymentPeriods = (ArrayList) this.loanTransactionHelper - .getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanId); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 1, 28)), repaymentPeriods.get(1).get(DUE_DATE), - "Checking for Due Date for 1st Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 2, 28)), repaymentPeriods.get(2).get(DUE_DATE), - "Checking for Due Date for 2nd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 3, 28)), repaymentPeriods.get(3).get(DUE_DATE), - "Checking for Due Date for 3rd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 4, 28)), repaymentPeriods.get(4).get(DUE_DATE), - "Checking for Due Date for 4th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 5, 28)), repaymentPeriods.get(5).get(DUE_DATE), - "Checking for Due Date for 5th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 6, 28)), repaymentPeriods.get(6).get(DUE_DATE), - "Checking for Due Date for 6th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 7, 28)), repaymentPeriods.get(7).get(DUE_DATE), - "Checking for Due Date for 7th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 8, 28)), repaymentPeriods.get(8).get(DUE_DATE), - "Checking for Due Date for 8th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 9, 28)), repaymentPeriods.get(9).get(DUE_DATE), - "Checking for Due Date for 9th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 10, 28)), repaymentPeriods.get(10).get(DUE_DATE), - "Checking for Due Date for 10th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 11, 28)), repaymentPeriods.get(11).get(DUE_DATE), - "Checking for Due Date for 11th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 12, 28)), repaymentPeriods.get(12).get(DUE_DATE), - "Checking for Due Date for 12th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 1, 28)), repaymentPeriods.get(13).get(DUE_DATE), - "Checking for Due Date for 13th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 2, 28)), repaymentPeriods.get(14).get(DUE_DATE), - "Checking for Due Date for 14th Month"); + Long loanProductId = createLoanProductEntity(); + + Long loanId = applyForLoanApplicationWithFirstRepaymentDate(clientId, loanProductId, firstRepaymentDate); + + verifyDueDates(loanId, List.of(// + LocalDate.of(2023, 1, 28), // + LocalDate.of(2023, 2, 28), // + LocalDate.of(2023, 3, 28), // + LocalDate.of(2023, 4, 28), // + LocalDate.of(2023, 5, 28), // + LocalDate.of(2023, 6, 28), // + LocalDate.of(2023, 7, 28), // + LocalDate.of(2023, 8, 28), // + LocalDate.of(2023, 9, 28), // + LocalDate.of(2023, 10, 28), // + LocalDate.of(2023, 11, 28), // + LocalDate.of(2023, 12, 28), // + LocalDate.of(2024, 1, 28), // + LocalDate.of(2024, 2, 28))); } - @SuppressWarnings({ "unchecked" }) @Test public void validateSeedDate25() { - final Integer clientId = createClient(CLIENT_ACTIVATION_DATE); + final Long clientId = createClient(CLIENT_ACTIVATION_DATE); String firstRepaymentDate = "25 January 2023"; - Integer loanProductId = createLoanProductEntity(); - - Integer loanId = applyForLoanApplication(clientId, loanProductId, firstRepaymentDate); - - final ArrayList repaymentPeriods = (ArrayList) this.loanTransactionHelper - .getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanId); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 1, 25)), repaymentPeriods.get(1).get(DUE_DATE), - "Checking for Due Date for 1st Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 2, 25)), repaymentPeriods.get(2).get(DUE_DATE), - "Checking for Due Date for 2nd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 3, 25)), repaymentPeriods.get(3).get(DUE_DATE), - "Checking for Due Date for 3rd Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 4, 25)), repaymentPeriods.get(4).get(DUE_DATE), - "Checking for Due Date for 4th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 5, 25)), repaymentPeriods.get(5).get(DUE_DATE), - "Checking for Due Date for 5th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 6, 25)), repaymentPeriods.get(6).get(DUE_DATE), - "Checking for Due Date for 6th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 7, 25)), repaymentPeriods.get(7).get(DUE_DATE), - "Checking for Due Date for 7th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 8, 25)), repaymentPeriods.get(8).get(DUE_DATE), - "Checking for Due Date for 8th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 9, 25)), repaymentPeriods.get(9).get(DUE_DATE), - "Checking for Due Date for 9th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 10, 25)), repaymentPeriods.get(10).get(DUE_DATE), - "Checking for Due Date for 10th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 11, 25)), repaymentPeriods.get(11).get(DUE_DATE), - "Checking for Due Date for 11th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2023, 12, 25)), repaymentPeriods.get(12).get(DUE_DATE), - "Checking for Due Date for 12th Month"); - - assertEquals(new ArrayList<>(Arrays.asList(2024, 1, 25)), repaymentPeriods.get(13).get(DUE_DATE), - "Checking for Due Date for 13th Month"); + Long loanProductId = createLoanProductEntity(); + + Long loanId = applyForLoanApplicationWithFirstRepaymentDate(clientId, loanProductId, firstRepaymentDate); + + verifyDueDates(loanId, List.of(// + LocalDate.of(2023, 1, 25), // + LocalDate.of(2023, 2, 25), // + LocalDate.of(2023, 3, 25), // + LocalDate.of(2023, 4, 25), // + LocalDate.of(2023, 5, 25), // + LocalDate.of(2023, 6, 25), // + LocalDate.of(2023, 7, 25), // + LocalDate.of(2023, 8, 25), // + LocalDate.of(2023, 9, 25), // + LocalDate.of(2023, 10, 25), // + LocalDate.of(2023, 11, 25), // + LocalDate.of(2023, 12, 25), // + LocalDate.of(2024, 1, 25), // + LocalDate.of(2024, 2, 25))); + } - assertEquals(new ArrayList<>(Arrays.asList(2024, 2, 25)), repaymentPeriods.get(14).get(DUE_DATE), - "Checking for Due Date for 14th Month"); + /** + * Asserts the due date of every repayment period. Period 0 is the disbursement row, so the expected dates line up + * with periods 1..n. + */ + private void verifyDueDates(final Long loanId, final List expectedDueDates) { + final List repaymentPeriods = getLoanDetails(loanId).getRepaymentSchedule().getPeriods(); + assertEquals(expectedDueDates.size() + 1, repaymentPeriods.size(), "Checking the number of repayment periods"); + for (int month = 1; month <= expectedDueDates.size(); month++) { + assertEquals(expectedDueDates.get(month - 1), repaymentPeriods.get(month).getDueDate(), + "Checking for Due Date for " + month + " Month"); + } } /** * create a new loan product **/ - private Integer createLoanProductEntity() { - final String loanProductJSON = new LoanProductTestBuilder().withPrincipal("10000").withRepaymentAfterEvery("1") + private Long createLoanProductEntity() { + return createLoanProduct(new LoanProductTestBuilder().withPrincipal("10000").withRepaymentAfterEvery("1") .withNumberOfRepayments(NUMBER_OF_REPAYMENTS).withRepaymentTypeAsMonth().withInterestRateFrequencyTypeAsMonths() - .build(null); - - Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON); - return loanProductId; + .buildRequest(null)); } /** * Apply for a Loan */ - private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String firstRepaymentDate) { - final String loanApplication = new LoanApplicationTestBuilder().withPrincipal("10000").withLoanTermFrequency(NUMBER_OF_REPAYMENTS) - .withLoanTermFrequencyAsMonths().withNumberOfRepayments(NUMBER_OF_REPAYMENTS).withRepaymentEveryAfter("1") - .withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("2").withExpectedDisbursementDate(DISBURSEMENT_DATE) - .withSubmittedOnDate(DISBURSEMENT_DATE).withFirstRepaymentDate(firstRepaymentDate) - .build(clientID.toString(), loanProductID.toString(), null); - return this.loanTransactionHelper.getLoanId(loanApplication); + private Long applyForLoanApplicationWithFirstRepaymentDate(final Long clientId, final Long loanProductId, String firstRepaymentDate) { + return applyForLoan(LoanRequestBuilders + .legacyIndividualApplication(clientId, loanProductId, "10000", TOTAL_REPAYMENTS, BigDecimal.valueOf(2), DISBURSEMENT_DATE) + .repaymentsStartingFromDate(firstRepaymentDate)); } } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java index dbad3e796ae..ff3b08e58c3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanValidationIntegrationTest.java @@ -18,71 +18,48 @@ */ package org.apache.fineract.integrationtests; -import com.jayway.jsonpath.DocumentContext; -import com.jayway.jsonpath.JsonPath; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; -import java.util.Collections; -import net.minidev.json.JSONArray; -import org.apache.fineract.integrationtests.common.ClientHelper; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.math.BigDecimal; +import org.apache.fineract.client.feign.util.CallFailedRuntimeException; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignStaffHelper; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignUserHelper; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; +import org.apache.fineract.integrationtests.client.feign.modules.LoanTestData; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; -import org.apache.fineract.integrationtests.common.accounting.AccountHelper; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.apache.fineract.integrationtests.common.organisation.StaffHelper; -import org.apache.fineract.integrationtests.useradministration.users.UserHelper; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@ExtendWith(LoanTestLifecycleExtension.class) -public class LoanValidationIntegrationTest { +public class LoanValidationIntegrationTest extends FeignLoanTestBase { private static final Logger LOG = LoggerFactory.getLogger(LoanValidationIntegrationTest.class); - - private RequestSpecification requestSpec; - private ResponseSpecification responseSpec; - private LoanTransactionHelper loanTransactionHelper; - private AccountHelper accountHelper; - - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); - } + private static final String NEW_USER_PASSWORD = "A1b2c3d4e5f$"; @Test public void checkPrincipalErrors() { - final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); + final Long staffId = new FeignStaffHelper(FineractFeignClientHelper.getFineractFeignClient()).createStaff().getResourceId(); String username = Utils.uniqueRandomStringGenerator("user", 8); - UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", "resourceId"); + FeignUserHelper.createUser(1L, staffId, username, NEW_USER_PASSWORD); LOG.info("-------------------------Creating Client---------------------------"); - final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); - ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID); + final Long clientId = createClient(); + Assertions.assertNotNull(clientHelper.getClient(clientId)); LOG.info("-------------------------Creating Loan---------------------------"); - final Account assetAccount = this.accountHelper.createAssetAccount(); - final Account incomeAccount = this.accountHelper.createIncomeAccount(); - final Account expenseAccount = this.accountHelper.createExpenseAccount(); - final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + final Account assetAccount = accountHelper.createAssetAccount(); + final Account incomeAccount = accountHelper.createIncomeAccount(); + final Account expenseAccount = accountHelper.createExpenseAccount(); + final Account overpaymentAccount = accountHelper.createLiabilityAccount(); LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); - final String loanProductJSON = new LoanProductTestBuilder() // + final Long loanProductId = createLoanProduct(new LoanProductTestBuilder() // .withPrincipal("10000000.00") // .withNumberOfRepayments("24") // .withRepaymentAfterEvery("1") // @@ -93,43 +70,17 @@ public void checkPrincipalErrors() { .withAmortizationTypeAsEqualPrincipalPayment() // .withInterestTypeAsDecliningBalance() // .currencyDetails("0", "0") - .withAccounting("2", new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount }).build(null); - final Integer loanProductID = this.loanTransactionHelper.getLoanProductId(loanProductJSON); + .withAccounting("2", new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount }).buildRequest(null)); LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); - final String loanApplicationJSON = new LoanApplicationTestBuilder() // - .withPrincipal("-1") // - .withLoanTermFrequency("6") // - .withLoanTermFrequencyAsMonths() // - .withNumberOfRepayments("6") // - .withRepaymentEveryAfter("1") // - .withRepaymentFrequencyTypeAsMonths() // - .withInterestRatePerPeriod("2") // - .withAmortizationTypeAsEqualInstallments() // - .withInterestTypeAsFlatBalance() // - .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // - .withExpectedDisbursementDate("12 July 2022") // - .withSubmittedOnDate("10 July 2022") // - .withRepaymentStrategy(LoanApplicationTestBuilder.DEFAULT_STRATEGY) // - .withCharges(Collections.emptyList()) // - .build(clientID.toString(), loanProductID.toString(), null); - - ResponseSpecification failedResponseSpec = new ResponseSpecBuilder().expectStatusCode(400).expectBody(new BaseMatcher() { - - @Override - public boolean matches(Object body) { - DocumentContext json = JsonPath.parse(body.toString()); - LOG.error(body.toString()); - JSONArray errors = json.read("$.errors[*].developerMessage"); - LOG.info("errors: {}", errors); - return errors.size() == 1; - } - - @Override - public void describeTo(Description description) { + // a negative principal is rejected, and the rejection names exactly one offending field + CallFailedRuntimeException exception = assertThrows(CallFailedRuntimeException.class, + () -> applyForLoan(LoanRequestBuilders + .legacyIndividualApplication(clientId, loanProductId, "-1", 6, BigDecimal.valueOf(2), "12 July 2022")// + .interestType(LoanTestData.InterestType.FLAT)// + .submittedOnDate("10 July 2022"))); - } - }).build(); - final Integer loanID = this.loanTransactionHelper.getLoanId(loanApplicationJSON, requestSpec, failedResponseSpec); + assertEquals(400, exception.getStatus()); + assertEquals(1, extractErrorCount(exception)); } } From 4b2a25c5988780659c648f2cf3f37be86fb52810 Mon Sep 17 00:00:00 2001 From: DeathGun44 Date: Thu, 10 Sep 2026 23:38:36 +0530 Subject: [PATCH 5/6] FINERACT-2824: migrate the loan auditing and concurrency tests to Feign LoanAuditingIntegrationTest reads the audit fields through the generated DefaultApi.getLoanAuditFields, matching its transaction-level sibling LoanTransactionAuditingIntegrationTest, and approves as the newly created user through a second Feign client rather than a re-headered request spec. ConcurrencyIntegrationTest drives its ten concurrent repayments through FeignTransactionHelper, and reads the net disbursal amount from the typed loan details instead of a JsonPath expression over the response body. --- .../ConcurrencyIntegrationTest.java | 116 ++++---------- .../LoanAuditingIntegrationTest.java | 150 +++++++++--------- 2 files changed, 107 insertions(+), 159 deletions(-) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java index 0b1cd78c3c0..94f7bf802ed 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ConcurrencyIntegrationTest.java @@ -18,79 +18,57 @@ */ package org.apache.fineract.integrationtests; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.path.json.JsonPath; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; import java.math.BigDecimal; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Calendar; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import org.apache.fineract.integrationtests.common.ClientHelper; -import org.apache.fineract.integrationtests.common.CollateralManagementHelper; -import org.apache.fineract.integrationtests.common.Utils; +import org.apache.fineract.client.models.PostLoansRequest; +import org.apache.fineract.client.models.PostLoansRequestCollateralData; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignCollateralHelper; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignTransactionHelper; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; import org.apache.fineract.integrationtests.common.accounting.Account; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@ExtendWith(LoanTestLifecycleExtension.class) -public class ConcurrencyIntegrationTest { +public class ConcurrencyIntegrationTest extends FeignLoanTestBase { private static final Logger LOG = LoggerFactory.getLogger(ConcurrencyIntegrationTest.class); - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; private static final String NO_ACCOUNTING = "1"; static final int MYTHREADS = 30; - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - } + private final FeignCollateralHelper collateralHelper = new FeignCollateralHelper(FineractFeignClientHelper.getFineractFeignClient()); @Test public void verifyConcurrentLoanRepayments() { - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - - final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); - ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID); - final Integer loanProductID = createLoanProduct(false, NO_ACCOUNTING); - final Integer loanID = applyForLoanApplication(clientID, loanProductID, "12,000.00"); - this.loanTransactionHelper.approveLoan("20 September 2011", loanID); - String loanDetails = this.loanTransactionHelper.getLoanDetails(this.requestSpec, this.responseSpec, loanID); - this.loanTransactionHelper.disburseLoanWithNetDisbursalAmount("20 September 2011", loanID, "12,000.00", - JsonPath.from(loanDetails).get("netDisbursalAmount").toString()); + final Long clientId = createClient(); + Assertions.assertNotNull(clientHelper.getClient(clientId)); + final Long loanProductId = createLoanProduct(false, NO_ACCOUNTING); + final Long loanId = applyForLoanApplicationWithCollateral(clientId, loanProductId, "12,000.00"); + // the loanHelper.approveLoan(date, loanId) shorthand pins the approved amount at 1000; this loan is for 12000 + approveLoan(loanId, LoanRequestBuilders.approveLoan(12000.0, "20 September 2011")); + BigDecimal netDisbursalAmount = getLoanDetails(loanId).getNetDisbursalAmount(); + disburseLoan(loanId, LoanRequestBuilders.disburseLoan(12000.0, "20 September 2011").netDisbursalAmount(netDisbursalAmount)); ExecutorService executor = Executors.newFixedThreadPool(MYTHREADS); Calendar date = Calendar.getInstance(); date.set(2011, 9, 20); - Float repaymentAmount = 100.0f; + Double repaymentAmount = 100.0; for (int i = 0; i < 10; i++) { LOG.info("Starting concurrent transaction number {}", i); date.add(Calendar.DAY_OF_MONTH, 1); repaymentAmount = repaymentAmount + 100; - Runnable worker = new LoanRepaymentExecutor(loanTransactionHelper, loanID, repaymentAmount, date); + Runnable worker = new LoanRepaymentExecutor(transactionHelper, loanId, repaymentAmount, date); executor.execute(worker); } @@ -103,7 +81,7 @@ public void verifyConcurrentLoanRepayments() { } - private Integer createLoanProduct(final boolean multiDisburseLoan, final String accountingRule, final Account... accounts) { + private Long createLoanProduct(final boolean multiDisburseLoan, final String accountingRule, final Account... accounts) { LOG.info("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); LoanProductTestBuilder builder = new LoanProductTestBuilder() // .withPrincipal("12,000.00") // @@ -120,67 +98,41 @@ private Integer createLoanProduct(final boolean multiDisburseLoan, final String if (multiDisburseLoan) { builder = builder.withInterestCalculationPeriodTypeAsRepaymentPeriod(true); } - final String loanProductJSON = builder.build(null); - return this.loanTransactionHelper.getLoanProductId(loanProductJSON); + return createLoanProduct(builder.buildRequest(null)); } - private Integer applyForLoanApplication(final Integer clientID, final Integer loanProductID, String principal) { + private Long applyForLoanApplicationWithCollateral(final Long clientId, final Long loanProductId, String principal) { LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------"); - List collaterals = new ArrayList<>(); - final Integer collateralId = CollateralManagementHelper.createCollateralProduct(this.requestSpec, this.responseSpec); + final Long collateralId = collateralHelper.createCollateralProduct().getResourceId(); Assertions.assertNotNull(collateralId); - final Integer clientCollateralId = CollateralManagementHelper.createClientCollateral(this.requestSpec, this.responseSpec, - clientID.toString(), collateralId); + final Long clientCollateralId = collateralHelper.createClientCollateral(clientId, collateralId).getResourceId(); Assertions.assertNotNull(clientCollateralId); - addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1)); - final String loanApplicationJSON = new LoanApplicationTestBuilder() // - .withPrincipal(principal) // - .withLoanTermFrequency("4") // - .withLoanTermFrequencyAsMonths() // - .withNumberOfRepayments("4") // - .withRepaymentEveryAfter("1") // - .withRepaymentFrequencyTypeAsMonths() // - .withInterestRatePerPeriod("2") // - .withAmortizationTypeAsEqualInstallments() // - .withInterestTypeAsDecliningBalance() // - .withInterestCalculationPeriodTypeSameAsRepaymentPeriod() // - .withExpectedDisbursementDate("20 September 2011") // - .withSubmittedOnDate("20 September 2011") // - .withCollaterals(collaterals).build(clientID.toString(), loanProductID.toString(), null); - return this.loanTransactionHelper.getLoanId(loanApplicationJSON); - } - - private void addCollaterals(List collaterals, Integer collateralId, BigDecimal quantity) { - collaterals.add(collaterals(collateralId, quantity)); - } - - private HashMap collaterals(Integer collateralId, BigDecimal quantity) { - HashMap collateral = new HashMap(2); - collateral.put("clientCollateralId", collateralId.toString()); - collateral.put("quantity", quantity.toString()); - return collateral; + final PostLoansRequest application = LoanRequestBuilders + .legacyIndividualApplication(clientId, loanProductId, principal, 4, BigDecimal.valueOf(2), "20 September 2011")// + .collateral(List.of(new PostLoansRequestCollateralData().clientCollateralId(clientCollateralId).quantity(BigDecimal.ONE))); + return applyForLoan(application); } public static class LoanRepaymentExecutor implements Runnable { - private final Integer loanId; - private final Float repaymentAmount; + private final Long loanId; + private final Double repaymentAmount; private final String repaymentDate; - private final LoanTransactionHelper loanTransactionHelper; + private final FeignTransactionHelper transactionHelper; DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); - LoanRepaymentExecutor(LoanTransactionHelper loanTransactionHelper, Integer loanId, Float repaymentAmount, Calendar repaymentDate) { + LoanRepaymentExecutor(FeignTransactionHelper transactionHelper, Long loanId, Double repaymentAmount, Calendar repaymentDate) { this.loanId = loanId; this.repaymentAmount = repaymentAmount; this.repaymentDate = dateFormat.format(repaymentDate.getTime()); - this.loanTransactionHelper = loanTransactionHelper; + this.transactionHelper = transactionHelper; } @Override public void run() { try { - this.loanTransactionHelper.makeRepayment(repaymentDate, repaymentAmount, loanId); + this.transactionHelper.makeLoanRepayment(loanId, LoanRequestBuilders.repayLoan(repaymentAmount, repaymentDate)); } catch (Exception e) { LOG.info("Found an exception {}", e.getMessage()); LOG.info("Details of failed concurrent transaction (date, amount, loanId) are {},{},{}", repaymentDate, repaymentAmount, diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java index e5ef1220b4f..4120cee4638 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAuditingIntegrationTest.java @@ -18,126 +18,122 @@ */ package org.apache.fineract.integrationtests; -import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_BY; -import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.CREATED_DATE; -import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_BY; -import static org.apache.fineract.infrastructure.core.domain.AuditableFieldsConstants.LAST_MODIFIED_DATE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import org.apache.fineract.client.feign.FineractFeignClient; +import org.apache.fineract.client.models.LoanAuditFieldsData; +import org.apache.fineract.client.models.PostLoansRequest; import org.apache.fineract.infrastructure.core.service.DateUtils; -import org.apache.fineract.integrationtests.common.ClientHelper; +import org.apache.fineract.integrationtests.client.feign.FeignLoanTestBase; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignLoanHelper; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignStaffHelper; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignUserHelper; +import org.apache.fineract.integrationtests.client.feign.modules.LoanRequestBuilders; +import org.apache.fineract.integrationtests.client.feign.modules.LoanTestData; +import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; -import org.apache.fineract.integrationtests.common.accounting.AccountHelper; -import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder; import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder; -import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker; -import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; -import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper; -import org.apache.fineract.integrationtests.common.organisation.StaffHelper; -import org.apache.fineract.integrationtests.useradministration.users.UserHelper; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@ExtendWith(LoanTestLifecycleExtension.class) -public class LoanAuditingIntegrationTest { +public class LoanAuditingIntegrationTest extends FeignLoanTestBase { private static final Logger LOG = LoggerFactory.getLogger(LoanAuditingIntegrationTest.class); - private ResponseSpecification responseSpec; - private RequestSpecification requestSpec; - private LoanTransactionHelper loanTransactionHelper; - private AccountHelper accountHelper; - - @BeforeEach - public void setup() { - Utils.initializeRESTAssured(); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - - this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); - this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); - } + private static final String NEW_USER_PASSWORD = "A1b2c3d4e5f$"; @Test public void checkAuditDates() throws InterruptedException { - final Integer staffId = StaffHelper.createStaff(this.requestSpec, this.responseSpec); + final Long staffId = new FeignStaffHelper(FineractFeignClientHelper.getFineractFeignClient()).createStaff().getResourceId(); String username = Utils.uniqueRandomStringGenerator("user", 8); - final Integer userId = (Integer) UserHelper.createUser(this.requestSpec, this.responseSpec, 1, staffId, username, "A1b2c3d4e5f$", - "resourceId"); + final Long userId = FeignUserHelper.createUser(1L, staffId, username, NEW_USER_PASSWORD).getResourceId(); LOG.info("-------------------------Creating Client---------------------------"); - final Integer clientID = ClientHelper.createClient(requestSpec, responseSpec); - ClientHelper.verifyClientCreatedOnServer(requestSpec, responseSpec, clientID); - LOG.info("-------------------------Creating Loan---------------------------"); - final Account assetAccount = this.accountHelper.createAssetAccount(); - final Account incomeAccount = this.accountHelper.createIncomeAccount(); - final Account expenseAccount = this.accountHelper.createExpenseAccount(); - final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + final Long clientId = createClient(); + Assertions.assertNotNull(clientHelper.getClient(clientId)); - final Integer loanProductID = this.loanTransactionHelper.createLoanProduct("0", "0", LoanProductTestBuilder.DEFAULT_STRATEGY, "2", - assetAccount, incomeAccount, expenseAccount, overpaymentAccount); + LOG.info("-------------------------Creating Loan---------------------------"); + final Long loanProductId = createLoanProduct("0", "0", LoanProductTestBuilder.DEFAULT_STRATEGY, "2"); OffsetDateTime now = Utils.getAuditDateTimeToCompare(); - final Integer loanID = this.loanTransactionHelper.applyForLoanApplicationWithPaymentStrategyAndPastMonth(clientID, loanProductID, - Collections.emptyList(), null, "10000", LoanApplicationTestBuilder.DEFAULT_STRATEGY, "10 July 2022", "11 July 2022"); - Assertions.assertNotNull(loanID); - HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); - LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + final Long loanId = applyForLoanApplication(clientId, loanProductId, 10000.0, "10 July 2022", "11 July 2022"); + Assertions.assertNotNull(loanId); + verifyLoanStatus(loanId, LoanStatus.SUBMITTED_AND_PENDING_APPROVAL); - Map auditFieldsResponse = LoanTransactionHelper.getLoanAuditFields(requestSpec, responseSpec, loanID, ""); + LoanAuditFieldsData auditFieldsResponse = getAuditFields(loanId); - OffsetDateTime createdDate = OffsetDateTime.parse((String) auditFieldsResponse.get(CREATED_DATE), - DateTimeFormatter.ISO_OFFSET_DATE_TIME); - OffsetDateTime lastModifiedDate = OffsetDateTime.parse((String) auditFieldsResponse.get(LAST_MODIFIED_DATE), - DateTimeFormatter.ISO_OFFSET_DATE_TIME); + OffsetDateTime createdDate = auditFieldsResponse.getCreatedDate(); + OffsetDateTime lastModifiedDate = auditFieldsResponse.getLastModifiedDate(); LOG.info("-------------------------Check Audit dates---------------------------"); - assertEquals(1, auditFieldsResponse.get(CREATED_BY)); - assertEquals(1, auditFieldsResponse.get(LAST_MODIFIED_BY)); + assertEquals(1L, auditFieldsResponse.getCreatedBy()); + assertEquals(1L, auditFieldsResponse.getLastModifiedBy()); assertTrue(DateUtils.isEqual(now, createdDate, ChronoUnit.MINUTES)); assertTrue(DateUtils.isEqual(now, lastModifiedDate, ChronoUnit.MINUTES)); LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------"); - this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - this.requestSpec.header("Authorization", - "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey(username, "A1b2c3d4e5f$")); - this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); + // approve as the newly created user, so the audit fields record a different last modifier + FineractFeignClient asNewUser = FineractFeignClientHelper.createNewFineractFeignClient(username, NEW_USER_PASSWORD); + FeignLoanHelper newUserLoanHelper = new FeignLoanHelper(asNewUser); OffsetDateTime now2 = Utils.getAuditDateTimeToCompare(); - loanStatusHashMap = this.loanTransactionHelper.approveLoan("11 July 2022", loanID); - LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); - auditFieldsResponse = LoanTransactionHelper.getLoanAuditFields(requestSpec, responseSpec, loanID, ""); + newUserLoanHelper.approveLoan(loanId, LoanRequestBuilders.approveLoan(10000.0, "11 July 2022")); + verifyLoanStatus(loanId, LoanStatus.APPROVED); + auditFieldsResponse = getAuditFields(loanId); - OffsetDateTime createdDate2 = OffsetDateTime.parse((String) auditFieldsResponse.get(CREATED_DATE), - DateTimeFormatter.ISO_OFFSET_DATE_TIME); - lastModifiedDate = OffsetDateTime.parse((String) auditFieldsResponse.get(LAST_MODIFIED_DATE), - DateTimeFormatter.ISO_OFFSET_DATE_TIME); + OffsetDateTime createdDate2 = auditFieldsResponse.getCreatedDate(); + lastModifiedDate = auditFieldsResponse.getLastModifiedDate(); LOG.info("-------------------------Check Audit dates---------------------------"); - assertEquals(1, auditFieldsResponse.get(CREATED_BY)); + assertEquals(1L, auditFieldsResponse.getCreatedBy()); assertTrue(DateUtils.isEqual(now, createdDate2, ChronoUnit.MINUTES)); assertTrue(DateUtils.isEqual(createdDate, createdDate2)); - assertEquals(userId, auditFieldsResponse.get(LAST_MODIFIED_BY)); + assertEquals(userId, auditFieldsResponse.getLastModifiedBy()); assertTrue(DateUtils.isEqual(now2, lastModifiedDate, ChronoUnit.MINUTES)); } + + private LoanAuditFieldsData getAuditFields(Long loanId) { + return ok(() -> fineractClient().defaultApi().getLoanAuditFields(loanId)); + } + + private Long applyForLoanApplication(final Long clientId, final Long loanProductId, Double principal, final String submittedOnDate, + final String disbursementDate) { + final PostLoansRequest application = LoanRequestBuilders.applyLoan(clientId, loanProductId, submittedOnDate, principal, 6)// + .expectedDisbursementDate(disbursementDate)// + .interestRatePerPeriod(BigDecimal.valueOf(2))// + .interestType(LoanTestData.InterestType.FLAT); + return applyForLoan(application); + } + + private Long createLoanProduct(final String inMultiplesOf, final String digitsAfterDecimal, final String repaymentStrategy, + final String accountingRule) { + final Account assetAccount = accountHelper.createAssetAccount(); + final Account incomeAccount = accountHelper.createIncomeAccount(); + final Account expenseAccount = accountHelper.createExpenseAccount(); + final Account overpaymentAccount = accountHelper.createLiabilityAccount(); + + return createLoanProduct(new LoanProductTestBuilder() // + .withPrincipal("10000000.00") // + .withNumberOfRepayments("24") // + .withRepaymentAfterEvery("1") // + .withRepaymentTypeAsMonth() // + .withinterestRatePerPeriod("2") // + .withInterestRateFrequencyTypeAsMonths() // + .withRepaymentStrategy(repaymentStrategy) // + .withAmortizationTypeAsEqualPrincipalPayment() // + .withInterestTypeAsDecliningBalance() // + .currencyDetails(digitsAfterDecimal, inMultiplesOf) + .withAccounting(accountingRule, new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount }) + .buildRequest(null)); + } } From 2f65d1dd3dc42e53a8e62b0363dc92ec5ff28a44 Mon Sep 17 00:00:00 2001 From: DeathGun44 Date: Thu, 10 Sep 2026 23:38:36 +0530 Subject: [PATCH 6/6] FINERACT-2824: remove REST Assured from the working capital loan originator test Only testUserWithoutPermissionsCannotAttachOrDetachOriginator still built a request spec, to create a role and a user through RolesHelper and UserHelper. Both now go through FeignRoleHelper and FeignUserHelper, and the last io.restassured import in the file is gone. --- .../WorkingCapitalLoanOriginatorsTest.java | 34 +++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/WorkingCapitalLoanOriginatorsTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/WorkingCapitalLoanOriginatorsTest.java index 6b555fcebee..243033b56b9 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/WorkingCapitalLoanOriginatorsTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/WorkingCapitalLoanOriginatorsTest.java @@ -23,15 +23,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import io.restassured.builder.RequestSpecBuilder; -import io.restassured.builder.ResponseSpecBuilder; -import io.restassured.http.ContentType; -import io.restassured.specification.RequestSpecification; -import io.restassured.specification.ResponseSpecification; import java.math.BigDecimal; -import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -45,6 +40,8 @@ import org.apache.fineract.client.models.PostUsersRequest; import org.apache.fineract.client.models.PostUsersResponse; import org.apache.fineract.client.models.PostWorkingCapitalLoansOriginatorData; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignRoleHelper; +import org.apache.fineract.integrationtests.client.feign.helpers.FeignUserHelper; import org.apache.fineract.integrationtests.client.feign.helpers.WorkingCapitalLoanOriginatorHelper; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.FineractFeignClientHelper; @@ -54,8 +51,6 @@ import org.apache.fineract.integrationtests.common.workingcapitalloan.WorkingCapitalLoanHelper; import org.apache.fineract.integrationtests.common.workingcapitalloanproduct.WorkingCapitalLoanProductHelper; import org.apache.fineract.integrationtests.common.workingcapitalloanproduct.WorkingCapitalLoanProductTestBuilder; -import org.apache.fineract.integrationtests.useradministration.roles.RolesHelper; -import org.apache.fineract.integrationtests.useradministration.users.UserHelper; import org.junit.jupiter.api.Test; public class WorkingCapitalLoanOriginatorsTest { @@ -251,25 +246,18 @@ public void testDetachOriginatorFromWorkingCapitalLoan() { @Test public void testUserWithoutPermissionsCannotAttachOrDetachOriginator() { - Utils.initializeRESTAssured(); - RequestSpecification requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); - requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); - ResponseSpecification responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); - - final Integer roleId = RolesHelper.createRole(requestSpec, responseSpec); + final Long roleId = FeignRoleHelper.createRole(); assertNotNull(roleId); - final HashMap permissions = new HashMap<>(); - permissions.put("READ_WORKINGCAPITALLOAN", true); - RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, permissions); + FeignRoleHelper.addPermissionsToRole(roleId, Map.of("READ_WORKINGCAPITALLOAN", true)); final String username = Utils.uniqueRandomStringGenerator("WCLOriginatorUser", 4); final String password = "Str0ngP@sw0rd!"; final GetOfficesResponse headOffice = OfficeHelper.getHeadOffice(); final PostUsersRequest createUserRequest = new PostUsersRequest().username(username).firstname(Utils.randomFirstNameGenerator()) .lastname(Utils.randomLastNameGenerator()).email("wcloriginator@test.org").password(password).repeatPassword(password) - .sendPasswordToEmail(false).roles(List.of(roleId.longValue())).officeId(headOffice.getId()); - final PostUsersResponse userResponse = UserHelper.createUser(requestSpec, responseSpec, createUserRequest); + .sendPasswordToEmail(false).roles(List.of(roleId)).officeId(headOffice.getId()); + final PostUsersResponse userResponse = FeignUserHelper.createUser(createUserRequest); assertNotNull(userResponse.getResourceId()); final FineractFeignClient userClient = FineractFeignClientHelper.createNewFineractFeignClient(username, password); @@ -294,9 +282,7 @@ public void testUserWithoutPermissionsCannotAttachOrDetachOriginator() { .failVoid(() -> userClient.workingCapitalLoanOriginators().attachOriginatorToWorkingCapitalLoan(loanId, originatorId)); assertThat(attachException.getStatus()).isEqualTo(403); - final HashMap attachPermission = new HashMap<>(); - attachPermission.put("ATTACH_WORKING_CAPITAL_LOAN_ORIGINATOR", true); - RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, attachPermission); + FeignRoleHelper.addPermissionsToRole(roleId, Map.of("ATTACH_WORKING_CAPITAL_LOAN_ORIGINATOR", true)); FeignCalls.ok(() -> userClient.workingCapitalLoanOriginators().attachOriginatorToWorkingCapitalLoan(loanId, originatorId)); @@ -304,9 +290,7 @@ public void testUserWithoutPermissionsCannotAttachOrDetachOriginator() { .failVoid(() -> userClient.workingCapitalLoanOriginators().detachOriginatorFromWorkingCapitalLoan(loanId, originatorId)); assertThat(detachException.getStatus()).isEqualTo(403); - final HashMap detachPermission = new HashMap<>(); - detachPermission.put("DETACH_WORKING_CAPITAL_LOAN_ORIGINATOR", true); - RolesHelper.addPermissionsToRole(requestSpec, responseSpec, roleId, detachPermission); + FeignRoleHelper.addPermissionsToRole(roleId, Map.of("DETACH_WORKING_CAPITAL_LOAN_ORIGINATOR", true)); FeignCalls.ok(() -> userClient.workingCapitalLoanOriginators().detachOriginatorFromWorkingCapitalLoan(loanId, originatorId));