Merge pull request #980 from rishy/Batch-API

added ApplySavings command in Batch-API
This commit is contained in:
Vishwas Babu A J
2014-06-26 13:24:30 -07:00
10 changed files with 161 additions and 20 deletions
@@ -13,6 +13,7 @@ import org.mifosplatform.integrationtests.common.BatchHelper;
import org.mifosplatform.integrationtests.common.Utils;
import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder;
import org.mifosplatform.integrationtests.common.loans.LoanTransactionHelper;
import org.mifosplatform.integrationtests.common.savings.SavingsProductHelper;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -191,7 +192,7 @@ public class BatchApiTest {
.withInterestTypeAsDecliningBalance() //
.currencyDetails("0", "100").build(null);
Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec)
final Integer productId = new LoanTransactionHelper(this.requestSpec, this.responseSpec)
.getLoanProductId(loanProductJSON);
//Create a createClient Request
@@ -217,4 +218,48 @@ public class BatchApiTest {
Assert.assertEquals("Loan Successfully applied to client " + clientId.getAsString(),
200L, (long) response.get(1).getStatusCode());
}
/**
* Tests that a new savings accounts was applied to an existing client and a
* 200(OK) status was returned. It first creates a new client and a savings product,
* then uses the cliendId and ProductId to apply a savings account.
*
* @see org.mifosplatform.batch.command.internal.ApplySavingsCommandStrategy
*/
@Test
public void shouldReturnOkStatusForApplySavingsCommand(){
final SavingsProductHelper savingsProductHelper = new SavingsProductHelper();
final String savingsProductJSON = savingsProductHelper //
.withInterestCompoundingPeriodTypeAsDaily() //
.withInterestPostingPeriodTypeAsMonthly() //
.withInterestCalculationPeriodTypeAsDailyBalance() //
.withMinimumOpenningBalance("5000").build();
final Integer productId = SavingsProductHelper.createSavingsProduct(savingsProductJSON,
this.requestSpec, this.responseSpec);
//Create a createClient Request
final BatchRequest br1 = BatchHelper.createClientRequest(4720L, "");
//Create a applySavings Request
final BatchRequest br2 = BatchHelper.applySavingsRequest(4721L, 4720L, productId);
final List<BatchRequest> batchRequests = new ArrayList<>();
batchRequests.add(br1);
batchRequests.add(br2);
final String jsonifiedRequest = BatchHelper.toJsonString(batchRequests);
final List<BatchResponse> response = BatchHelper.postBatchRequestsWithoutEnclosingTransaction(this.requestSpec,
this.responseSpec, jsonifiedRequest);
//Get the clientId parameter from createClient Response
final JsonElement clientId = new FromJsonHelper().parse(response.get(0).getBody())
.getAsJsonObject().get("clientId");
Assert.assertEquals("Savings Successfully applied to client " + clientId.getAsString(),
200L, (long) response.get(1).getStatusCode());
}
}
@@ -52,7 +52,7 @@ public class BatchHelper {
/**
* Returns a list of BatchResponse with query paramater enclosing transaction set to
* Returns a list of BatchResponse with query parameter enclosing transaction set to
* false by posting the jsonified BatchRequest to the server.
*
* @param requestSpec
@@ -67,7 +67,7 @@ public class BatchHelper {
}
/**
* Returns a list of BatchResponse with query paramater enclosing transaction set to
* Returns a list of BatchResponse with query parameter enclosing transaction set to
* true by posting the jsonified BatchRequest to the server.
*
* @param requestSpec
@@ -164,9 +164,10 @@ public class BatchHelper {
*
* @param requestId
* @param reference
* @param productId
* @return BatchRequest
*/
public static BatchRequest applyLoanRequest(final Long requestId, final Long reference,
public static BatchRequest applyLoanRequest(final Long requestId, final Long reference,
final Integer productId) {
final BatchRequest br = new BatchRequest();
@@ -176,7 +177,6 @@ public class BatchHelper {
br.setMethod("POST");
br.setReference(reference);
//NOTE: Set the value productId according to your db else will result in a '404' response
final String body = "{\"dateFormat\": \"dd MMMM yyyy\", \"locale\": \"en_GB\", \"clientId\": \"$.clientId\"," +
"\"productId\": "+productId+", \"principal\": \"10,000.00\", \"loanTermFrequency\": 12," +
"\"loanTermFrequencyType\": 2, \"loanType\": \"individual\", \"numberOfRepayments\": 10," +
@@ -189,6 +189,32 @@ public class BatchHelper {
return br;
}
/**
* Creates and returns a {@link org.mifosplatform.batch.command.internal.ApplySavingsCommandStrategy}
* Request with given requestId and reference.
*
* @param requestId
* @param reference
* @param productId
* @return BatchRequest
*/
public static BatchRequest applySavingsRequest(final Long requestId, final Long reference,
final Integer productId){
final BatchRequest br = new BatchRequest();
br.setRequestId(requestId);
br.setRelativeUrl("savingsaccounts");
br.setMethod("POST");
br.setReference(reference);
final String body = "{\"clientId\": \"$.clientId\", \"productId\": "+productId+ "," +
"\"locale\": \"en\", \"dateFormat\": \"dd MMMM yyyy\", \"submittedOnDate\": \"01 March 2011\"}";
br.setBody(body);
return br;
}
/**
* Checks that the client with given externalId is not created on the server.
*
@@ -13,6 +13,8 @@ import javax.ws.rs.core.MediaType;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.batch.exception.ErrorHandler;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.mifosplatform.batch.serialization.BatchRequestJsonHelper;
import org.mifosplatform.batch.service.BatchApiService;
import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer;
@@ -96,9 +98,11 @@ public class BatchApiResource {
BatchResponse response = new BatchResponse();
response.setStatusCode(400);
response.setBody("One or more of your requests couldn't be completed because of errors" +
" - Rolling back the whole transaction\n\n" + e.toString());
//Gets an object of type ErrorInfo, containing information about raised exception
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(ex.getMessage());
result.add(response);
return this.toApiJsonSerializer.serialize(result);
@@ -70,6 +70,7 @@ public class CommandStrategyProvider {
this.commandStrategies.put(CommandContext.resource("clients").method("POST").build(), "createClientCommandStrategy");
this.commandStrategies.put(CommandContext.resource("clients\\/\\d+").method("PUT").build(), "updateClientCommandStrategy");
this.commandStrategies.put(CommandContext.resource("loans").method("POST").build(), "applyLoanCommandStrategy");
this.commandStrategies.put(CommandContext.resource("savingsaccounts").method("POST").build(), "applySavingsCommandStrategy");
}
}
@@ -9,8 +9,6 @@ import org.mifosplatform.portfolio.loanaccount.api.LoansApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} and applies a new loan
* on an existing client. It passes the contents of the body from the BatchRequest
@@ -61,7 +59,7 @@ public class ApplyLoanCommandStrategy implements CommandStrategy{
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(new Gson().toJson(ex));
response.setBody(ex.getMessage());
}
return response;
@@ -0,0 +1,67 @@
package org.mifosplatform.batch.command.internal;
import org.mifosplatform.batch.command.CommandStrategy;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.batch.exception.ErrorHandler;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.mifosplatform.portfolio.savings.api.SavingsAccountsApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} and applies a new savings
* on an existing client. It passes the contents of the body from the BatchRequest
* to {@link org.mifosplatform.portfolio.client.api.SavingsAccountsApiResource} and gets back
* the response. This class will also catch any errors raised by
* {@link org.mifosplatform.portfolio.client.api.SavingsAccountsApiResource} and map those errors
* to appropriate status codes in BatchResponse.
*
* @author Rishabh Shukla
*
* @see org.mifosplatform.batch.command.CommandStrategy
* @see org.mifosplatform.batch.domain.BatchRequest
* @see org.mifosplatform.batch.domain.BatchResponse
*/
@Component
public class ApplySavingsCommandStrategy implements CommandStrategy{
private final SavingsAccountsApiResource savingsAccountsApiResource;
@Autowired
public ApplySavingsCommandStrategy(final SavingsAccountsApiResource savingsAccountsApiResource) {
this.savingsAccountsApiResource = savingsAccountsApiResource;
}
@Override
public BatchResponse execute(BatchRequest request) {
final BatchResponse response = new BatchResponse();
final String responseBody;
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
//Try-catch blocks to map exceptions to appropriate status codes
try {
//Calls 'submitApplication' function from 'SavingsAccountsApiResource' to Apply Savings to an existing client
responseBody = savingsAccountsApiResource.submitApplication(request.getBody());
response.setStatusCode(200);
//Sets the body of the response after savings is successfully applied
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;
}
}
@@ -9,8 +9,6 @@ import org.mifosplatform.portfolio.client.api.ClientsApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} to handle
* creation of a new client. It passes the contents of the body from the BatchRequest
@@ -61,7 +59,7 @@ public class CreateClientCommandStrategy implements CommandStrategy{
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(new Gson().toJson(ex));
response.setBody(ex.getMessage());
}
return response;
@@ -9,8 +9,6 @@ import org.mifosplatform.portfolio.client.api.ClientsApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} and updates the
* information of an existing client. It passes the contents of the body from the BatchRequest
@@ -64,7 +62,7 @@ public class UpdateClientCommandStrategy implements CommandStrategy {
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(new Gson().toJson(ex));
response.setBody(ex.getMessage());
}
return response;
@@ -4,6 +4,7 @@ import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceN
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
import org.springframework.transaction.TransactionException;
/**
* Provides an Error Handler method that returns an object of type {@link ErrorInfo}
@@ -35,14 +36,17 @@ public class ErrorHandler extends RuntimeException{
public static ErrorInfo handler(RuntimeException exception) {
if(exception instanceof AbstractPlatformResourceNotFoundException) {
return new ErrorInfo(404, 1001, "Requested Resource was not Found");
return new ErrorInfo(404, 1001, "Requested Resource was not Found: Check for any unavailable Parameters");
} else if(exception instanceof UnsupportedParameterException) {
return new ErrorInfo(400, 2001, "UnsupportedParameterException: Check for any unsupported Parameters");
} else if(exception instanceof PlatformApiDataValidationException) {
return new ErrorInfo(400, 2002, "ApiDataValidationException: Re-Check the input data");
} else if(exception instanceof PlatformDataIntegrityException) {
return new ErrorInfo(403, 3001, "DataIntegrityException: Check for any duplicate data");
}
} else if(exception instanceof TransactionException) {
return new ErrorInfo(400, 4001, "TransactionException: One or more of your requests were unsuccessful," +
" reverting back all the transactions in this Batch Request");
}
return new ErrorInfo(500, 9999, "Internal Server Error");
@@ -91,7 +91,7 @@ public class BatchApiServiceImpl implements BatchApiService{
//Some detail information about the error
final ErrorInfo conflictError = new ErrorInfo(Status.CONFLICT.getStatusCode(), 8001,
"Parent request with id " + parentResponse.getRequestId() + " was erroneous!");
response.setBody(new Gson().toJson(conflictError));
response.setBody(conflictError.getMessage());
responseList.add(response);
//Proceed with next list entry