FINERACT-2380: move retrofit client based test to feign
This commit is contained in:
+3
-1
@@ -51,6 +51,8 @@ public class BasicAuthRequestInterceptor implements RequestInterceptor {
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate template) {
|
||||
template.header(AUTHORIZATION_HEADER, BASIC_AUTH_PREFIX + credentials);
|
||||
if (!template.headers().containsKey(AUTHORIZATION_HEADER)) {
|
||||
template.header(AUTHORIZATION_HEADER, BASIC_AUTH_PREFIX + credentials);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-10
@@ -61,7 +61,6 @@ import org.apache.fineract.client.feign.services.EntityDataTableApi;
|
||||
import org.apache.fineract.client.feign.services.EntityFieldConfigurationApi;
|
||||
import org.apache.fineract.client.feign.services.ExternalAssetOwnerLoanProductAttributesApi;
|
||||
import org.apache.fineract.client.feign.services.ExternalAssetOwnersApi;
|
||||
import org.apache.fineract.client.feign.services.ExternalAssetOwnersApiExtension;
|
||||
import org.apache.fineract.client.feign.services.ExternalEventConfigurationApi;
|
||||
import org.apache.fineract.client.feign.services.ExternalServicesApi;
|
||||
import org.apache.fineract.client.feign.services.FetchAuthenticatedUserDetailsApi;
|
||||
@@ -96,7 +95,6 @@ import org.apache.fineract.client.feign.services.LoanCobCatchUpApi;
|
||||
import org.apache.fineract.client.feign.services.LoanCollateralApi;
|
||||
import org.apache.fineract.client.feign.services.LoanCollateralManagementApi;
|
||||
import org.apache.fineract.client.feign.services.LoanDisbursementDetailsApi;
|
||||
import org.apache.fineract.client.feign.services.LoanDisbursementDetailsApiExtension;
|
||||
import org.apache.fineract.client.feign.services.LoanInterestPauseApi;
|
||||
import org.apache.fineract.client.feign.services.LoanProductsApi;
|
||||
import org.apache.fineract.client.feign.services.LoanReschedulingApi;
|
||||
@@ -394,10 +392,6 @@ public final class FineractFeignClient {
|
||||
return create(ExternalAssetOwnersApi.class);
|
||||
}
|
||||
|
||||
public ExternalAssetOwnersApiExtension externalAssetOwnersExtension() {
|
||||
return create(ExternalAssetOwnersApiExtension.class);
|
||||
}
|
||||
|
||||
public ExternalEventConfigurationApi externalEventConfiguration() {
|
||||
return create(ExternalEventConfigurationApi.class);
|
||||
}
|
||||
@@ -534,10 +528,6 @@ public final class FineractFeignClient {
|
||||
return create(LoanDisbursementDetailsApi.class);
|
||||
}
|
||||
|
||||
public LoanDisbursementDetailsApiExtension loanDisbursementDetailsExtension() {
|
||||
return create(LoanDisbursementDetailsApiExtension.class);
|
||||
}
|
||||
|
||||
public LoanInterestPauseApi loanInterestPause() {
|
||||
return create(LoanInterestPauseApi.class);
|
||||
}
|
||||
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* 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.client.feign.services;
|
||||
|
||||
import feign.Headers;
|
||||
import feign.Param;
|
||||
import feign.QueryMap;
|
||||
import feign.RequestLine;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.client.models.ExternalAssetOwnerRequest;
|
||||
import org.apache.fineract.client.models.PostInitiateTransferResponse;
|
||||
|
||||
public interface ExternalAssetOwnersApiExtension {
|
||||
|
||||
@RequestLine("POST /v1/external-asset-owners/transfers/{id}")
|
||||
@Headers("Content-Type: application/json")
|
||||
PostInitiateTransferResponse transferRequestWithIdWithBody(@Param("id") Long id, ExternalAssetOwnerRequest body,
|
||||
@QueryMap Map<String, Object> queryParams);
|
||||
|
||||
@RequestLine("POST /v1/external-asset-owners/transfers/external-id/{externalId}")
|
||||
@Headers("Content-Type: application/json")
|
||||
PostInitiateTransferResponse transferRequestWithId1WithBody(@Param("externalId") String externalId, ExternalAssetOwnerRequest body,
|
||||
@QueryMap Map<String, Object> queryParams);
|
||||
}
|
||||
-3
@@ -40,9 +40,6 @@ public class LoanProductResolver {
|
||||
log.debug("Resolving loan product by name [{}]", loanProductName);
|
||||
List<GetLoanProductsResponse> loanProductsResponses = ok(() -> fineractClient.loanProducts().retrieveAllLoanProducts(Map.of()));
|
||||
|
||||
log.info("Retrieved {} loan products from API", loanProductsResponses.size());
|
||||
log.info("Available loan products: {}", loanProductsResponses.stream().map(GetLoanProductsResponse::getName).toList());
|
||||
|
||||
GetLoanProductsResponse foundLpr = loanProductsResponses.stream().filter(lpr -> loanProductName.equals(lpr.getName())).findAny()
|
||||
.orElseThrow(() -> new IllegalArgumentException("Loan product [%s] not found".formatted(loanProductName)));
|
||||
return foundLpr.getId();
|
||||
|
||||
+7
-8
@@ -41,11 +41,10 @@ public class FineractInitializer implements InitializingBean {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// ALWAYS log initializer counts at INFO level for debugging
|
||||
log.info("=== FineractInitializer.afterPropertiesSet() called ===");
|
||||
log.info("Global initializers count: {}", globalInitializerSteps.size());
|
||||
log.info("Suite initializers count: {}", suiteInitializerSteps.size());
|
||||
log.info("Scenario initializers count: {}", scenarioInitializerSteps.size());
|
||||
log.debug("=== FineractInitializer.afterPropertiesSet() called ===");
|
||||
log.debug("Global initializers count: {}", globalInitializerSteps.size());
|
||||
log.debug("Suite initializers count: {}", suiteInitializerSteps.size());
|
||||
log.debug("Scenario initializers count: {}", scenarioInitializerSteps.size());
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
String globalInitializers = globalInitializerSteps.stream().map(Object::getClass).map(Class::getName)
|
||||
@@ -64,7 +63,7 @@ public class FineractInitializer implements InitializingBean {
|
||||
// Always log the suite initializers at INFO since this is critical
|
||||
String suiteInitializers = suiteInitializerSteps.stream().map(Object::getClass).map(Class::getName)
|
||||
.collect(Collectors.joining(", "));
|
||||
log.info("Suite initializers: [{}]", suiteInitializers);
|
||||
log.debug("Suite initializers: [{}]", suiteInitializers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +75,9 @@ public class FineractInitializer implements InitializingBean {
|
||||
}
|
||||
|
||||
public void setupDefaultsForSuite() throws Exception {
|
||||
log.info("=== setupDefaultsForSuite() called - {} suite initializers to execute ===", suiteInitializerSteps.size());
|
||||
log.debug("=== setupDefaultsForSuite() called - {} suite initializers to execute ===", suiteInitializerSteps.size());
|
||||
for (FineractSuiteInitializerStep initializerStep : suiteInitializerSteps) {
|
||||
log.info("Executing suite initializer: {}", initializerStep.getClass().getName());
|
||||
log.debug("Executing suite initializer: {}", initializerStep.getClass().getName());
|
||||
initializerStep.initializeForSuite();
|
||||
}
|
||||
businessDateHelper.setBusinessDateToday();
|
||||
|
||||
+1
-1
@@ -271,7 +271,7 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
|
||||
|
||||
try {
|
||||
executeVoid(() -> fineractClient.codeValues().createCodeValue(codeId, postCodeValuesDataRequest, Map.of()));
|
||||
log.info("Code value '{}' created successfully", name);
|
||||
log.debug("Code value '{}' created successfully", name);
|
||||
} catch (CallFailedRuntimeException e) {
|
||||
if (e.getStatus() == 403 && e.getDeveloperMessage() != null && e.getDeveloperMessage().contains("already exists")) {
|
||||
log.debug("Code value '{}' already exists, skipping creation", name);
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ public class FinancialActivityMappingGlobalInitializerStep implements FineractGl
|
||||
|
||||
try {
|
||||
executeVoid(() -> fineractClient.mappingFinancialActivitiesToAccounts().createGLAccount(request, Map.of()));
|
||||
log.info("Financial activity mapping created successfully");
|
||||
log.debug("Financial activity mapping created successfully");
|
||||
} catch (CallFailedRuntimeException e) {
|
||||
if (e.getStatus() == 403 && e.getDeveloperMessage() != null && e.getDeveloperMessage().contains("already exists")) {
|
||||
log.debug("Financial activity mapping already exists, skipping creation");
|
||||
|
||||
+4
-4
@@ -4329,14 +4329,14 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
|
||||
private PostLoanProductsResponse createLoanProductIdempotent(PostLoanProductsRequest loanProductRequest) {
|
||||
String productName = loanProductRequest.getName();
|
||||
log.info("Attempting to create loan product: {}", productName);
|
||||
log.debug("Attempting to create loan product: {}", productName);
|
||||
try {
|
||||
List<GetLoanProductsResponse> existingProducts = fineractClient.loanProducts().retrieveAllLoanProducts(Map.of());
|
||||
GetLoanProductsResponse existingProduct = existingProducts.stream().filter(p -> productName.equals(p.getName())).findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (existingProduct != null) {
|
||||
log.info("Loan product '{}' already exists with ID: {}", productName, existingProduct.getId());
|
||||
log.debug("Loan product '{}' already exists with ID: {}", productName, existingProduct.getId());
|
||||
PostLoanProductsResponse response = new PostLoanProductsResponse();
|
||||
response.setResourceId(existingProduct.getId());
|
||||
return response;
|
||||
@@ -4345,10 +4345,10 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
|
||||
log.warn("Error checking if loan product '{}' exists", productName, e);
|
||||
}
|
||||
|
||||
log.info("Creating new loan product: {}", productName);
|
||||
log.debug("Creating new loan product: {}", productName);
|
||||
try {
|
||||
PostLoanProductsResponse response = ok(() -> fineractClient.loanProducts().createLoanProduct(loanProductRequest, Map.of()));
|
||||
log.info("Successfully created loan product '{}' with ID: {}", productName, response.getResourceId());
|
||||
log.debug("Successfully created loan product '{}' with ID: {}", productName, response.getResourceId());
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
log.error("FAILED to create loan product '{}'", productName, e);
|
||||
|
||||
+3
-3
@@ -55,7 +55,7 @@ public class ExternalEventSuiteInitializerStep implements FineractSuiteInitializ
|
||||
|
||||
@Override
|
||||
public void initializeForSuite() throws InterruptedException {
|
||||
log.info("=== ExternalEventSuiteInitializerStep.initializeForSuite() - START ===");
|
||||
log.debug("=== ExternalEventSuiteInitializerStep.initializeForSuite() - START ===");
|
||||
|
||||
// Step 1: Enable all external events
|
||||
Map<String, Boolean> eventConfigMap = new HashMap<>();
|
||||
@@ -72,7 +72,7 @@ public class ExternalEventSuiteInitializerStep implements FineractSuiteInitializ
|
||||
.externalEventConfigurations(eventConfigMap);
|
||||
|
||||
executeVoid(() -> fineractClient.externalEventConfiguration().updateExternalEventConfigurations(null, request, Map.of()));
|
||||
log.info("=== External event configuration updated - all events enabled ===");
|
||||
log.debug("=== External event configuration updated - all events enabled ===");
|
||||
|
||||
// Step 2: Wait for JMS Listener to be ready before proceeding
|
||||
if (eventProperties != null && eventProperties.isEventVerificationEnabled()) {
|
||||
@@ -93,6 +93,6 @@ public class ExternalEventSuiteInitializerStep implements FineractSuiteInitializ
|
||||
}
|
||||
}
|
||||
|
||||
log.info("=== ExternalEventSuiteInitializerStep.initializeForSuite() - COMPLETED ===");
|
||||
log.debug("=== ExternalEventSuiteInitializerStep.initializeForSuite() - COMPLETED ===");
|
||||
}
|
||||
}
|
||||
|
||||
+18
-18
@@ -40,44 +40,44 @@ public class JobSuiteInitializerStep implements FineractSuiteInitializerStep {
|
||||
private final FineractFeignClient fineractClient;
|
||||
|
||||
public JobSuiteInitializerStep(FineractFeignClient fineractClient) {
|
||||
log.info("=== JobSuiteInitializerStep: Constructor called - bean is being created ===");
|
||||
log.debug("=== JobSuiteInitializerStep: Constructor called - bean is being created ===");
|
||||
this.fineractClient = fineractClient;
|
||||
log.info("=== JobSuiteInitializerStep: FineractFeignClient injected successfully ===");
|
||||
log.debug("=== JobSuiteInitializerStep: FineractFeignClient injected successfully ===");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeForSuite() throws InterruptedException {
|
||||
log.info("=== JobSuiteInitializerStep.initializeForSuite() - START ===");
|
||||
log.debug("=== JobSuiteInitializerStep.initializeForSuite() - START ===");
|
||||
enableAndExecuteEventJob();
|
||||
log.info("=== JobSuiteInitializerStep.initializeForSuite() - COMPLETED successfully ===");
|
||||
log.debug("=== JobSuiteInitializerStep.initializeForSuite() - COMPLETED successfully ===");
|
||||
}
|
||||
|
||||
private void enableAndExecuteEventJob() throws InterruptedException {
|
||||
log.info("=== Initializing Send Asynchronous Events job ===");
|
||||
log.debug("=== Initializing Send Asynchronous Events job ===");
|
||||
Long jobId = updateExternalEventJobFrequency(EVERY_1_SECONDS);
|
||||
log.info("=== Updated cron expression to EVERY_1_SECONDS ===");
|
||||
log.debug("=== Updated cron expression to EVERY_1_SECONDS ===");
|
||||
|
||||
// CRITICAL: SchedulerGlobalInitializerStep stops the scheduler globally
|
||||
// Solution: START the scheduler so the job runs every 1 second automatically
|
||||
log.info("Starting scheduler to enable automatic job execution every 1 second...");
|
||||
log.debug("Starting scheduler to enable automatic job execution every 1 second...");
|
||||
executeVoid(() -> fineractClient.scheduler().changeSchedulerStatus("start", Map.of()));
|
||||
log.info("Scheduler started successfully");
|
||||
log.debug("Scheduler started successfully");
|
||||
|
||||
// Manually execute once immediately to publish any queued events from initialization
|
||||
log.info("Manually executing '{}' job once to publish queued events...", SEND_ASYNCHRONOUS_EVENTS_JOB_NAME);
|
||||
log.debug("Manually executing '{}' job once to publish queued events...", SEND_ASYNCHRONOUS_EVENTS_JOB_NAME);
|
||||
executeVoid(() -> fineractClient.schedulerJob().executeJob(jobId, new ExecuteJobRequest(), Map.of("command", "executeJob")));
|
||||
|
||||
// Poll job history to confirm it ran
|
||||
log.info("Polling job history to confirm initial execution...");
|
||||
log.debug("Polling job history to confirm initial execution...");
|
||||
Long initialRunCount = getJobRunCount(jobId);
|
||||
log.info("Initial job run count: {}", initialRunCount);
|
||||
log.debug("Initial job run count: {}", initialRunCount);
|
||||
|
||||
boolean jobRan = false;
|
||||
for (int i = 0; i < 30; i++) {
|
||||
Thread.sleep(200);
|
||||
Long currentRunCount = getJobRunCount(jobId);
|
||||
if (currentRunCount > initialRunCount) {
|
||||
log.info("Job execution confirmed! Run count increased from {} to {}", initialRunCount, currentRunCount);
|
||||
log.debug("Job execution confirmed! Run count increased from {} to {}", initialRunCount, currentRunCount);
|
||||
jobRan = true;
|
||||
break;
|
||||
}
|
||||
@@ -88,9 +88,9 @@ public class JobSuiteInitializerStep implements FineractSuiteInitializerStep {
|
||||
}
|
||||
|
||||
// Wait for events to propagate to ActiveMQ
|
||||
log.info("Waiting 1 second for event propagation to ActiveMQ...");
|
||||
log.debug("Waiting 1 second for event propagation to ActiveMQ...");
|
||||
Thread.sleep(1000);
|
||||
log.info("Scheduler is now running - job will execute every 1 second automatically");
|
||||
log.debug("Scheduler is now running - job will execute every 1 second automatically");
|
||||
}
|
||||
|
||||
private Long getJobRunCount(Long jobId) {
|
||||
@@ -105,20 +105,20 @@ public class JobSuiteInitializerStep implements FineractSuiteInitializerStep {
|
||||
|
||||
@Override
|
||||
public void resetAfterSuite() {
|
||||
log.info("=== JobSuiteInitializerStep.resetAfterSuite() - START ===");
|
||||
log.debug("=== JobSuiteInitializerStep.resetAfterSuite() - START ===");
|
||||
|
||||
// Stop the scheduler to prevent jobs from running between test suites
|
||||
log.info("Stopping scheduler...");
|
||||
log.debug("Stopping scheduler...");
|
||||
try {
|
||||
executeVoid(() -> fineractClient.scheduler().changeSchedulerStatus(Map.of("command", "stop")));
|
||||
log.info("Scheduler stopped successfully");
|
||||
log.debug("Scheduler stopped successfully");
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to stop scheduler: {}", e.getMessage());
|
||||
}
|
||||
|
||||
// Reset cron expression to default
|
||||
updateExternalEventJobFrequency(EVERY_60_SECONDS);
|
||||
log.info("=== JobSuiteInitializerStep.resetAfterSuite() - COMPLETED ===");
|
||||
log.debug("=== JobSuiteInitializerStep.resetAfterSuite() - COMPLETED ===");
|
||||
}
|
||||
|
||||
private Long updateExternalEventJobFrequency(String cronExpression) {
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ import org.springframework.stereotype.Component;
|
||||
public class EventCheckHelper {
|
||||
|
||||
private static final DateTimeFormatter FORMATTER_EVENTS = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final long TRANSACTION_COMMIT_DELAY_MS = 500L;
|
||||
private static final long TRANSACTION_COMMIT_DELAY_MS = 100L;
|
||||
|
||||
@Autowired
|
||||
private FineractFeignClient fineractClient;
|
||||
|
||||
+8
-22
@@ -46,7 +46,6 @@ import java.io.IOException;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -54,7 +53,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.client.feign.FineractFeignClient;
|
||||
import org.apache.fineract.client.feign.services.ExternalAssetOwnerLoanProductAttributesApi;
|
||||
import org.apache.fineract.client.feign.services.ExternalAssetOwnersApi;
|
||||
import org.apache.fineract.client.feign.services.ExternalAssetOwnersApiExtension;
|
||||
import org.apache.fineract.client.feign.services.LoanProductsApi;
|
||||
import org.apache.fineract.client.feign.util.CallFailedRuntimeException;
|
||||
import org.apache.fineract.client.models.ExternalAssetOwnerRequest;
|
||||
@@ -104,10 +102,6 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||
return fineractFeignClient.externalAssetOwners();
|
||||
}
|
||||
|
||||
private ExternalAssetOwnersApiExtension externalAssetOwnersApiExtension() {
|
||||
return fineractFeignClient.externalAssetOwnersExtension();
|
||||
}
|
||||
|
||||
private LoanProductsApi loanProductsApi() {
|
||||
return fineractFeignClient.loanProducts();
|
||||
}
|
||||
@@ -152,8 +146,8 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||
.dateFormat(DATE_FORMAT_ASSET_EXT)//
|
||||
.locale(DEFAULT_LOCALE);//
|
||||
|
||||
PostInitiateTransferResponse response = externalAssetOwnersApi().transferRequestWithLoanId(loanId, request, transferData.get(0),
|
||||
Collections.emptyMap());
|
||||
PostInitiateTransferResponse response = externalAssetOwnersApi().transferRequestWithLoanId(loanId, request,
|
||||
Map.of("command", transferData.get(0)));
|
||||
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_RESPONSE, response);
|
||||
testContext().set(TestContextKey.ASSET_EXTERNALIZATION_BUYBACK_TRANSFER_EXTERNAL_ID_FROM_RESPONSE,
|
||||
response.getResourceExternalId());
|
||||
@@ -809,9 +803,7 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||
String transferExternalId = testContext()
|
||||
.get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type);
|
||||
|
||||
ExternalAssetOwnerRequest request = new ExternalAssetOwnerRequest().dateFormat(DATE_FORMAT_ASSET_EXT).locale(DEFAULT_LOCALE);
|
||||
|
||||
externalAssetOwnersApiExtension().transferRequestWithId1WithBody(transferExternalId, request, Map.of("command", command));
|
||||
externalAssetOwnersApi().transferRequestWithId1(transferExternalId, Map.of("command", command));
|
||||
}
|
||||
|
||||
@When("Admin send {string} command to the transaction type {string} will throw error")
|
||||
@@ -819,10 +811,8 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||
String transferExternalId = testContext()
|
||||
.get(TestContextKey.ASSET_EXTERNALIZATION_TRANSFER_EXTERNAL_ID_USER_GENERATED + "_" + type);
|
||||
|
||||
ExternalAssetOwnerRequest request = new ExternalAssetOwnerRequest().dateFormat(DATE_FORMAT_ASSET_EXT).locale(DEFAULT_LOCALE);
|
||||
|
||||
CallFailedRuntimeException exception = fail(() -> externalAssetOwnersApiExtension()
|
||||
.transferRequestWithId1WithBody(transferExternalId, request, Map.of("command", command)));
|
||||
CallFailedRuntimeException exception = fail(
|
||||
() -> externalAssetOwnersApi().transferRequestWithId1(transferExternalId, Map.of("command", command)));
|
||||
|
||||
assertThat(exception.getStatus()).as("Expected status code: 403").isEqualTo(403);
|
||||
}
|
||||
@@ -883,10 +873,8 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||
}
|
||||
|
||||
ExternalAssetOwnerRequest request = new ExternalAssetOwnerRequest().dateFormat(DATE_FORMAT_ASSET_EXT).locale(DEFAULT_LOCALE);
|
||||
|
||||
CallFailedRuntimeException exception = fail(() -> externalAssetOwnersApiExtension()
|
||||
.transferRequestWithId1WithBody(transferExternalId, request, Map.of("command", command)));
|
||||
CallFailedRuntimeException exception = fail(
|
||||
() -> externalAssetOwnersApi().transferRequestWithId1(transferExternalId, Map.of("command", command)));
|
||||
|
||||
assertThat(exception.getStatus()).as("Expected status code: 403").isEqualTo(403);
|
||||
}
|
||||
@@ -900,9 +888,7 @@ public class AssetExternalizationStepDef extends AbstractStepDef {
|
||||
transferExternalId = testContext().get(TestContextKey.ASSET_EXTERNALIZATION_SALES_TRANSFER_EXTERNAL_ID_FROM_RESPONSE);
|
||||
}
|
||||
|
||||
ExternalAssetOwnerRequest request = new ExternalAssetOwnerRequest().dateFormat(DATE_FORMAT_ASSET_EXT).locale(DEFAULT_LOCALE);
|
||||
|
||||
externalAssetOwnersApiExtension().transferRequestWithId1WithBody(transferExternalId, request, Map.of("command", command));
|
||||
externalAssetOwnersApi().transferRequestWithId1(transferExternalId, Map.of("command", command));
|
||||
}
|
||||
|
||||
@When("Admin set external asset owner loan product attribute {string} value {string} for loan product {string}")
|
||||
|
||||
+15
-3
@@ -27,6 +27,7 @@ import io.cucumber.java.en.Then;
|
||||
import io.cucumber.java.en.When;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
@@ -39,6 +40,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.fineract.avro.loan.v1.LoanSchedulePeriodDataV1;
|
||||
import org.apache.fineract.client.feign.FineractFeignClient;
|
||||
import org.apache.fineract.client.feign.services.BatchApiApi;
|
||||
@@ -50,6 +52,7 @@ import org.apache.fineract.client.models.GetClientsClientIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdStatus;
|
||||
import org.apache.fineract.client.models.GetLoansLoanIdTransactions;
|
||||
import org.apache.fineract.client.models.GetUsersUserIdResponse;
|
||||
import org.apache.fineract.client.models.Header;
|
||||
import org.apache.fineract.client.models.InlineJobRequest;
|
||||
import org.apache.fineract.client.models.PostClientsRequest;
|
||||
@@ -61,6 +64,7 @@ import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||
import org.apache.fineract.client.models.PostLoansRequest;
|
||||
import org.apache.fineract.client.models.PostLoansResponse;
|
||||
import org.apache.fineract.client.models.PostUpdateRescheduleLoansRequest;
|
||||
import org.apache.fineract.client.models.PostUsersResponse;
|
||||
import org.apache.fineract.test.data.ChargeProductType;
|
||||
import org.apache.fineract.test.data.LoanRescheduleErrorMessage;
|
||||
import org.apache.fineract.test.data.LoanStatus;
|
||||
@@ -543,10 +547,18 @@ public class BatchApiStepDef extends AbstractStepDef {
|
||||
|
||||
// Feign throws exceptions on errors instead of returning error in response body
|
||||
ErrorResponse errorResponse = null;
|
||||
Map<String, String> headerMap = new HashMap<>();
|
||||
|
||||
// Create new user which cannot bypass loan COB execution
|
||||
PostUsersResponse createUserResponse = testContext().get(TestContextKey.CREATED_SIMPLE_USER_RESPONSE);
|
||||
Long createdUserId = createUserResponse.getResourceId();
|
||||
GetUsersUserIdResponse user = fineractFeignClient.users().retrieveOne31(createdUserId);
|
||||
String authorizationString = user.getUsername() + ":" + PWD_USER_WITH_ROLE;
|
||||
Base64 base64 = new Base64();
|
||||
headerMap.put("Authorization",
|
||||
"Basic " + new String(base64.encode(authorizationString.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
|
||||
try {
|
||||
// TODO: Feign doesn't support per-request headers - need to use RequestInterceptor
|
||||
batchApiApi().handleBatchRequests(requestList, queryParams);
|
||||
throw new IllegalStateException("Expected Feign exception but call succeeded");
|
||||
batchApiApi().handleBatchRequests(requestList, queryParams, headerMap);
|
||||
} catch (org.apache.fineract.client.feign.FeignException e) {
|
||||
errorResponse = fromJson(e.responseBodyAsString(), ErrorResponse.class);
|
||||
}
|
||||
|
||||
+4
-2
@@ -32,6 +32,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.client.feign.FineractFeignClient;
|
||||
import org.apache.fineract.client.models.LoanAccountLock;
|
||||
import org.apache.fineract.client.models.LoanAccountLockResponseDTO;
|
||||
import org.apache.fineract.client.models.LockRequest;
|
||||
import org.apache.fineract.client.models.OldestCOBProcessedLoanDTO;
|
||||
import org.apache.fineract.client.models.PostLoansResponse;
|
||||
import org.apache.fineract.test.helper.ErrorMessageHelper;
|
||||
@@ -90,7 +91,8 @@ public class LoanCOBStepDef extends AbstractStepDef {
|
||||
PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.getLoanId();
|
||||
|
||||
executeVoid(() -> fineractClient.defaultApi().placeLockOnLoanAccount(loanId, "LOAN_COB_CHUNK_PROCESSING", "TestError"));
|
||||
executeVoid(() -> fineractClient.defaultApi().placeLockOnLoanAccount(loanId, "LOAN_COB_CHUNK_PROCESSING",
|
||||
new LockRequest().error("ERROR")));
|
||||
}
|
||||
|
||||
@When("Admin places a lock on loan account WITHOUT an error message")
|
||||
@@ -98,6 +100,6 @@ public class LoanCOBStepDef extends AbstractStepDef {
|
||||
PostLoansResponse loanResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
|
||||
long loanId = loanResponse.getLoanId();
|
||||
|
||||
executeVoid(() -> fineractClient.defaultApi().placeLockOnLoanAccount(loanId, "LOAN_COB_CHUNK_PROCESSING", ""));
|
||||
executeVoid(() -> fineractClient.defaultApi().placeLockOnLoanAccount(loanId, "LOAN_COB_CHUNK_PROCESSING", new LockRequest()));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -75,6 +75,7 @@ import org.apache.fineract.client.models.ApiResponse;
|
||||
import org.apache.fineract.client.models.BusinessDateResponse;
|
||||
import org.apache.fineract.client.models.BuyDownFeeAmortizationDetails;
|
||||
import org.apache.fineract.client.models.CapitalizedIncomeDetails;
|
||||
import org.apache.fineract.client.models.CommandProcessingResult;
|
||||
import org.apache.fineract.client.models.DeleteLoansLoanIdResponse;
|
||||
import org.apache.fineract.client.models.DisbursementDetail;
|
||||
import org.apache.fineract.client.models.GetCodeValuesDataResponse;
|
||||
@@ -1626,8 +1627,8 @@ public class LoanStepDef extends AbstractStepDef {
|
||||
|
||||
PostAddAndDeleteDisbursementDetailRequest disbursementDetailRequest = LoanRequestFactory
|
||||
.defaultLoanDisbursementDetailRequest(disbursementData);
|
||||
PostAddAndDeleteDisbursementDetailRequest loanDisburseResponse = ok(
|
||||
() -> fineractClient.loanDisbursementDetailsExtension().addAndDeleteDisbursementDetail(loanId, disbursementDetailRequest));
|
||||
CommandProcessingResult loanDisburseResponse = ok(
|
||||
() -> fineractClient.loanDisbursementDetails().addAndDeleteDisbursementDetail(loanId, disbursementDetailRequest));
|
||||
testContext().set(TestContextKey.LOAN_DISBURSEMENT_DETAIL_RESPONSE, loanDisburseResponse);
|
||||
}
|
||||
|
||||
|
||||
@@ -701,7 +701,7 @@ Feature: LoanReschedule
|
||||
| rescheduleFromDate | submittedOnDate | adjustedDueDate | approvedOnDate | enclosingTransaction |
|
||||
| 16 January 2024 | 10 January 2024 | 31 January 2024 | 10 January 2024 | true |
|
||||
|
||||
@Skip @TestRailId:C3318 @AdvancedPaymentAllocation
|
||||
@TestRailId:C3318 @AdvancedPaymentAllocation
|
||||
Scenario: Verify that in case of Loan is hard locked for COB execution WITHOUT error message, BatchAPI request of Loan reschedule creation and approval will result a 409 error and a LOAN_LOCKED_BY_COB error message
|
||||
When Admin sets the business date to "01 January 2024"
|
||||
When Admin creates a client with random data
|
||||
|
||||
+8
-12
@@ -97,8 +97,8 @@ public class ExternalAssetOwnersApiResource {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))),
|
||||
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
|
||||
public CommandProcessingResult transferRequestWithLoanId(@PathParam("loanId") final Long loanId,
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam,
|
||||
@Parameter(hidden = true) ExternalAssetOwnerRequest assetOwnerReq) {
|
||||
@Parameter ExternalAssetOwnerRequest assetOwnerReq,
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
|
||||
platformUserRightsContext.isAuthenticated();
|
||||
final String serializedAssetRequest = postApiJsonSerializerService.serialize(assetOwnerReq);
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, loanId, serializedAssetRequest,
|
||||
@@ -115,8 +115,8 @@ public class ExternalAssetOwnersApiResource {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))),
|
||||
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
|
||||
public CommandProcessingResult transferRequestWithLoanExternalId(@PathParam("loanExternalId") final String externalLoanId,
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam,
|
||||
@Parameter(hidden = true) ExternalAssetOwnerRequest assetOwnerReq) {
|
||||
@Parameter ExternalAssetOwnerRequest assetOwnerReq,
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
|
||||
platformUserRightsContext.isAuthenticated();
|
||||
final Long loanId = loanReadPlatformService.getLoanIdByLoanExternalId(externalLoanId);
|
||||
final String serializedAssetRequest = postApiJsonSerializerService.serialize(assetOwnerReq);
|
||||
@@ -134,11 +134,9 @@ public class ExternalAssetOwnersApiResource {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))),
|
||||
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
|
||||
public CommandProcessingResult transferRequestWithId(@PathParam("id") final Long id,
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam,
|
||||
@Parameter(hidden = true) ExternalAssetOwnerRequest assetOwnerReq) {
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
|
||||
platformUserRightsContext.isAuthenticated();
|
||||
final String serializedAssetRequest = postApiJsonSerializerService.serialize(assetOwnerReq);
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, id, serializedAssetRequest,
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, id, null,
|
||||
new UnrecognizedQueryParamException(COMMAND_PARAM, commandParam));
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
@@ -151,12 +149,10 @@ public class ExternalAssetOwnersApiResource {
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ExternalAssetOwnersApiResourceSwagger.PostInitiateTransferResponse.class))),
|
||||
@ApiResponse(responseCode = "403", description = "Transfer cannot be initiated") })
|
||||
public CommandProcessingResult transferRequestWithId(@PathParam("externalId") final String externalId,
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam,
|
||||
@Parameter(hidden = true) ExternalAssetOwnerRequest assetOwnerReq) {
|
||||
@QueryParam(COMMAND_PARAM) @Parameter(description = COMMAND_PARAM) final String commandParam) {
|
||||
platformUserRightsContext.isAuthenticated();
|
||||
final Long id = externalAssetOwnersReadService.retrieveLastTransferIdByExternalId(new ExternalId(externalId));
|
||||
final String serializedAssetRequest = postApiJsonSerializerService.serialize(assetOwnerReq);
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, id, serializedAssetRequest,
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, id, null,
|
||||
new UnrecognizedQueryParamException(COMMAND_PARAM, commandParam));
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
+3
-4
@@ -70,7 +70,7 @@ public class InternalLoanAccountLockApiResource implements InitializingBean {
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
|
||||
public Response placeLockOnLoanAccount(@Context final UriInfo uriInfo, @PathParam("loanId") Long loanId,
|
||||
@PathParam("lockOwner") String lockOwner, @RequestBody(required = false) String error) {
|
||||
@PathParam("lockOwner") String lockOwner, @RequestBody(required = false) LockRequest request) {
|
||||
log.warn("------------------------------------------------------------");
|
||||
log.warn(" ");
|
||||
log.warn("Placing lock on loan: {}", loanId);
|
||||
@@ -80,11 +80,10 @@ public class InternalLoanAccountLockApiResource implements InitializingBean {
|
||||
LoanAccountLock loanAccountLock = new LoanAccountLock(loanId, LockOwner.valueOf(lockOwner),
|
||||
ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE));
|
||||
|
||||
if (StringUtils.isNotBlank(error)) {
|
||||
loanAccountLock.setError(error, error);
|
||||
if (StringUtils.isNotBlank(request.getError())) {
|
||||
loanAccountLock.setError(request.getError(), request.getError());
|
||||
}
|
||||
loanAccountLockRepository.save(loanAccountLock);
|
||||
return Response.status(Response.Status.ACCEPTED).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
-9
@@ -16,16 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.client.feign.services;
|
||||
package org.apache.fineract.cob.api;
|
||||
|
||||
import feign.Param;
|
||||
import feign.RequestLine;
|
||||
import org.apache.fineract.client.models.PostAddAndDeleteDisbursementDetailRequest;
|
||||
import lombok.Data;
|
||||
|
||||
public interface LoanDisbursementDetailsApiExtension {
|
||||
|
||||
@RequestLine("PUT /v1/loans/{loanId}/disbursements/editDisbursements")
|
||||
PostAddAndDeleteDisbursementDetailRequest addAndDeleteDisbursementDetail(@Param("loanId") Long loanId,
|
||||
PostAddAndDeleteDisbursementDetailRequest postAddAndDeleteDisbursementDetailRequest);
|
||||
@Data
|
||||
public class LockRequest {
|
||||
|
||||
private String error;
|
||||
}
|
||||
+7
-9
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
@@ -68,15 +69,13 @@ public class LoanDisbursementDetailApiResource {
|
||||
@Path("{disbursementId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String updateDisbursementDate(@PathParam("loanId") final Long loanId, @PathParam("disbursementId") final Long disbursementId,
|
||||
final String apiRequestBodyAsJson) {
|
||||
public CommandProcessingResult updateDisbursementDate(@PathParam("loanId") final Long loanId,
|
||||
@PathParam("disbursementId") final Long disbursementId, final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateDisbusementDate(loanId, disbursementId)
|
||||
.withJson(apiRequestBodyAsJson).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@@ -84,14 +83,13 @@ public class LoanDisbursementDetailApiResource {
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = LoanDisbursementDetailApiResourceSwagger.PostAddAndDeleteDisbursementDetailRequest.class)))
|
||||
public String addAndDeleteDisbursementDetail(@PathParam("loanId") final Long loanId, final String apiRequestBodyAsJson) {
|
||||
public CommandProcessingResult addAndDeleteDisbursementDetail(@PathParam("loanId") final Long loanId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
CommandWrapper commandRequest = new CommandWrapperBuilder().addAndDeleteDisbursementDetails(loanId).withJson(apiRequestBodyAsJson)
|
||||
.build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@GET
|
||||
|
||||
+4
-2
@@ -21,6 +21,7 @@ package org.apache.fineract.integrationtests.common.loans;
|
||||
import com.google.gson.Gson;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
|
||||
@@ -45,7 +46,7 @@ public class LoanAccountLockHelper {
|
||||
// org.apache.fineract.client.models.PostLoansLoanIdRequest)
|
||||
@Deprecated(forRemoval = true)
|
||||
public String placeSoftLockOnLoanAccount(Integer loanId, String lockOwner) {
|
||||
return placeSoftLockOnLoanAccount(loanId, lockOwner, null);
|
||||
return placeSoftLockOnLoanAccount(loanId, lockOwner, "");
|
||||
}
|
||||
|
||||
// TODO: Rewrite to use fineract-client instead!
|
||||
@@ -54,7 +55,8 @@ public class LoanAccountLockHelper {
|
||||
@Deprecated(forRemoval = true)
|
||||
public String placeSoftLockOnLoanAccount(Integer loanId, String lockOwner, String error) {
|
||||
return Utils.performServerPost(requestSpec, responseSpec,
|
||||
INTERNAL_PLACE_LOCK_ON_LOAN_ACCOUNT_URL + loanId + "/place-lock/" + lockOwner + "?" + Utils.TENANT_IDENTIFIER, error);
|
||||
INTERNAL_PLACE_LOCK_ON_LOAN_ACCOUNT_URL + loanId + "/place-lock/" + lockOwner + "?" + Utils.TENANT_IDENTIFIER,
|
||||
GSON.toJson(Map.of("error", error)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -2584,11 +2584,11 @@ public class LoanTransactionHelper {
|
||||
getAddAndDeleteDisbursementsAsJSON(approvalAmount, expectedDisbursementDate, disbursementData), jsonAttributeToGetBack);
|
||||
}
|
||||
|
||||
public String addAndDeleteDisbursementDetail(final Long loanId, PostAddAndDeleteDisbursementDetailRequest request) {
|
||||
public CommandProcessingResult addAndDeleteDisbursementDetail(final Long loanId, PostAddAndDeleteDisbursementDetailRequest request) {
|
||||
return Calls.ok(FineractClientHelper.getFineractClient().loanDisbursementDetails.addAndDeleteDisbursementDetail(loanId, request));
|
||||
}
|
||||
|
||||
public String addAndDeleteDisbursementDetail(final Long loanId, final List<DisbursementDetail> disbursementDetails) {
|
||||
public CommandProcessingResult addAndDeleteDisbursementDetail(final Long loanId, final List<DisbursementDetail> disbursementDetails) {
|
||||
return addAndDeleteDisbursementDetail(loanId, new PostAddAndDeleteDisbursementDetailRequest().locale("en")
|
||||
.dateFormat("dd MMMM yyyy").disbursementData(disbursementDetails));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user