This is an automated email from the ASF dual-hosted git repository.
arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 1899b517b FINERACT-1724: Batch API support for Loan chargeback and
fineract client adjustments
1899b517b is described below
commit 1899b517b4d48db58745678bd385faf4f853649f
Author: Arnold Galovics <[email protected]>
AuthorDate: Wed Nov 23 15:51:34 2022 +0100
FINERACT-1724: Batch API support for Loan chargeback and fineract client
adjustments
---
.../batch/command/CommandStrategyProvider.java | 2 +-
.../internal/AdjustTransactionCommandStrategy.java | 10 ++-
.../loanaccount/api/LoansApiResourceSwagger.java | 4 ++
.../api/LoanProductsApiResourceSwagger.java | 4 ++
.../batch/command/CommandStrategyProviderTest.java | 2 +
.../AdjustTransactionCommandStrategyTest.java | 40 +++++++++++-
.../fineract/integrationtests/BatchApiTest.java | 71 ++++++++++++++++++++++
.../integrationtests/common/BatchHelper.java | 37 +++++++++++
8 files changed, 165 insertions(+), 5 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/batch/command/CommandStrategyProvider.java
b/fineract-provider/src/main/java/org/apache/fineract/batch/command/CommandStrategyProvider.java
index 42ff0c5ae..cf52777b8 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/batch/command/CommandStrategyProvider.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/batch/command/CommandStrategyProvider.java
@@ -94,7 +94,7 @@ public class CommandStrategyProvider {
"getChargeByIdCommandStrategy");
commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/transactions\\?(\\w+(\\=[\\w]+))").method("POST").build(),
"createTransactionLoanCommandStrategy");
-
commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/transactions\\/\\d+").method("POST").build(),
+
commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/transactions\\/\\d+(\\?command=[\\w]+)?").method("POST").build(),
"adjustTransactionCommandStrategy");
commandStrategies.put(CommandContext.resource("clients\\/\\d+\\?command=activate").method("POST").build(),
"activateClientCommandStrategy");
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategy.java
b/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategy.java
index d5341d191..038a9064a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategy.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategy.java
@@ -59,7 +59,15 @@ public class AdjustTransactionCommandStrategy implements
CommandStrategy {
// Get the loan and transaction ids for use in
loanTransactionsApiResource
final List<String> pathParameters =
Splitter.on('/').splitToList(relativeUrl);
Long loanId = Long.parseLong(pathParameters.get(1));
- Long transactionId = Long.parseLong(pathParameters.get(3));
+
+ final String transactionIdPathParameter = pathParameters.get(3);
+ Long transactionId;
+ if (transactionIdPathParameter.contains("?")) {
+ transactionId = Long.parseLong(pathParameters.get(3).substring(0,
pathParameters.get(3).indexOf("?")));
+ } else {
+ transactionId = Long.parseLong(pathParameters.get(3));
+ }
+
Map<String, String> queryParameters =
CommandStrategyUtils.getQueryParameters(relativeUrl);
String command = queryParameters.get("command");
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
index 74ffdd8e4..5e5829594 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
@@ -976,6 +976,8 @@ final class LoansApiResourceSwagger {
public GetDelinquencyRangesResponse delinquencyRange;
@Schema(example = "false")
public Boolean fraud;
+ @Schema(example = "250.000000")
+ public Double totalOverpaid;
}
@Schema(description = "GetLoansResponse")
@@ -1049,6 +1051,8 @@ final class LoansApiResourceSwagger {
public List<PostLoansDisbursementData> disbursementData;
@Schema(description = "Maximum allowed outstanding balance")
public BigDecimal maxOutstandingLoanBalance;
+ @Schema(example = "[2011, 10, 20]")
+ public LocalDate repaymentsStartingFromDate;
}
@Schema(description = "PostLoansResponse")
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
index d25930356..d16740cad 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
@@ -1175,6 +1175,10 @@ final class LoanProductsApiResourceSwagger {
public GetLoanCharge charge;
public GetLoanAccountingMappings.GetLoanIncomeFromFeeAccount
incomeAccount;
+ @Schema(example = "10")
+ public Long chargeId;
+ @Schema(example = "39")
+ public Long incomeAccountId;
}
@Schema(example = "11")
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/batch/command/CommandStrategyProviderTest.java
b/fineract-provider/src/test/java/org/apache/fineract/batch/command/CommandStrategyProviderTest.java
index 5ce803bf2..507e615e9 100644
---
a/fineract-provider/src/test/java/org/apache/fineract/batch/command/CommandStrategyProviderTest.java
+++
b/fineract-provider/src/test/java/org/apache/fineract/batch/command/CommandStrategyProviderTest.java
@@ -88,6 +88,8 @@ public class CommandStrategyProviderTest {
mock(CreateTransactionLoanCommandStrategy.class)),
Arguments.of("loans/123/transactions/123", HttpMethod.POST,
"adjustTransactionCommandStrategy",
mock(AdjustTransactionCommandStrategy.class)),
+ Arguments.of("loans/123/transactions/123?command=chargeback",
HttpMethod.POST, "adjustTransactionCommandStrategy",
+ mock(AdjustTransactionCommandStrategy.class)),
Arguments.of("clients/456?command=activate", HttpMethod.POST,
"activateClientCommandStrategy",
mock(ActivateClientCommandStrategy.class)),
Arguments.of("loans/123?command=approve", HttpMethod.POST,
"approveLoanCommandStrategy",
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategyTest.java
b/fineract-provider/src/test/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategyTest.java
index 17fb6da2e..20dae9a60 100644
---
a/fineract-provider/src/test/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategyTest.java
+++
b/fineract-provider/src/test/java/org/apache/fineract/batch/command/internal/AdjustTransactionCommandStrategyTest.java
@@ -25,6 +25,7 @@ import static org.mockito.BDDMockito.given;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse;
import
org.apache.fineract.portfolio.loanaccount.api.LoanTransactionsApiResource;
@@ -39,13 +40,13 @@ public class AdjustTransactionCommandStrategyTest {
* Test {@link AdjustTransactionCommandStrategy#execute} happy path
scenario.
*/
@Test
- public void testExecuteSuccessScenario() {
+ public void testExecuteWithoutCommandSuccessScenario() {
// given
final TestContext testContext = new TestContext();
final Long loanId = Long.valueOf(RandomStringUtils.randomNumeric(4));
final Long transactionId =
Long.valueOf(RandomStringUtils.randomNumeric(4));
- final BatchRequest request = getBatchRequest(loanId, transactionId);
+ final BatchRequest request = getBatchRequest(loanId, transactionId,
null);
final String responseBody =
"{\"officeId\":1,\"clientId\":107,\"loanId\":71,\"resourceId\":193,\"changes\""
+ ":{\"transactionDate\":\"03 October
2022\",\"transactionAmount\":\"500\",\"locale\":\"en\",\"dateFormat\":"
+ "\"dd MMMM yyyy\",\"paymentTypeId\":\"\"}}";
@@ -63,6 +64,34 @@ public class AdjustTransactionCommandStrategyTest {
assertEquals(response.getBody(), responseBody);
}
+ /**
+ * Test {@link AdjustTransactionCommandStrategy#execute} happy path
scenario.
+ */
+ @Test
+ public void testExecuteWithCommandSuccessScenario() {
+ // given
+ final TestContext testContext = new TestContext();
+
+ final Long loanId = Long.valueOf(RandomStringUtils.randomNumeric(4));
+ final Long transactionId =
Long.valueOf(RandomStringUtils.randomNumeric(4));
+ final BatchRequest request = getBatchRequest(loanId, transactionId,
"chargeback");
+ final String responseBody =
"{\"officeId\":1,\"clientId\":107,\"loanId\":71,\"resourceId\":193,\"changes\""
+ + ":{\"transactionDate\":\"03 October
2022\",\"transactionAmount\":\"500\",\"locale\":\"en\",\"dateFormat\":"
+ + "\"dd MMMM yyyy\",\"paymentTypeId\":\"\"}}";
+
+
given(testContext.loanTransactionsApiResource.adjustLoanTransaction(eq(loanId),
eq(transactionId), eq(request.getBody()),
+ eq("chargeback"))).willReturn(responseBody);
+
+ // when
+ final BatchResponse response =
testContext.subjectToTest.execute(request, testContext.uriInfo);
+
+ // then
+ assertEquals(response.getStatusCode(), HttpStatus.SC_OK);
+ assertEquals(response.getRequestId(), request.getRequestId());
+ assertEquals(response.getHeaders(), request.getHeaders());
+ assertEquals(response.getBody(), responseBody);
+ }
+
/**
* Creates and returns a request with the given loan id and transaction id.
*
@@ -70,15 +99,20 @@ public class AdjustTransactionCommandStrategyTest {
* the loan id
* @param transactionId
* the transaction id
+ * @param transactionCommand
+ * the optional transaction command
* @return BatchRequest
*/
- private BatchRequest getBatchRequest(final Long loanId, final Long
transactionId) {
+ private BatchRequest getBatchRequest(final Long loanId, final Long
transactionId, final String transactionCommand) {
final BatchRequest br = new BatchRequest();
String relativeUrl = String.format("loans/%s/transactions/%s", loanId,
transactionId);
br.setRequestId(Long.valueOf(RandomStringUtils.randomNumeric(5)));
br.setRelativeUrl(relativeUrl);
+ if (StringUtils.isNotBlank(transactionCommand)) {
+ br.setRelativeUrl(br.getRelativeUrl() +
String.format("?command=%s", transactionCommand));
+ }
br.setMethod(HttpMethod.POST);
br.setReference(Long.valueOf(RandomStringUtils.randomNumeric(5)));
br.setBody("{\"locale\":\"en\",\"dateFormat\":\"dd MMMM
yyyy\",\"transactionDate\":\"03 October 2022\",\"transactionAmount\":500}");
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java
index afb0505fe..f81774280 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BatchApiTest.java
@@ -1391,6 +1391,77 @@ public class BatchApiTest {
Assertions.assertEquals(date, reversedOnDate);
}
+ /**
+ * Test for the successful repayment chargeback transaction. A '200'
status code is expected on successful
+ * responses.
+ *
+ * @see AdjustTransactionCommandStrategy
+ */
+ @Test
+ public void shouldReturnOkStatusForBatchRepaymentChargeback() {
+
+ final String loanProductJSON = new LoanProductTestBuilder() //
+ .withPrincipal("10000000.00") //
+ .withNumberOfRepayments("24") //
+ .withRepaymentAfterEvery("1") //
+ .withRepaymentTypeAsMonth() //
+ .withinterestRatePerPeriod("2") //
+ .withInterestRateFrequencyTypeAsMonths() //
+ .withAmortizationTypeAsEqualPrincipalPayment() //
+ .withInterestTypeAsDecliningBalance() //
+ .currencyDetails("0", "100").build(null);
+
+ final Integer productId = new LoanTransactionHelper(this.requestSpec,
this.responseSpec).getLoanProductId(loanProductJSON);
+
+ final Long applyLoanRequestId = 5730L;
+ final Long approveLoanRequestId = 5731L;
+ final Long disburseLoanRequestId = 5732L;
+ final Long repayLoanRequestId = 5733L;
+ final Long repayReversalRequestId = 5734L;
+ final Long getLoanRequestId = 5735L;
+
+ // Create client
+ final Integer clientId = ClientHelper.createClient(this.requestSpec,
this.responseSpec);
+ ClientHelper.verifyClientCreatedOnServer(this.requestSpec,
this.responseSpec, clientId);
+
+ // Create an apply loan request
+ final BatchRequest applyLoanRequest =
BatchHelper.applyLoanRequestWithClientId(applyLoanRequestId, clientId,
productId);
+
+ // Create an approve loan request
+ final BatchRequest approveLoanRequest =
BatchHelper.approveLoanRequest(approveLoanRequestId, applyLoanRequestId);
+
+ // Create a disburse loan request
+ final BatchRequest disburseLoanRequest =
BatchHelper.disburseLoanRequest(disburseLoanRequestId, approveLoanRequestId);
+
+ // Create a repayment request
+ final BatchRequest repaymentRequest =
BatchHelper.repayLoanRequest(repayLoanRequestId, disburseLoanRequestId, "500");
+
+ // Create a repayment chargeback request
+ final BatchRequest repaymentChargebackRequest =
BatchHelper.createChargebackTransactionRequest(repayReversalRequestId,
+ repayLoanRequestId, "500");
+
+ // Get loan transactions request
+ final BatchRequest getLoanTransactionsRequest =
BatchHelper.getLoanByIdRequest(getLoanRequestId, applyLoanRequestId,
+ "associations=transactions");
+
+ final List<BatchRequest> batchRequests =
Arrays.asList(applyLoanRequest, approveLoanRequest, disburseLoanRequest,
repaymentRequest,
+ repaymentChargebackRequest, getLoanTransactionsRequest);
+
+ final List<BatchResponse> responses =
BatchHelper.postBatchRequestsWithoutEnclosingTransaction(this.requestSpec,
this.responseSpec,
+ BatchHelper.toJsonString(batchRequests));
+
+ final FromJsonHelper jsonHelper = new FromJsonHelper();
+ final JsonObject repayment =
jsonHelper.parse(responses.get(5).getBody()).getAsJsonObject().get("transactions").getAsJsonArray()
+ .get(2).getAsJsonObject();
+
+ Assertions.assertEquals(HttpStatus.SC_OK, (long)
responses.get(4).getStatusCode(),
+ "Verify Status Code 200 for repayment chargeback");
+ Assertions.assertEquals("Repayment",
repayment.get("type").getAsJsonObject().get("value").getAsString());
+ final JsonArray transactionRelations =
repayment.get("transactionRelations").getAsJsonArray();
+ Assertions.assertEquals(1, transactionRelations.size());
+ Assertions.assertEquals("CHARGEBACK",
transactionRelations.get(0).getAsJsonObject().get("relationType").getAsString());
+ }
+
/**
* Tests successful run of batch goodwill credit reversal for loans. A
'200' status code is expected on successful
* responses.
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
index 50f373570..ca54486fb 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BatchHelper.java
@@ -883,6 +883,19 @@ public final class BatchHelper {
return br;
}
+ /**
+ * Creates and returns a batch request to create an adjust transaction
request.
+ *
+ * @param requestId
+ * the request ID
+ * @param reference
+ * the reference
+ * @param amount
+ * the amount
+ * @param date
+ * the date
+ * @return the {@link BatchRequest}
+ */
public static BatchRequest createAdjustTransactionRequest(final Long
requestId, final Long reference, final String amount,
final LocalDate date) {
final BatchRequest br = new BatchRequest();
@@ -897,6 +910,30 @@ public final class BatchHelper {
dateString, amount));
return br;
+ }
+
+ /**
+ * Creates and returns a batch request to create a chargeback transaction
request.
+ *
+ * @param requestId
+ * the request ID
+ * @param reference
+ * the reference
+ * @param amount
+ * the amount
+ * @return the {@link BatchRequest}
+ */
+ public static BatchRequest createChargebackTransactionRequest(final Long
requestId, final Long reference, final String amount) {
+
+ final BatchRequest br = new BatchRequest();
+
+ br.setRequestId(requestId);
+ br.setReference(reference);
+
br.setRelativeUrl("loans/$.loanId/transactions/$.resourceId?command=chargeback");
+ br.setMethod("POST");
+ br.setBody(String.format("{\"locale\": \"en\", \"transactionAmount\":
%s, \"paymentTypeId\": 2}", amount));
+
+ return br;
}
}