This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git

commit f28382b70f66c9b33d870d6b66cf4bf1e2290b56
Author: Adam Saghy <[email protected]>
AuthorDate: Tue Nov 25 21:24:24 2025 +0100

    FINERACT-2380: move retrofit client based test to feign
---
 .../client/feign/BasicAuthRequestInterceptor.java  |  4 ++-
 .../fineract/client/feign/FineractFeignClient.java | 10 ------
 .../services/ExternalAssetOwnersApiExtension.java  | 40 ----------------------
 .../test/data/loanproduct/LoanProductResolver.java |  3 --
 .../test/initializer/base/FineractInitializer.java | 15 ++++----
 .../global/CodeGlobalInitializerStep.java          |  2 +-
 ...ancialActivityMappingGlobalInitializerStep.java |  2 +-
 .../global/LoanProductGlobalInitializerStep.java   |  8 ++---
 .../suite/ExternalEventSuiteInitializerStep.java   |  6 ++--
 .../initializer/suite/JobSuiteInitializerStep.java | 36 +++++++++----------
 .../test/messaging/event/EventCheckHelper.java     |  2 +-
 .../AssetExternalizationStepDef.java               | 30 +++++-----------
 .../test/stepdef/common/BatchApiStepDef.java       | 18 ++++++++--
 .../fineract/test/stepdef/loan/LoanCOBStepDef.java |  6 ++--
 .../fineract/test/stepdef/loan/LoanStepDef.java    |  5 +--
 .../test/resources/features/LoanReschedule.feature |  2 +-
 .../api/ExternalAssetOwnersApiResource.java        | 20 +++++------
 .../api/InternalLoanAccountLockApiResource.java    |  7 ++--
 .../org/apache/fineract/cob/api/LockRequest.java   | 14 +++-----
 .../api/LoanDisbursementDetailApiResource.java     | 16 ++++-----
 .../common/loans/LoanAccountLockHelper.java        |  6 ++--
 .../common/loans/LoanTransactionHelper.java        |  4 +--
 22 files changed, 98 insertions(+), 158 deletions(-)

diff --git 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/BasicAuthRequestInterceptor.java
 
b/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/BasicAuthRequestInterceptor.java
index dad772522d..355bec7dbd 100644
--- 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/BasicAuthRequestInterceptor.java
+++ 
b/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/BasicAuthRequestInterceptor.java
@@ -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);
+        }
     }
 }
diff --git 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/FineractFeignClient.java
 
b/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/FineractFeignClient.java
index 3a416e9119..8c049039f8 100644
--- 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/FineractFeignClient.java
+++ 
b/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/FineractFeignClient.java
@@ -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);
     }
diff --git 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/ExternalAssetOwnersApiExtension.java
 
b/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/ExternalAssetOwnersApiExtension.java
deleted file mode 100644
index 90bcf7fd0e..0000000000
--- 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/ExternalAssetOwnersApiExtension.java
+++ /dev/null
@@ -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);
-}
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java
index 18c7e9607d..8c98b2b0b4 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/data/loanproduct/LoanProductResolver.java
@@ -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();
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java
index cb245fa72e..383f1532d3 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/base/FineractInitializer.java
@@ -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();
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
index 4e7ccc9190..983099fc24 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/CodeGlobalInitializerStep.java
@@ -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);
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java
index f13d754d5d..a274c6e039 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/FinancialActivityMappingGlobalInitializerStep.java
@@ -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");
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
index b535f0fddf..e8ae46d19b 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/global/LoanProductGlobalInitializerStep.java
@@ -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);
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java
index 1fd71ce917..5a6451b8b7 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/ExternalEventSuiteInitializerStep.java
@@ -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 ===");
     }
 }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java
index 3922e44022..93ae3321a1 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/initializer/suite/JobSuiteInitializerStep.java
@@ -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) {
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java
index 59406c4ec2..94449abdcd 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/messaging/event/EventCheckHelper.java
@@ -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;
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/assetexternalization/AssetExternalizationStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/assetexternalization/AssetExternalizationStepDef.java
index 868fe05b7d..10b9bb20bb 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/assetexternalization/AssetExternalizationStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/assetexternalization/AssetExternalizationStepDef.java
@@ -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}")
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java
index 72345ceec9..00a9064667 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/common/BatchApiStepDef.java
@@ -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);
         }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanCOBStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanCOBStepDef.java
index 4dccbf69f0..fb84780c93 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanCOBStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanCOBStepDef.java
@@ -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()));
     }
 }
diff --git 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
index f409d90393..da78fee7fa 100644
--- 
a/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
+++ 
b/fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java
@@ -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);
     }
 
diff --git 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature
index f6a809c3ba..424461e376 100644
--- 
a/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature
+++ 
b/fineract-e2e-tests-runner/src/test/resources/features/LoanReschedule.feature
@@ -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
diff --git 
a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
 
b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
index b0021fa998..3dbebba00d 100644
--- 
a/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
+++ 
b/fineract-investor/src/main/java/org/apache/fineract/investor/api/ExternalAssetOwnersApiResource.java
@@ -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);
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/cob/api/InternalLoanAccountLockApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/cob/api/InternalLoanAccountLockApiResource.java
index a925719783..c61696e156 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/cob/api/InternalLoanAccountLockApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/api/InternalLoanAccountLockApiResource.java
@@ -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();
     }
-
 }
diff --git 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/LoanDisbursementDetailsApiExtension.java
 b/fineract-provider/src/main/java/org/apache/fineract/cob/api/LockRequest.java
similarity index 60%
rename from 
fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/LoanDisbursementDetailsApiExtension.java
rename to 
fineract-provider/src/main/java/org/apache/fineract/cob/api/LockRequest.java
index dece067344..0b33c0acb6 100644
--- 
a/fineract-client-feign/src/main/java/org/apache/fineract/client/feign/services/LoanDisbursementDetailsApiExtension.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/cob/api/LockRequest.java
@@ -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;
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanDisbursementDetailApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanDisbursementDetailApiResource.java
index 7dd270f9ff..060288c66d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanDisbursementDetailApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanDisbursementDetailApiResource.java
@@ -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
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanAccountLockHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanAccountLockHelper.java
index 9967f9560c..90ab4f5805 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanAccountLockHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanAccountLockHelper.java
@@ -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)));
     }
 
 }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index 276713ad53..8a55b88eb0 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -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));
     }

Reply via email to