You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by vi...@apache.org on 2019/06/14 20:05:58 UTC

[fineract] branch develop updated: FINERACT-767: Batch Repayment for loans

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

vishwasbabu 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 86e105f  FINERACT-767: Batch Repayment for loans
     new f10bff2  Merge pull request #584 from mohitsinha/repaymentbatch
86e105f is described below

commit 86e105ff154c91f37c13b4040e3bb07e9f081198
Author: Mohit Sinha <mo...@gmail.com>
AuthorDate: Fri Jun 14 17:07:12 2019 +0700

    FINERACT-767: Batch Repayment for loans
---
 api-docs/apiLive.htm                               |  1 +
 .../fineract/integrationtests/BatchApiTest.java    | 66 ++++++++++++++++
 .../integrationtests/common/BatchHelper.java       | 34 ++++++++
 .../batch/command/CommandStrategyProvider.java     |  2 +
 .../command/internal/RepayLoanCommandStrategy.java | 90 ++++++++++++++++++++++
 5 files changed, 193 insertions(+)

diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index 67dfc71..236fc25 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -4777,6 +4777,7 @@ Successful transaction response:
 						<li><a href="#clients_activate">Activate a Pending Client</a>
 						<li><a href="#loans_approve">Approve a Pending Loan</a>
 						<li><a href="#loans_disburse">Disburse a Loan</a>
+						<li><a href="#loans_transaction_repayment">Repayment for a Loan</a>
 					</ul>
 				</div>
 			</div>
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/BatchApiTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/BatchApiTest.java
index aae79a0..38f89e9 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/BatchApiTest.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/BatchApiTest.java
@@ -21,6 +21,8 @@ package org.apache.fineract.integrationtests;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
 
 import org.apache.fineract.batch.domain.BatchRequest;
 import org.apache.fineract.batch.domain.BatchResponse;
@@ -340,6 +342,70 @@ public class BatchApiTest {
     }
 
     /**
+     * Tests that batch repayment for loans is happening properly.
+     * Collected properly 200(OK) status was returned for successful responses.
+     * It first creates a new loan and then makes two repayments for it
+     * and then verifies that 200(OK) is returned for the repayment requests.
+     *
+     * @see org.apache.fineract.batch.command.internal.RepayLoanCommandStrategy
+     */
+    @Test
+    public void shouldReturnOkStatusForBatchRepayment() {
+
+        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);
+
+        // Create a createClient Request
+        final BatchRequest br1 = BatchHelper.createClientRequest(4730L, "");
+
+        // Create a activateClient Request
+        final BatchRequest br2 = BatchHelper.activateClientRequest(4731L, 4730L);
+
+        // Create a ApplyLoan Request
+        final BatchRequest br3 = BatchHelper.applyLoanRequest(4732L, 4731L, productId);
+
+        // Create a approveLoan Request
+        final BatchRequest br4 = BatchHelper.approveLoanRequest(4733L, 4732L);
+
+        // Create a disburseLoan Request
+        final BatchRequest br5 = BatchHelper.disburseLoanRequest(4734L, 4733L);
+
+        // Create a loanRepay Request
+        final BatchRequest br6 = BatchHelper.repayLoanRequest(4735L, 4734L);
+
+        // Create a loanRepay Request
+        final BatchRequest br7 = BatchHelper.repayLoanRequest(4736L, 4734L);
+
+        final List<BatchRequest> batchRequests = new ArrayList<>();
+
+        batchRequests.add(br1);
+        batchRequests.add(br2);
+        batchRequests.add(br3);
+        batchRequests.add(br4);
+        batchRequests.add(br5);
+        batchRequests.add(br6);
+        batchRequests.add(br7);
+
+        final String jsonifiedRequest = BatchHelper.toJsonString(batchRequests);
+
+        final List<BatchResponse> response = BatchHelper.postBatchRequestsWithoutEnclosingTransaction(this.requestSpec, this.responseSpec,
+                jsonifiedRequest);
+
+        Assert.assertEquals("Verify Status Code 200 for Repayment", 200L, (long) response.get(5).getStatusCode());
+        Assert.assertEquals("Verify Status Code 200 for Repayment", 200L, (long) response.get(6).getStatusCode());
+    }
+
+    /**
      * Test for the successful activation of a pending client using
      * 'ActivateClientCommandStrategy'. A '200' status code is expected on
      * successful activation.
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/BatchHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/BatchHelper.java
index 5a9a4d3..170ede5 100644
--- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/BatchHelper.java
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/BatchHelper.java
@@ -20,6 +20,7 @@ package org.apache.fineract.integrationtests.common;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.fineract.batch.domain.BatchRequest;
 import org.apache.fineract.batch.domain.BatchResponse;
@@ -59,6 +60,16 @@ public class BatchHelper {
     }
 
     /**
+     * Returns a Map from Json String
+     *
+     * @param jsonBody
+     * @return Map
+     */
+    public static Map generateMapFromJsonString(final String jsonString) {
+        return new Gson().fromJson(jsonString, Map.class);
+    }
+
+    /**
      * Returns the converted string response into JSON.
      * 
      * @param json
@@ -379,6 +390,29 @@ public class BatchHelper {
 
         return br;
     }
+
+    /**
+     * Creates and returns a
+     * {@link org.apache.fineract.batch.command.internal.RepayLoanCommandStrategy}
+     * Request with given requestId.
+     *
+     *
+     * @param requestId
+     * @param reference
+     * @return BatchRequest
+     */
+    public static BatchRequest repayLoanRequest(final Long requestId, final Long reference) {
+        final BatchRequest br = new BatchRequest();
+
+        br.setRequestId(requestId);
+        br.setReference(reference);
+        br.setRelativeUrl("loans/$.loanId/transactions?command=repayment");
+        br.setMethod("POST");
+        br.setBody("{\"locale\": \"en\", \"dateFormat\": \"dd MMMM yyyy\", " +
+                "\"transactionDate\": \"15 September 2013\",  \"transactionAmount\": 500}");
+
+        return br;
+    }
     
     /**
      * Checks that the client with given externalId is not created on the
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 e506004..8a95fd8 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
@@ -92,6 +92,8 @@ public class CommandStrategyProvider {
         this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\/charges").method("POST").build(), "createChargeCommandStrategy");
         this.commandStrategies
                 .put(CommandContext.resource("loans\\/\\d+\\/charges").method("GET").build(), "collectChargesCommandStrategy");
+        this.commandStrategies
+                .put(CommandContext.resource("loans\\/\\d+\\/transactions\\?command=repayment").method("POST").build(), "repayLoanCommandStrategy");
         this.commandStrategies.put(CommandContext.resource("clients\\/\\d+\\?command=activate").method("POST").build(),
                 "activateClientCommandStrategy");
         this.commandStrategies.put(CommandContext.resource("loans\\/\\d+\\?command=approve").method("POST").build(),
diff --git a/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/RepayLoanCommandStrategy.java b/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/RepayLoanCommandStrategy.java
new file mode 100644
index 0000000..16d710c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/batch/command/internal/RepayLoanCommandStrategy.java
@@ -0,0 +1,90 @@
+/**
+ * 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.batch.command.internal;
+
+import org.apache.fineract.batch.command.CommandStrategy;
+import org.apache.fineract.batch.domain.BatchRequest;
+import org.apache.fineract.batch.domain.BatchResponse;
+import org.apache.fineract.batch.exception.ErrorHandler;
+import org.apache.fineract.batch.exception.ErrorInfo;
+import org.apache.fineract.portfolio.loanaccount.api.LoanTransactionsApiResource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.core.UriInfo;
+
+/**
+ * Implements {@link CommandStrategy} and handles
+ * repayment for a Loan. It passes the contents of the body from the BatchRequest
+ * to {@link LoanTransactionsApiResource} and
+ * gets back the response. This class will also catch any errors raised by
+ * {@link LoanTransactionsApiResource} and map
+ * those errors to appropriate status codes in BatchResponse.
+ *
+ * @author Mohit Sinha
+ *
+ * @see CommandStrategy
+ * @see BatchRequest
+ * @see BatchResponse
+ */
+@Component
+public class RepayLoanCommandStrategy implements CommandStrategy {
+
+    private final LoanTransactionsApiResource loanTransactionsApiResource;
+
+    @Autowired
+    public RepayLoanCommandStrategy(final LoanTransactionsApiResource loanTransactionsApiResource) {
+        this.loanTransactionsApiResource = loanTransactionsApiResource;
+    }
+
+    @Override
+    public BatchResponse execute(BatchRequest request, @SuppressWarnings("unused") UriInfo uriInfo) {
+
+        final BatchResponse response = new BatchResponse();
+        final String responseBody;
+
+        response.setRequestId(request.getRequestId());
+        response.setHeaders(request.getHeaders());
+
+        final String[] pathParameters = request.getRelativeUrl().split("/");
+        Long loanId = Long.parseLong(pathParameters[1]);
+
+        // Try-catch blocks to map exceptions to appropriate status codes
+        try {
+
+            responseBody = loanTransactionsApiResource.executeLoanTransaction(loanId, "repayment", request.getBody());
+
+            response.setStatusCode(200);
+            // Sets the body of the response after Charge has been successfully
+            // created
+            response.setBody(responseBody);
+
+        } catch (RuntimeException e) {
+
+            // Gets an object of type ErrorInfo, containing information about
+            // raised exception
+            ErrorInfo ex = ErrorHandler.handler(e);
+
+            response.setStatusCode(ex.getStatusCode());
+            response.setBody(ex.getMessage());
+        }
+
+        return response;
+    }
+}