You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2025/01/08 15:21:40 UTC
(fineract) 01/01: Revert "FINERACT-2152: API update and delete interest pause"
This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch revert-4235-FINERACT-2152/delete_and_update_interest_pause_period
in repository https://gitbox.apache.org/repos/asf/fineract.git
commit f0cad9ece8aee77bbf49a83529813bbf9433dc7a
Author: Adam Saghy <ad...@gmail.com>
AuthorDate: Wed Jan 8 16:21:33 2025 +0100
Revert "FINERACT-2152: API update and delete interest pause"
This reverts commit 8663c054a076ca52e49b8df3987f8da46c929e51.
---
.../fineract/commands/domain/CommandSource.java | 3 +-
.../fineract/commands/domain/CommandWrapper.java | 12 +-
.../commands/service/CommandWrapperBuilder.java | 18 --
.../SynchronousCommandProcessingService.java | 12 +-
.../api/LoanInterestPauseApiResource.java | 42 +--
.../handler/DeleteInterestPauseCommandHandler.java | 41 ---
...ndler.java => InterestPauseCommandHandler.java} | 12 +-
.../handler/UpdateInterestPauseCommandHandler.java | 45 ---
.../service/InterestPauseWritePlatformService.java | 50 ----
.../InterestPauseWritePlatformServiceImpl.java | 91 +-----
.../loanaccount/domain/LoanTermVariations.java | 48 ---
.../domain/LoanTermVariationsRepository.java | 9 -
.../starter/LoanAccountConfiguration.java | 4 +-
.../db/changelog/tenant/changelog-tenant.xml | 1 -
..._additional_audit_fields_to_term_variations.xml | 51 ----
.../integrationtests/LoanInterestPauseApiTest.java | 328 +++++++--------------
.../common/loans/LoanProductTestBuilder.java | 1 -
.../common/loans/LoanTransactionHelper.java | 38 +--
18 files changed, 131 insertions(+), 675 deletions(-)
diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java
index e468e4a17..ad28f696c 100644
--- a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java
+++ b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandSource.java
@@ -159,7 +159,8 @@ public class CommandSource extends AbstractPersistableCustom<Long> {
.transactionId(command.getTransactionId()) //
.creditBureauId(command.getCreditBureauId()) //
.organisationCreditBureauId(command.getOrganisationCreditBureauId()) //
- .loanExternalId(command.getLoanExternalId()).build(); //
+ .loanExternalId(command.getLoanExternalId()) //
+ .build(); //
}
public String getPermissionCode() {
diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandWrapper.java b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandWrapper.java
index fd73b43b9..5b51f40de 100644
--- a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandWrapper.java
+++ b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandWrapper.java
@@ -251,16 +251,8 @@ public class CommandWrapper {
return this.entityName.equalsIgnoreCase("INTEREST_PAUSE");
}
- public boolean isInterestPauseCreateResource() {
- return this.entityName.equalsIgnoreCase("INTEREST_PAUSE") && "CREATE".equalsIgnoreCase(this.actionName);
- }
-
- public boolean isInterestPauseUpdateResource() {
- return this.entityName.equalsIgnoreCase("INTEREST_PAUSE") && "UPDATE".equalsIgnoreCase(this.actionName);
- }
-
- public boolean isInterestPauseDeleteResource() {
- return this.entityName.equalsIgnoreCase("INTEREST_PAUSE") && "DELETE".equalsIgnoreCase(this.actionName);
+ public boolean isInterestPauseExternalIdResource() {
+ return this.entityName.equalsIgnoreCase("INTEREST_PAUSE") && this.href.contains("/external-id/");
}
public Long commandId() {
diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index 740fbbbc6..497862cbf 100644
--- a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -3732,22 +3732,4 @@ public class CommandWrapperBuilder {
this.href = "/v1/loans/external-id/" + loanExternalId + "/interest-pauses";
return this;
}
-
- public CommandWrapperBuilder deleteInterestPause(final long loanId, final long variationId) {
- this.actionName = "DELETE";
- this.entityName = "INTEREST_PAUSE";
- this.loanId = loanId;
- this.entityId = variationId;
- this.href = "/v1/loans/" + loanId + "/interest-pauses/" + variationId;
- return this;
- }
-
- public CommandWrapperBuilder updateInterestPause(final long loanId, final long variationId) {
- this.actionName = "UPDATE";
- this.entityName = "INTEREST_PAUSE";
- this.loanId = loanId;
- this.entityId = variationId;
- this.href = "/v1/loans/" + loanId + "/interest-pauses/" + variationId;
- return this;
- }
}
diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java
index f021cb23c..9b525d5cd 100644
--- a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java
+++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java
@@ -249,16 +249,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
} else {
throw new UnsupportedCommandException(wrapper.commandName());
}
- } else if (wrapper.isInterestPauseResource()) {
- if (wrapper.isInterestPauseCreateResource()) {
- handler = applicationContext.getBean("createInterestPauseCommandHandler", NewCommandSourceHandler.class);
- } else if (wrapper.isInterestPauseUpdateResource()) {
- handler = applicationContext.getBean("updateInterestPauseCommandHandler", NewCommandSourceHandler.class);
- } else if (wrapper.isInterestPauseDeleteResource()) {
- handler = applicationContext.getBean("deleteInterestPauseCommandHandler", NewCommandSourceHandler.class);
- } else {
- throw new UnsupportedCommandException(wrapper.commandName());
- }
+ } else if (wrapper.isInterestPauseResource() || wrapper.isInterestPauseExternalIdResource()) {
+ handler = applicationContext.getBean("interestPauseCommandHandler", NewCommandSourceHandler.class);
} else {
handler = commandHandlerProvider.getHandler(wrapper.entityName(), wrapper.actionName());
}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/api/LoanInterestPauseApiResource.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/api/LoanInterestPauseApiResource.java
index 253727547..1b08ad6d8 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/api/LoanInterestPauseApiResource.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/api/LoanInterestPauseApiResource.java
@@ -25,15 +25,12 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes;
-import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
-import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.commands.domain.CommandWrapper;
@@ -53,7 +50,6 @@ import org.springframework.stereotype.Component;
public class LoanInterestPauseApiResource {
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "LOAN";
- private static final String MODIFY_RESOURCE_NAME_FOR_PERMISSIONS = "UPDATE LOAN";
private final PlatformSecurityContext context;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
@@ -68,7 +64,7 @@ public class LoanInterestPauseApiResource {
public CommandProcessingResult createInterestPause(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
@RequestBody(required = true) final InterestPauseRequestDto request) {
- this.context.authenticatedUser().validateHasReadPermission(MODIFY_RESOURCE_NAME_FOR_PERMISSIONS);
+ this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final CommandWrapper commandRequest = new CommandWrapperBuilder().createInterestPause(loanId).withJson(request.toJson()).build();
@@ -85,7 +81,7 @@ public class LoanInterestPauseApiResource {
@PathParam("loanExternalId") @Parameter(description = "loanExternalId") final String loanExternalId,
@RequestBody(required = true) final InterestPauseRequestDto request) {
- this.context.authenticatedUser().validateHasReadPermission(MODIFY_RESOURCE_NAME_FOR_PERMISSIONS);
+ this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
final CommandWrapper commandRequest = new CommandWrapperBuilder().createInterestPauseByExternalId(loanExternalId)
.withJson(request.toJson()).build();
@@ -118,38 +114,4 @@ public class LoanInterestPauseApiResource {
return this.interestPauseReadPlatformService.retrieveInterestPauses(loanExternalId);
}
-
- @DELETE
- @Path("/{loanId}/interest-pauses/{variationId}")
- @Operation(summary = "Delete an interest pause period", description = "Deletes a specific interest pause period by its variation ID.")
- @ApiResponses({ @ApiResponse(responseCode = "204", description = "No Content") })
- public Response deleteInterestPause(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
- @PathParam("variationId") @Parameter(description = "variationId") final Long variationId) {
-
- this.context.authenticatedUser().validateHasReadPermission(MODIFY_RESOURCE_NAME_FOR_PERMISSIONS);
-
- final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteInterestPause(loanId, variationId).build();
-
- this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
-
- return Response.noContent().build();
- }
-
- @PUT
- @Path("/{loanId}/interest-pauses/{variationId}")
- @Consumes({ MediaType.APPLICATION_JSON })
- @Produces({ MediaType.APPLICATION_JSON })
- @Operation(summary = "Update an interest pause period", description = "Updates a specific interest pause period by its variation ID.")
- @ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
- public CommandProcessingResult updateInterestPause(@PathParam("loanId") @Parameter(description = "loanId") final Long loanId,
- @PathParam("variationId") @Parameter(description = "variationId") final Long variationId,
- @RequestBody(required = true) final InterestPauseRequestDto request) {
-
- this.context.authenticatedUser().validateHasReadPermission(MODIFY_RESOURCE_NAME_FOR_PERMISSIONS);
-
- final CommandWrapper commandRequest = new CommandWrapperBuilder().updateInterestPause(loanId, variationId)
- .withJson(request.toJson()).build();
-
- return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
- }
}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/DeleteInterestPauseCommandHandler.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/DeleteInterestPauseCommandHandler.java
deleted file mode 100644
index 8068c8c5a..000000000
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/DeleteInterestPauseCommandHandler.java
+++ /dev/null
@@ -1,41 +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.portfolio.interestpauses.handler;
-
-import lombok.RequiredArgsConstructor;
-import org.apache.fineract.commands.handler.NewCommandSourceHandler;
-import org.apache.fineract.infrastructure.core.api.JsonCommand;
-import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
-import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformService;
-import org.springframework.stereotype.Component;
-
-@Component("deleteInterestPauseCommandHandler")
-@RequiredArgsConstructor
-public class DeleteInterestPauseCommandHandler implements NewCommandSourceHandler {
-
- private final InterestPauseWritePlatformService interestPauseService;
-
- @Override
- public CommandProcessingResult processCommand(final JsonCommand command) {
- final Long loanId = command.getLoanId();
- final Long termVariationId = command.getResourceId();
-
- return interestPauseService.deleteInterestPause(loanId, termVariationId);
- }
-}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/CreateInterestPauseCommandHandler.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/InterestPauseCommandHandler.java
similarity index 85%
rename from fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/CreateInterestPauseCommandHandler.java
rename to fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/InterestPauseCommandHandler.java
index 6246f278c..5747625dd 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/CreateInterestPauseCommandHandler.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/InterestPauseCommandHandler.java
@@ -27,14 +27,16 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformService;
import org.springframework.stereotype.Component;
-@Component("createInterestPauseCommandHandler")
+@Component("interestPauseCommandHandler")
@RequiredArgsConstructor
-public class CreateInterestPauseCommandHandler implements NewCommandSourceHandler {
+public class InterestPauseCommandHandler implements NewCommandSourceHandler {
private final InterestPauseWritePlatformService interestPauseService;
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
+ CommandProcessingResult result;
+
final String startDate = command.stringValueOfParameterNamed("startDate");
final String endDate = command.stringValueOfParameterNamed("endDate");
final String dateFormat = command.stringValueOfParameterNamed("dateFormat");
@@ -42,13 +44,15 @@ public class CreateInterestPauseCommandHandler implements NewCommandSourceHandle
if (command.getLoanId() != null) {
final Long loanId = command.getLoanId();
- return interestPauseService.createInterestPause(loanId, startDate, endDate, dateFormat, locale);
+ result = interestPauseService.createInterestPause(loanId, startDate, endDate, dateFormat, locale);
} else if (command.getLoanExternalId() != null) {
final ExternalId loanExternalId = command.getLoanExternalId();
- return interestPauseService.createInterestPause(loanExternalId, startDate, endDate, dateFormat, locale);
+ result = interestPauseService.createInterestPause(loanExternalId, startDate, endDate, dateFormat, locale);
} else {
throw new PlatformApiDataValidationException("validation.msg.missing.loan.id.or.external.id",
"Either loanId or loanExternalId must be provided.", "loanId");
}
+
+ return result;
}
}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/UpdateInterestPauseCommandHandler.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/UpdateInterestPauseCommandHandler.java
deleted file mode 100644
index 04a9b2f03..000000000
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/handler/UpdateInterestPauseCommandHandler.java
+++ /dev/null
@@ -1,45 +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.portfolio.interestpauses.handler;
-
-import lombok.RequiredArgsConstructor;
-import org.apache.fineract.commands.handler.NewCommandSourceHandler;
-import org.apache.fineract.infrastructure.core.api.JsonCommand;
-import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
-import org.apache.fineract.portfolio.interestpauses.service.InterestPauseWritePlatformService;
-import org.springframework.stereotype.Component;
-
-@Component("updateInterestPauseCommandHandler")
-@RequiredArgsConstructor
-public class UpdateInterestPauseCommandHandler implements NewCommandSourceHandler {
-
- private final InterestPauseWritePlatformService interestPauseService;
-
- @Override
- public CommandProcessingResult processCommand(final JsonCommand command) {
- final Long loanId = command.getLoanId();
- final Long termVariationId = command.getResourceId();
- final String startDate = command.stringValueOfParameterNamed("startDate");
- final String endDate = command.stringValueOfParameterNamed("endDate");
- final String dateFormat = command.stringValueOfParameterNamed("dateFormat");
- final String locale = command.stringValueOfParameterNamed("locale");
-
- return interestPauseService.updateInterestPause(loanId, termVariationId, startDate, endDate, dateFormat, locale);
- }
-}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformService.java
index 491a45171..e3b8c397a 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformService.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformService.java
@@ -23,21 +23,6 @@ import org.apache.fineract.infrastructure.core.domain.ExternalId;
public interface InterestPauseWritePlatformService {
- /**
- * Create a new interest pause period for a loan identified by its external ID.
- *
- * @param loanExternalId
- * the external ID of the loan
- * @param startDate
- * the start date of the interest pause period (inclusive)
- * @param endDate
- * the end date of the interest pause period (inclusive)
- * @param dateFormat
- * the format of the provided dates
- * @param locale
- * the locale used for date parsing
- * @return the ID of the created loan term variation representing the interest pause
- */
CommandProcessingResult createInterestPause(ExternalId loanExternalId, String startDate, String endDate, String dateFormat,
String locale);
@@ -50,42 +35,7 @@ public interface InterestPauseWritePlatformService {
* the start date of the interest pause period (inclusive)
* @param endDate
* the end date of the interest pause period (inclusive)
- * @param dateFormat
- * the format of the provided dates
- * @param locale
- * the locale used for date parsing
* @return the ID of the created loan term variation representing the interest pause
*/
CommandProcessingResult createInterestPause(Long loanId, String startDate, String endDate, String dateFormat, String locale);
-
- /**
- * Delete an existing interest pause period for a loan.
- *
- * @param loanId
- * the ID of the loan
- * @param variationId
- * the ID of the loan term variation representing the interest pause
- * @return the result of the delete operation
- */
- CommandProcessingResult deleteInterestPause(Long loanId, Long variationId);
-
- /**
- * Update an existing interest pause period for a loan identified by its internal ID.
- *
- * @param loanId
- * the ID of the loan
- * @param variationId
- * the ID of the loan term variation representing the interest pause to be updated
- * @param startDateString
- * the new start date of the interest pause period (inclusive) as a string
- * @param endDateString
- * the new end date of the interest pause period (inclusive) as a string
- * @param dateFormat
- * the format of the provided dates (e.g., "yyyy-MM-dd")
- * @param locale
- * the locale used for parsing the provided dates
- * @return the updated loan term variation ID along with the updated fields
- */
- CommandProcessingResult updateInterestPause(Long loanId, Long variationId, String startDateString, String endDateString,
- String dateFormat, String locale);
}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java
index 095ec4024..272ba3f9f 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java
@@ -18,19 +18,12 @@
*/
package org.apache.fineract.portfolio.interestpauses.service;
-import static org.apache.fineract.portfolio.loanaccount.domain.LoanStatus.ACTIVE;
-import static org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType.INTEREST_PAUSE;
-import static org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType.PROGRESSIVE;
-
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
import lombok.AllArgsConstructor;
@@ -41,13 +34,11 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
-import org.apache.fineract.infrastructure.core.service.DateUtils;
-import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariationType;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
import org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanTermVariationsRepository;
-import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.transaction.annotation.Transactional;
@AllArgsConstructor
@@ -56,7 +47,6 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite
private final LoanTermVariationsRepository loanTermVariationsRepository;
private final LoanRepositoryWrapper loanRepositoryWrapper;
- private final PlatformSecurityContext context;
@Override
public CommandProcessingResult createInterestPause(ExternalId loanExternalId, String startDateString, String endDateString,
@@ -78,59 +68,14 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite
locale);
}
- @Override
- public CommandProcessingResult deleteInterestPause(Long loanId, Long variationId) {
- LoanTermVariations variation = loanTermVariationsRepository
- .findByIdAndLoanIdAndTermType(variationId, loanId, INTEREST_PAUSE.getValue())
- .orElseThrow(() -> new GeneralPlatformDomainRuleException("error.msg.variation.not.found",
- "Variation not found for the given loan ID"));
-
- loanTermVariationsRepository.delete(variation);
-
- return new CommandProcessingResultBuilder().withEntityId(variationId).build();
- }
-
- @Override
- public CommandProcessingResult updateInterestPause(Long loanId, Long variationId, String startDateString, String endDateString,
- String dateFormat, String locale) {
- Loan loan = loanRepositoryWrapper.findOneWithNotFoundDetection(loanId);
-
- LocalDate startDate = parseDate(startDateString, dateFormat, locale);
- LocalDate endDate = parseDate(endDateString, dateFormat, locale);
-
- validateInterestPauseDates(loan, startDate, endDate, dateFormat, locale);
-
- LoanTermVariations variation = loanTermVariationsRepository
- .findByIdAndLoanIdAndTermType(variationId, loanId, INTEREST_PAUSE.getValue())
- .orElseThrow(() -> new GeneralPlatformDomainRuleException("error.msg.variation.not.found",
- "Variation not found for the given loan ID"));
-
- validateVariations(loan, variation);
-
- variation.setTermApplicableFrom(startDate);
- variation.setDateValue(endDate);
-
- AppUser currentUser = context.authenticatedUser();
- variation.setUpdatedBy(currentUser != null ? currentUser.getId() : null);
- variation.setUpdatedOnDate(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
-
- LoanTermVariations updatedVariation = loanTermVariationsRepository.save(variation);
-
- return new CommandProcessingResultBuilder().withEntityId(updatedVariation.getId())
- .with(Map.of("startDate", startDate.toString(), "endDate", endDate.toString())).build();
- }
-
private CommandProcessingResult processInterestPause(Supplier<Loan> loanSupplier, LocalDate startDate, LocalDate endDate,
String dateFormat, String locale) {
final Loan loan = loanSupplier.get();
validateInterestPauseDates(loan, startDate, endDate, dateFormat, locale);
- LoanTermVariations variation = new LoanTermVariations(INTEREST_PAUSE.getValue(), startDate, null, endDate, false, loan);
-
- AppUser currentUser = context.authenticatedUser();
- variation.setCreatedBy(currentUser != null ? currentUser.getId() : null);
- variation.setCreatedOnDate(LocalDateTime.now(DateUtils.getDateTimeZoneOfTenant()));
+ LoanTermVariations variation = new LoanTermVariations(LoanTermVariationType.INTEREST_PAUSE.getValue(), startDate, null, endDate,
+ false, loan);
LoanTermVariations savedVariation = loanTermVariationsRepository.saveAndFlush(variation);
@@ -164,36 +109,6 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite
.format("Interest pause end date (%s) must not be before the interest pause start date (%s).", endDate, startDate),
endDate, startDate);
}
-
- if (!Objects.equals(loan.getLoanStatus(), ACTIVE.getValue())) {
- throw new GeneralPlatformDomainRuleException("loan.must.be.active",
- "Operations on interest pauses are restricted to active loans.");
- }
-
- if (!PROGRESSIVE.equals(loan.getLoanRepaymentScheduleDetail().getLoanScheduleType())) {
- throw new GeneralPlatformDomainRuleException("loan.must.be.progressive",
- "Interest pause is only supported for progressive loans.");
- }
-
- if (!loan.getLoanRepaymentScheduleDetail().isInterestRecalculationEnabled()) {
- throw new GeneralPlatformDomainRuleException("loan.must.have.recalculate.interest.enabled",
- "Interest pause is only supported for loans with recalculate interest enabled.");
- }
- }
-
- private void validateVariations(Loan loan, LoanTermVariations variation) {
- if (variation == null) {
- throw new GeneralPlatformDomainRuleException("interest.pause.not.found",
- "The specified interest pause does not exist for the given loan.");
- }
-
- List<LoanTermVariations> existingVariations = loan.getLoanTermVariations();
- for (LoanTermVariations existingVariation : existingVariations) {
- if (!existingVariation.equals(variation) && variation.getTermApplicableFrom().isBefore(existingVariation.getDateValue())
- && variation.getDateValue().isAfter(existingVariation.getTermApplicableFrom())) {
- throw new GeneralPlatformDomainRuleException("interest.pause.overlapping", "Overlapping interest pauses are not allowed.");
- }
- }
}
private LocalDate parseDate(String date, String dateFormat, String locale) {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariations.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariations.java
index 891dde0e2..d5f41828d 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariations.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTermVariations.java
@@ -27,7 +27,6 @@ import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
@@ -62,18 +61,6 @@ public class LoanTermVariations extends AbstractPersistableCustom<Long> {
@Column(name = "is_active", nullable = false)
private Boolean isActive;
- @Column(name = "created_by")
- private Long createdBy;
-
- @Column(name = "created_on_date")
- private LocalDateTime createdOnDate;
-
- @Column(name = "updated_by")
- private Long updatedBy;
-
- @Column(name = "updated_on_date")
- private LocalDateTime updatedOnDate;
-
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private LoanTermVariations parent;
@@ -152,10 +139,6 @@ public class LoanTermVariations extends AbstractPersistableCustom<Long> {
return this.dateValue;
}
- public void setDateValue(LocalDate dateValue) {
- this.dateValue = dateValue;
- }
-
public void setTermApplicableFrom(LocalDate termApplicableFrom) {
this.termApplicableFrom = termApplicableFrom;
}
@@ -184,35 +167,4 @@ public class LoanTermVariations extends AbstractPersistableCustom<Long> {
this.isActive = false;
}
- public Long getCreatedBy() {
- return createdBy;
- }
-
- public void setCreatedBy(Long createdBy) {
- this.createdBy = createdBy;
- }
-
- public LocalDateTime getCreatedOnDate() {
- return createdOnDate;
- }
-
- public void setCreatedOnDate(LocalDateTime createdOnDate) {
- this.createdOnDate = createdOnDate;
- }
-
- public Long getUpdatedBy() {
- return updatedBy;
- }
-
- public void setUpdatedBy(Long updatedBy) {
- this.updatedBy = updatedBy;
- }
-
- public LocalDateTime getUpdatedOnDate() {
- return updatedOnDate;
- }
-
- public void setUpdatedOnDate(LocalDateTime updatedOnDate) {
- this.updatedOnDate = updatedOnDate;
- }
}
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanTermVariationsRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanTermVariationsRepository.java
index 57993fe05..0bf7209ff 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanTermVariationsRepository.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/domain/LoanTermVariationsRepository.java
@@ -19,7 +19,6 @@
package org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain;
import java.util.List;
-import java.util.Optional;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.portfolio.loanaccount.data.LoanTermVariationsData;
import org.apache.fineract.portfolio.loanaccount.domain.LoanTermVariations;
@@ -61,12 +60,4 @@ public interface LoanTermVariationsRepository
""")
List<LoanTermVariationsData> findLoanTermVariationsByExternalLoanIdAndTermType(@Param("loanExternalId") ExternalId loanExternalId,
@Param("termType") int termType);
-
- @Query("""
- select ltv
- from LoanTermVariations ltv
- where ltv.id = :variationId and ltv.loan.id = :loanId and ltv.termType = :termType
- """)
- Optional<LoanTermVariations> findByIdAndLoanIdAndTermType(@Param("variationId") long variationId, @Param("loanId") long loanId,
- @Param("termType") int termType);
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
index a1a1fddbb..b7b9a955d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java
@@ -471,7 +471,7 @@ public class LoanAccountConfiguration {
@Bean
@ConditionalOnMissingBean(InterestPauseWritePlatformService.class)
public InterestPauseWritePlatformService interestPauseWritePlatformService(LoanTermVariationsRepository loanTermVariationsRepository,
- LoanRepositoryWrapper loanRepositoryWrapper, PlatformSecurityContext context) {
- return new InterestPauseWritePlatformServiceImpl(loanTermVariationsRepository, loanRepositoryWrapper, context);
+ LoanRepositoryWrapper loanRepositoryWrapper) {
+ return new InterestPauseWritePlatformServiceImpl(loanTermVariationsRepository, loanRepositoryWrapper);
}
}
diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
index b058f2a2a..673a92f1f 100644
--- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
+++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml
@@ -180,5 +180,4 @@
<include file="parts/0159_trial_balance_summary_with_asset_owner_year_end_summary.xml" relativeToChangelogFile="true" />
<include file="parts/0160_add_acc_product_mapping_product_id_index.xml" relativeToChangelogFile="true" />
<include file="parts/0161_add_loan_external_id_to_commands.xml" relativeToChangelogFile="true" />
- <include file="parts/0162_add_additional_audit_fields_to_term_variations.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0162_add_additional_audit_fields_to_term_variations.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0162_add_additional_audit_fields_to_term_variations.xml
deleted file mode 100644
index fbb1ef2bf..000000000
--- a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0162_add_additional_audit_fields_to_term_variations.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
-
- <changeSet id="1" author="fineract">
- <addColumn tableName="m_loan_term_variations">
- <column name="created_by" type="BIGINT">
- <constraints nullable="true"/>
- </column>
- </addColumn>
-
- <addColumn tableName="m_loan_term_variations">
- <column name="created_on_date" type="TIMESTAMP">
- <constraints nullable="true"/>
- </column>
- </addColumn>
-
- <addColumn tableName="m_loan_term_variations">
- <column name="updated_by" type="BIGINT">
- <constraints nullable="true"/>
- </column>
- </addColumn>
-
- <addColumn tableName="m_loan_term_variations">
- <column name="updated_on_date" type="TIMESTAMP">
- <constraints nullable="true"/>
- </column>
- </addColumn>
- </changeSet>
-</databaseChangeLog>
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestPauseApiTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestPauseApiTest.java
index d4f5d0dc0..347b72f23 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestPauseApiTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanInterestPauseApiTest.java
@@ -24,30 +24,38 @@ import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.AdvancedPaymentData;
-import org.apache.fineract.client.models.PostLoansLoanIdRequest;
+import org.apache.fineract.client.models.PaymentAllocationOrder;
+import org.apache.fineract.client.models.PostClientsResponse;
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.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
-import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleProcessingType;
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
+import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Slf4j
-@ExtendWith(LoanTestLifecycleExtension.class)
+@ExtendWith({ LoanTestLifecycleExtension.class })
public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(LoanInterestPauseApiTest.class);
@@ -55,56 +63,52 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
private static RequestSpecification REQUEST_SPEC;
private static ResponseSpecification RESPONSE_SPEC;
private static ResponseSpecification RESPONSE_SPEC_403;
- private static ResponseSpecification RESPONSE_SPEC_204;
private static LoanTransactionHelper LOAN_TRANSACTIONAL_HELPER;
- private static LoanTransactionHelper LOAN_TRANSACTIONAL_HELPER_204;
private static LoanTransactionHelper LOAN_TRANSACTION_HELPER_403;
- private static AccountHelper ACCOUNT_HELPER;
- private static final Integer nonExistLoanId = 99999;
+ private static AccountHelper accountHelper;
+ private static PostClientsResponse client;
+ private static Integer loanProductId;
+ private static Long loanId;
+ private static Long nonExistLoanId = 99999L;
private static String externalId;
- private static final String nonExistExternalId = "7c4fb86f-a778-4d02-b7a8-ec3ec98941fa";
- private Integer clientId;
- private Integer loanProductId;
- private Integer loanId;
- private final String loanPrincipalAmount = "10000.00";
- private final String numberOfRepayments = "12";
- private final String interestRatePerPeriod = "18";
- private final String dateString = "01 January 2023";
-
- @BeforeEach
- public void initialize() {
+ private static String nonExistExternalId = "7c4fb86f-a778-4d02-b7a8-ec3ec98941fa";
+
+ @BeforeAll
+ public static void setupTests() {
Utils.initializeRESTAssured();
REQUEST_SPEC = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
REQUEST_SPEC.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
RESPONSE_SPEC = new ResponseSpecBuilder().expectStatusCode(200).build();
RESPONSE_SPEC_403 = new ResponseSpecBuilder().expectStatusCode(403).build();
- RESPONSE_SPEC_204 = new ResponseSpecBuilder().expectStatusCode(204).build();
LOAN_TRANSACTIONAL_HELPER = new LoanTransactionHelper(REQUEST_SPEC, RESPONSE_SPEC);
LOAN_TRANSACTION_HELPER_403 = new LoanTransactionHelper(REQUEST_SPEC, RESPONSE_SPEC_403);
- LOAN_TRANSACTIONAL_HELPER_204 = new LoanTransactionHelper(REQUEST_SPEC, RESPONSE_SPEC_204);
- ACCOUNT_HELPER = new AccountHelper(REQUEST_SPEC, RESPONSE_SPEC);
+ accountHelper = new AccountHelper(REQUEST_SPEC, RESPONSE_SPEC);
+ ClientHelper clientHelper = new ClientHelper(REQUEST_SPEC, RESPONSE_SPEC);
+ client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
+
+ final Account assetAccount = accountHelper.createAssetAccount();
+ final Account incomeAccount = accountHelper.createIncomeAccount();
+ final Account expenseAccount = accountHelper.createExpenseAccount();
+ final Account overpaymentAccount = accountHelper.createLiabilityAccount();
externalId = UUID.randomUUID().toString();
- createRequiredEntities();
+ loanProductId = createLoanProduct("500", "15", "4", true, "25", true, LoanScheduleType.PROGRESSIVE,
+ LoanScheduleProcessingType.HORIZONTAL, assetAccount, incomeAccount, expenseAccount, overpaymentAccount);
+
+ final PostLoansResponse loanResponse = applyForLoanApplication(client.getClientId(), loanProductId, BigDecimal.valueOf(500.0), 45,
+ 15, 3, BigDecimal.ZERO, "01 January 2023", "01 January 2023", externalId);
+
+ loanId = loanResponse.getLoanId();
Assertions.assertNotNull(loanProductId, "Loan Product ID should not be null after creation");
Assertions.assertNotNull(loanId, "Loan ID should not be null after creation");
Assertions.assertNotNull(externalId, "External Loan ID should not be null after creation");
}
- /**
- * Creates the client, loan product, and loan entities
- **/
- private void createRequiredEntities() {
- this.createClientEntity();
- this.createLoanProductEntity();
- this.createLoanEntity();
- }
-
@Test
public void testCreateInterestPauseByLoanId_validRequest_shouldSucceed() {
- PostLoansLoanIdTransactionsResponse response = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01", "2023-01-12",
+ PostLoansLoanIdTransactionsResponse response = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01", "2023-02-05",
"yyyy-MM-dd", "en", loanId);
Assertions.assertNotNull(response);
@@ -114,7 +118,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testCreateInterestPauseByLoanId_endDateBeforeStartDate_shouldFail() {
try {
- LOAN_TRANSACTION_HELPER_403.createInterestPauseByLoanId("2024-12-05", "2023-01-12", "yyyy-MM-dd", "en", loanId);
+ LOAN_TRANSACTION_HELPER_403.createInterestPauseByLoanId("2024-12-05", "2024-12-01", "yyyy-MM-dd", "en", loanId);
} catch (Exception e) {
String responseBody = e.getMessage();
Assertions.assertNotNull(responseBody, "Response body should not be null");
@@ -126,7 +130,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testCreateInterestPauseByLoanId_startDateBeforeLoanStart_shouldFail() {
try {
- LOAN_TRANSACTION_HELPER_403.createInterestPauseByLoanId("2022-12-01", "2023-01-12", "yyyy-MM-dd", "en", loanId);
+ LOAN_TRANSACTION_HELPER_403.createInterestPauseByLoanId("2022-12-01", "2024-12-05", "yyyy-MM-dd", "en", loanId);
} catch (Exception e) {
String responseBody = e.getMessage();
Assertions.assertNotNull(responseBody, "Response body should not be null");
@@ -159,18 +163,18 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testRetrieveInterestPausesByLoanId_shouldReturnData() {
- LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01", "2023-01-12", "yyyy-MM-dd", "en", loanId);
+ LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01", "2023-02-05", "yyyy-MM-dd", "en", loanId);
String response = LOAN_TRANSACTIONAL_HELPER.retrieveInterestPauseByLoanId(loanId);
Assertions.assertNotNull(response, "Response should not be null");
Assertions.assertTrue(response.contains("2023-01-01"));
- Assertions.assertTrue(response.contains("2023-01-12"));
+ Assertions.assertTrue(response.contains("2023-02-05"));
}
@Test
public void testCreateInterestPauseByExternalLoanId_validRequest_shouldSucceed() {
- PostLoansLoanIdTransactionsResponse response = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByExternalId("2023-01-01", "2023-01-12",
+ PostLoansLoanIdTransactionsResponse response = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByExternalId("2023-01-01", "2023-02-05",
"yyyy-MM-dd", "en", externalId);
Assertions.assertNotNull(response);
@@ -180,7 +184,7 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testCreateInterestPauseByExternalLoanId_endDateBeforeStartDate_shouldFail() {
try {
- LOAN_TRANSACTION_HELPER_403.createInterestPauseByExternalId("2023-01-01", "2022-01-12", "yyyy-MM-dd", "en", externalId);
+ LOAN_TRANSACTION_HELPER_403.createInterestPauseByExternalId("2024-12-05", "2024-12-01", "yyyy-MM-dd", "en", externalId);
} catch (Exception e) {
String responseBody = e.getMessage();
Assertions.assertNotNull(responseBody, "Response body should not be null");
@@ -225,207 +229,87 @@ public class LoanInterestPauseApiTest extends BaseLoanIntegrationTest {
@Test
public void testRetrieveInterestPausesByExternalLoanId_shouldReturnData() {
- LOAN_TRANSACTIONAL_HELPER.createInterestPauseByExternalId("2023-01-01", "2023-01-12", "yyyy-MM-dd", "en", externalId);
+ LOAN_TRANSACTIONAL_HELPER.createInterestPauseByExternalId("2023-01-01", "2023-02-05", "yyyy-MM-dd", "en", externalId);
String response = LOAN_TRANSACTIONAL_HELPER.retrieveInterestPauseByExternalId(externalId);
Assertions.assertNotNull(response, "Response should not be null");
Assertions.assertTrue(response.contains("2023-01-01"));
- Assertions.assertTrue(response.contains("2023-01-12"));
- }
-
- @Test
- public void testUpdateInterestPauseByLoanId_validRequest_shouldSucceed() {
- PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01",
- "2023-01-12", "yyyy-MM-dd", "en", loanId);
-
- Assertions.assertNotNull(createResponse);
- Assertions.assertNotNull(createResponse.getResourceId());
-
- Long variationId = createResponse.getResourceId();
-
- PostLoansLoanIdTransactionsResponse updateResponse = LOAN_TRANSACTIONAL_HELPER.updateInterestPauseByLoanId(variationId,
- "2023-01-01", "2023-01-12", "yyyy-MM-dd", "en", loanId);
-
- Assertions.assertNotNull(updateResponse);
- Assertions.assertNotNull(updateResponse.getResourceId());
- Assertions.assertEquals(variationId, updateResponse.getResourceId());
- }
-
- @Test
- public void testUpdateInterestPauseByLoanId_endDateBeforeStartDate_shouldFail() {
- PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01",
- "2023-01-12", "yyyy-MM-dd", "en", loanId);
-
- Assertions.assertNotNull(createResponse);
- Assertions.assertNotNull(createResponse.getResourceId());
-
- Long variationId = createResponse.getResourceId();
-
- try {
- LOAN_TRANSACTION_HELPER_403.updateInterestPauseByLoanId(variationId, "2023-03-01", "2023-01-12", "yyyy-MM-dd", "en", loanId);
- } catch (Exception e) {
- String responseBody = e.getMessage();
- Assertions.assertNotNull(responseBody, "Response body should not be null");
- Assertions.assertTrue(responseBody.contains("interest.pause.end.date.before.start.date"),
- "Response should contain the validation error message for end date before start date");
- }
- }
-
- @Test
- public void testUpdateInterestPauseByLoanId_startDateBeforeLoanStart_shouldFail() {
- PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01",
- "2023-01-12", "yyyy-MM-dd", "en", loanId);
-
- Assertions.assertNotNull(createResponse);
- Assertions.assertNotNull(createResponse.getResourceId());
-
- Long variationId = createResponse.getResourceId();
-
- try {
- LOAN_TRANSACTION_HELPER_403.updateInterestPauseByLoanId(variationId, "2022-12-01", "2023-01-12", "yyyy-MM-dd", "en", loanId);
- } catch (Exception e) {
- String responseBody = e.getMessage();
- Assertions.assertNotNull(responseBody, "Response body should not be null");
- Assertions.assertTrue(responseBody.contains("interest.pause.start.date.before.loan.start.date"),
- "Response should contain the validation error message for start date before loan start date");
- }
+ Assertions.assertTrue(response.contains("2023-02-05"));
}
- @Test
- public void testDeleteInterestPauseByLoanId_validRequest_shouldSucceed() {
- PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01",
- "2023-01-12", "yyyy-MM-dd", "en", loanId);
-
- Assertions.assertNotNull(createResponse, "Create response should not be null");
- Assertions.assertNotNull(createResponse.getResourceId(), "Resource ID should not be null");
-
- Long variationId = createResponse.getResourceId();
-
- try {
- LOAN_TRANSACTIONAL_HELPER_204.deleteInterestPauseByLoanId(variationId, loanId);
- } catch (Exception e) {
- Assertions.fail("Delete operation failed: " + e.getMessage());
- }
-
- String response = LOAN_TRANSACTIONAL_HELPER.retrieveInterestPauseByLoanId(loanId);
- Assertions.assertFalse(response.contains(String.valueOf(variationId)), "Response should not contain the deleted variation ID");
+ private static Integer createLoanProduct(final String principal, final String repaymentAfterEvery, final String numberOfRepayments,
+ boolean downPaymentEnabled, String downPaymentPercentage, boolean autoPayForDownPayment, LoanScheduleType loanScheduleType,
+ LoanScheduleProcessingType loanScheduleProcessingType, final Account... accounts) {
+ AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation();
+ final String loanProductJSON = new LoanProductTestBuilder().withMinPrincipal(principal).withPrincipal(principal)
+ .withRepaymentTypeAsDays().withRepaymentAfterEvery(repaymentAfterEvery).withNumberOfRepayments(numberOfRepayments)
+ .withEnableDownPayment(downPaymentEnabled, downPaymentPercentage, autoPayForDownPayment).withinterestRatePerPeriod("0")
+ .withInterestRateFrequencyTypeAsMonths()
+ .withRepaymentStrategy(AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
+ .withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts)
+ .addAdvancedPaymentAllocation(defaultAllocation).withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
+ .withInterestTypeAsDecliningBalance().withMultiDisburse().withDisallowExpectedDisbursements(true)
+ .withLoanScheduleType(loanScheduleType).withLoanScheduleProcessingType(loanScheduleProcessingType).withDaysInMonth("30")
+ .withDaysInYear("365").withMoratorium("0", "0").build(null);
+ return LOAN_TRANSACTIONAL_HELPER.getLoanProductId(loanProductJSON);
}
- @Test
- public void testDeleteInterestPauseByLoanId_nonExistentVariation_shouldFail() {
- try {
- LOAN_TRANSACTION_HELPER_403.deleteInterestPauseByLoanId(99999L, loanId);
- } catch (Exception e) {
- String responseBody = e.getMessage();
- Assertions.assertNotNull(responseBody, "Response body should not be null");
- Assertions.assertTrue(responseBody.contains("error.msg.variation.not.found"),
- "Response should contain the validation error message for variation not found");
- }
- }
+ private static AdvancedPaymentData createDefaultPaymentAllocation() {
+ AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
+ advancedPaymentData.setTransactionType("DEFAULT");
+ advancedPaymentData.setFutureInstallmentAllocationRule("NEXT_INSTALLMENT");
- @Test
- public void testDeleteInterestPauseByLoanId_invalidLoanId_shouldFail() {
- PostLoansLoanIdTransactionsResponse createResponse = LOAN_TRANSACTIONAL_HELPER.createInterestPauseByLoanId("2023-01-01",
- "2023-01-12", "yyyy-MM-dd", "en", loanId);
+ List<PaymentAllocationOrder> paymentAllocationOrders = getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
+ PaymentAllocationType.PAST_DUE_FEE, PaymentAllocationType.PAST_DUE_PRINCIPAL, PaymentAllocationType.PAST_DUE_INTEREST,
+ PaymentAllocationType.DUE_PENALTY, PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
+ PaymentAllocationType.DUE_INTEREST, PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
+ PaymentAllocationType.IN_ADVANCE_PRINCIPAL, PaymentAllocationType.IN_ADVANCE_INTEREST);
- Assertions.assertNotNull(createResponse);
- Assertions.assertNotNull(createResponse.getResourceId());
-
- Long variationId = createResponse.getResourceId();
-
- try {
- LOAN_TRANSACTION_HELPER_403.deleteInterestPauseByLoanId(variationId, nonExistLoanId);
- } catch (Exception e) {
- String responseBody = e.getMessage();
- Assertions.assertNotNull(responseBody, "Response body should not be null");
- Assertions.assertTrue(responseBody.contains("error.msg.variation.not.found"),
- "Response should contain the validation error message for variation not found");
- }
- }
-
- /**
- * create a new client
- **/
- private void createClientEntity() {
- this.clientId = ClientHelper.createClient(REQUEST_SPEC, RESPONSE_SPEC);
-
- ClientHelper.verifyClientCreatedOnServer(REQUEST_SPEC, RESPONSE_SPEC, clientId);
+ advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
+ return advancedPaymentData;
}
- /**
- * create a new loan product
- **/
- private void createLoanProductEntity() {
- LOG.info("---------------------------------CREATING LOAN PRODUCT------------------------------------------");
-
- final String interestRecalculationCompoundingMethod = LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE;
- final String rescheduleStrategyMethod = LoanProductTestBuilder.RECALCULATION_STRATEGY_ADJUST_LAST_UNPAID_PERIOD;
- final String preCloseInterestCalculationStrategy = LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE;
-
- final Account assetAccount = ACCOUNT_HELPER.createAssetAccount();
- final Account incomeAccount = ACCOUNT_HELPER.createIncomeAccount();
- final Account expenseAccount = ACCOUNT_HELPER.createExpenseAccount();
- final Account overpaymentAccount = ACCOUNT_HELPER.createLiabilityAccount();
-
- String futureInstallmentAllocationRule = "NEXT_INSTALLMENT";
- AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation(futureInstallmentAllocationRule);
- String loanProductJSON = new LoanProductTestBuilder().withPrincipal(loanPrincipalAmount).withNumberOfRepayments(numberOfRepayments)
- .withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod(interestRatePerPeriod)
- .withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestTypeAsDecliningBalance()
- .withAccountingRulePeriodicAccrual(new Account[] { assetAccount, incomeAccount, expenseAccount, overpaymentAccount })
- .withInterestCalculationPeriodTypeAsRepaymentPeriod(true).addAdvancedPaymentAllocation(defaultAllocation)
- .withLoanScheduleType(LoanScheduleType.PROGRESSIVE).withLoanScheduleProcessingType(LoanScheduleProcessingType.HORIZONTAL)
- .withMultiDisburse().withDisallowExpectedDisbursements(true).withInterestRecalculationDetails(
- interestRecalculationCompoundingMethod, rescheduleStrategyMethod, preCloseInterestCalculationStrategy)
- .build();
-
- loanProductId = LOAN_TRANSACTIONAL_HELPER.getLoanProductId(loanProductJSON);
- LOG.info("Successfully created loan product (ID:{}) ", loanProductId);
+ private static List<PaymentAllocationOrder> getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
+ AtomicInteger integer = new AtomicInteger(1);
+ return Arrays.stream(paymentAllocationTypes).map(pat -> {
+ PaymentAllocationOrder paymentAllocationOrder = new PaymentAllocationOrder();
+ paymentAllocationOrder.setPaymentAllocationRule(pat.name());
+ paymentAllocationOrder.setOrder(integer.getAndIncrement());
+ return paymentAllocationOrder;
+ }).collect(Collectors.toList());
}
- /**
- * submit a new loan application, approve and disburse the loan
- **/
- private void createLoanEntity() {
- LOG.info("---------------------------------NEW LOAN APPLICATION------------------------------------------");
-
- String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
- .withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsDays().withNumberOfRepayments(numberOfRepayments)
- .withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsDays().withInterestRatePerPeriod(interestRatePerPeriod)
- .withInterestTypeAsFlatBalance().withAmortizationTypeAsEqualPrincipalPayments()
- .withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withExpectedDisbursementDate(dateString)
- .withSubmittedOnDate(dateString).withLoanType("individual").withExternalId(externalId)
- .withRepaymentStrategy("advanced-payment-allocation-strategy").build(clientId.toString(), loanProductId.toString(), null);
-
- loanId = LOAN_TRANSACTIONAL_HELPER.getLoanId(loanApplicationJSON);
-
- LOG.info("Sucessfully created loan (ID: {} )", loanId);
-
- approveLoanApplication();
- disburseLoan();
+ private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
+ final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
+ final String expectedDisbursementDate, final String submittedOnDate, final String externalId) {
+ return applyForLoanApplication(clientId, loanProductId, principal, loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
+ interestRate, expectedDisbursementDate, submittedOnDate, LoanScheduleProcessingType.HORIZONTAL, externalId);
}
- /**
- * approve the loan application
- **/
- private void approveLoanApplication() {
-
- if (loanId != null) {
- LOAN_TRANSACTIONAL_HELPER.approveLoan(dateString, loanId);
- LOG.info("Successfully approved loan (ID: {} )", loanId);
- }
+ private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
+ final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
+ final String expectedDisbursementDate, final String submittedOnDate, LoanScheduleProcessingType loanScheduleProcessingType,
+ final String externalId) {
+ LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+ return applyForLoanApplication(clientId, loanProductId, principal, loanTermFrequency, repaymentAfterEvery, numberOfRepayments,
+ interestRate, expectedDisbursementDate, submittedOnDate,
+ AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY, loanScheduleProcessingType.name(),
+ externalId);
}
- /**
- * disburse the newly created loan
- **/
- private void disburseLoan() {
-
- if (loanId != null) {
- LOAN_TRANSACTIONAL_HELPER.disburseLoan(externalId, new PostLoansLoanIdRequest().actualDisbursementDate(dateString)
- .transactionAmount(new BigDecimal(loanPrincipalAmount)).locale("en").dateFormat("dd MMMM yyyy"));
- LOG.info("Successfully disbursed loan (ID: {} )", loanId);
- }
+ private static PostLoansResponse applyForLoanApplication(final Long clientId, final Integer loanProductId, final BigDecimal principal,
+ final int loanTermFrequency, final int repaymentAfterEvery, final int numberOfRepayments, final BigDecimal interestRate,
+ final String expectedDisbursementDate, final String submittedOnDate, String transactionProcessorCode,
+ String loanScheduleProcessingType, final String externalId) {
+ LOG.info("--------------------------------APPLYING FOR LOAN APPLICATION--------------------------------");
+ return LOAN_TRANSACTIONAL_HELPER.applyLoan(new PostLoansRequest().clientId(clientId).productId(loanProductId.longValue())
+ .expectedDisbursementDate(expectedDisbursementDate).dateFormat(DATETIME_PATTERN)
+ .transactionProcessingStrategyCode(transactionProcessorCode).locale("en").submittedOnDate(submittedOnDate)
+ .amortizationType(1).interestRatePerPeriod(interestRate).interestCalculationPeriodType(1).interestType(0)
+ .repaymentFrequencyType(0).repaymentEvery(repaymentAfterEvery).repaymentFrequencyType(0)
+ .numberOfRepayments(numberOfRepayments).loanTermFrequency(loanTermFrequency).loanTermFrequencyType(0).principal(principal)
+ .loanType("individual").loanScheduleProcessingType(loanScheduleProcessingType).externalId(externalId)
+ .maxOutstandingLoanBalance(BigDecimal.valueOf(35000)));
}
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index 507d789fe..40116b9ae 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -66,7 +66,6 @@ public class LoanProductTestBuilder {
public static final String RECALCULATION_STRATEGY_RESCHEDULE_NEXT_REPAYMENTS = "1";
public static final String RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS = "2";
public static final String RECALCULATION_STRATEGY_REDUCE_EMI_AMOUN = "3";
- public static final String RECALCULATION_STRATEGY_ADJUST_LAST_UNPAID_PERIOD = "4";
public static final String RECALCULATION_COMPOUNDING_METHOD_NONE = "0";
public static final String RECALCULATION_COMPOUNDING_METHOD_INTEREST = "1";
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 52e222d65..8785ec626 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
@@ -609,7 +609,7 @@ public class LoanTransactionHelper extends IntegrationTest {
}
public PostLoansLoanIdTransactionsResponse createInterestPauseByLoanId(final String startDate, final String endDate,
- final String dateFormat, final String locale, final Integer loanID) {
+ final String dateFormat, final String locale, final Long loanID) {
log.info("Creating interest pause for Loan {} from {} to {} with dateFormat {} and locale {}", loanID, startDate, endDate,
dateFormat, locale);
String body = getInterestPauseBodyAsJSON(startDate, endDate, dateFormat, locale);
@@ -624,20 +624,7 @@ public class LoanTransactionHelper extends IntegrationTest {
return postLoanTransaction(createInterestPause(INTEREST_PAUSE_COMMAND, externalId), body);
}
- public PostLoansLoanIdTransactionsResponse updateInterestPauseByLoanId(final Long termVariationId, final String startDate,
- final String endDate, final String dateFormat, final String locale, final Integer loanID) {
- log.info("Updating interest pause for Loan {} with Term Variation ID {}: startDate={} endDate={} dateFormat={} locale={}", loanID,
- termVariationId, startDate, endDate, dateFormat, locale);
- String body = getInterestPauseBodyAsJSON(startDate, endDate, dateFormat, locale);
- return putLoanTransaction(updateInterestPause(termVariationId, loanID), body);
- }
-
- public void deleteInterestPauseByLoanId(final Long termVariationId, final Integer loanID) {
- log.info("Deleting interest pause for Loan ID {} with Term Variation ID {}", loanID, termVariationId);
- deleteLoanTransaction(deleteInterestPause(termVariationId, loanID));
- }
-
- public String retrieveInterestPauseByLoanId(final Integer loanID) {
+ public String retrieveInterestPauseByLoanId(final Long loanID) {
log.info("Retrieving interest pauses for Loan ID {}", loanID);
String url = retrieveInterestPause(loanID);
return Utils.performServerGet(requestSpec, responseSpec, url);
@@ -1463,7 +1450,7 @@ public class LoanTransactionHelper extends IntegrationTest {
return "/fineract-provider/api/v1/loans/" + loanID + "/transactions?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
}
- private String createInterestPause(final String command, final Integer loanID) {
+ private String createInterestPause(final String command, final Long loanID) {
return "/fineract-provider/api/v1/loans/" + loanID + "/interest-pauses?command=" + command + "&" + Utils.TENANT_IDENTIFIER;
}
@@ -1472,7 +1459,7 @@ public class LoanTransactionHelper extends IntegrationTest {
+ Utils.TENANT_IDENTIFIER;
}
- private String retrieveInterestPause(final Integer loanID) {
+ private String retrieveInterestPause(final Long loanID) {
return "/fineract-provider/api/v1/loans/" + loanID + "/interest-pauses?" + Utils.TENANT_IDENTIFIER;
}
@@ -1480,14 +1467,6 @@ public class LoanTransactionHelper extends IntegrationTest {
return "/fineract-provider/api/v1/loans/external-id/" + externalId + "/interest-pauses?" + Utils.TENANT_IDENTIFIER;
}
- private String updateInterestPause(final Long termVariationId, final Integer loanID) {
- return "/fineract-provider/api/v1/loans/" + loanID + "/interest-pauses/" + termVariationId + "?" + Utils.TENANT_IDENTIFIER;
- }
-
- private String deleteInterestPause(final Long termVariationId, final Integer loanID) {
- return "/fineract-provider/api/v1/loans/" + loanID + "/interest-pauses/" + termVariationId + "?" + Utils.TENANT_IDENTIFIER;
- }
-
private String createInteroperationLoanTransactionURL(final String accountNo) {
return "/fineract-provider/api/v1/interoperation/transactions/" + accountNo + "/loanrepayment";
}
@@ -1534,15 +1513,6 @@ public class LoanTransactionHelper extends IntegrationTest {
return GSON.fromJson(response, PostLoansLoanIdTransactionsResponse.class);
}
- private PostLoansLoanIdTransactionsResponse putLoanTransaction(final String putURLForLoanTransaction, final String jsonToBeSent) {
- final String response = Utils.performServerPut(this.requestSpec, this.responseSpec, putURLForLoanTransaction, jsonToBeSent);
- return GSON.fromJson(response, PostLoansLoanIdTransactionsResponse.class);
- }
-
- private void deleteLoanTransaction(final String deleteURLForLoanTransaction) {
- Utils.performServerDelete(this.requestSpec, this.responseSpec, deleteURLForLoanTransaction, null);
- }
-
private Object performLoanTransaction(final String postURLForLoanTransaction, final String jsonToBeSent,
ResponseSpecification responseValidationError) {