diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/CalculateLoanScheduleCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/CalculateLoanScheduleCommand.java index 1a7e495ef..7390a49d1 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/CalculateLoanScheduleCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/CalculateLoanScheduleCommand.java @@ -95,13 +95,13 @@ public class CalculateLoanScheduleCommand { this.commonLoanProperties.setPrincipal(principal); } - public Boolean getFlexibleRepaymentSchedule() { - return this.commonLoanProperties.getFlexibleRepaymentSchedule(); - } - - public Boolean getInterestRebateAllowed() { - return this.commonLoanProperties.getInterestRebateAllowed(); - } +// public Boolean getFlexibleRepaymentSchedule() { +// return this.commonLoanProperties.getFlexibleRepaymentSchedule(); +// } +// +// public Boolean getInterestRebateAllowed() { +// return this.commonLoanProperties.getInterestRebateAllowed(); +// } public Integer getInterestRateFrequencyMethod() { return commonLoanProperties.getInterestRateFrequencyMethod(); diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/CommonLoanProperties.java b/mifosng-data/src/main/java/org/mifosng/data/command/CommonLoanProperties.java index 2305a22dd..038e2275a 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/CommonLoanProperties.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/CommonLoanProperties.java @@ -117,13 +117,13 @@ public class CommonLoanProperties { this.principal = principal; } - public Boolean getFlexibleRepaymentSchedule() { - return this.flexibleRepaymentSchedule; - } +// public Boolean getFlexibleRepaymentSchedule() { +// return this.flexibleRepaymentSchedule; +// } - public Boolean getInterestRebateAllowed() { - return this.interestRebateAllowed; - } +// public Boolean getInterestRebateAllowed() { +// return this.interestRebateAllowed; +// } public Integer getInterestRateFrequencyMethod() { return interestRateFrequencyMethod; diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/CreateLoanProductCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/CreateLoanProductCommand.java index 230dc0903..2791a5d62 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/CreateLoanProductCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/CreateLoanProductCommand.java @@ -144,18 +144,18 @@ public class CreateLoanProductCommand implements LoanProductCommandData { /* (non-Javadoc) * @see org.mifosng.data.command.LoanProductCommandData#getFlexibleRepaymentSchedule() */ - @Override - public Boolean getFlexibleRepaymentSchedule() { - return this.commonLoanProperties.getFlexibleRepaymentSchedule(); - } +// @Override +// public Boolean getFlexibleRepaymentSchedule() { +// return this.commonLoanProperties.getFlexibleRepaymentSchedule(); +// } /* (non-Javadoc) * @see org.mifosng.data.command.LoanProductCommandData#getInterestRebateAllowed() */ - @Override - public Boolean getInterestRebateAllowed() { - return this.commonLoanProperties.getInterestRebateAllowed(); - } +// @Override +// public Boolean getInterestRebateAllowed() { +// return this.commonLoanProperties.getInterestRebateAllowed(); +// } /* (non-Javadoc) * @see org.mifosng.data.command.LoanProductCommandData#getInterestRateFrequencyMethod() diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/LoanProductCommandData.java b/mifosng-data/src/main/java/org/mifosng/data/command/LoanProductCommandData.java index 180503063..0cfdf73f2 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/LoanProductCommandData.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/LoanProductCommandData.java @@ -22,9 +22,9 @@ public interface LoanProductCommandData { BigDecimal getPrincipal(); - Boolean getFlexibleRepaymentSchedule(); +// Boolean getFlexibleRepaymentSchedule(); - Boolean getInterestRebateAllowed(); +// Boolean getInterestRebateAllowed(); Integer getInterestRateFrequencyMethod(); diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/SubmitLoanApplicationCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/SubmitLoanApplicationCommand.java index 58725e5a1..1bf2608a3 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/SubmitLoanApplicationCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/SubmitLoanApplicationCommand.java @@ -187,13 +187,13 @@ public class SubmitLoanApplicationCommand { this.commonLoanProperties.setPrincipal(principal); } - public Boolean getFlexibleRepaymentSchedule() { - return this.commonLoanProperties.getFlexibleRepaymentSchedule(); - } - - public Boolean getInterestRebateAllowed() { - return this.commonLoanProperties.getInterestRebateAllowed(); - } +// public Boolean getFlexibleRepaymentSchedule() { +// return this.commonLoanProperties.getFlexibleRepaymentSchedule(); +// } +// +// public Boolean getInterestRebateAllowed() { +// return this.commonLoanProperties.getInterestRebateAllowed(); +// } public Integer getInterestRateFrequencyMethod() { return commonLoanProperties.getInterestRateFrequencyMethod(); diff --git a/mifosng-data/src/main/java/org/mifosng/data/command/UpdateLoanProductCommand.java b/mifosng-data/src/main/java/org/mifosng/data/command/UpdateLoanProductCommand.java index 010717427..07da0703f 100644 --- a/mifosng-data/src/main/java/org/mifosng/data/command/UpdateLoanProductCommand.java +++ b/mifosng-data/src/main/java/org/mifosng/data/command/UpdateLoanProductCommand.java @@ -106,13 +106,13 @@ public class UpdateLoanProductCommand implements LoanProductCommandData { this.commonLoanProperties.setPrincipal(principal); } - public Boolean getFlexibleRepaymentSchedule() { - return this.commonLoanProperties.getFlexibleRepaymentSchedule(); - } - - public Boolean getInterestRebateAllowed() { - return this.commonLoanProperties.getInterestRebateAllowed(); - } +// public Boolean getFlexibleRepaymentSchedule() { +// return this.commonLoanProperties.getFlexibleRepaymentSchedule(); +// } +// +// public Boolean getInterestRebateAllowed() { +// return this.commonLoanProperties.getInterestRebateAllowed(); +// } public Integer getInterestRateFrequencyMethod() { return commonLoanProperties.getInterestRateFrequencyMethod(); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java index 33e653541..8b4b03d83 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoanProductApiResource.java @@ -1,24 +1,37 @@ package org.mifosng.platform.api; +import java.util.Arrays; import java.util.Collection; import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import org.mifosng.data.EntityIdentifier; +import org.mifosng.data.ErrorResponse; +import org.mifosng.data.ErrorResponseList; import org.mifosng.data.LoanProductData; import org.mifosng.data.LoanProductList; +import org.mifosng.data.command.CreateLoanProductCommand; +import org.mifosng.data.command.UpdateLoanProductCommand; import org.mifosng.platform.ReadPlatformService; import org.mifosng.platform.WritePlatformService; +import org.mifosng.platform.exceptions.ApplicationDomainRuleException; import org.mifosng.platform.exceptions.ClientNotAuthenticatedException; -import org.mifosng.platform.security.PlatformUserDetailsService; +import org.mifosng.platform.exceptions.NewDataValidationException; import org.mifosng.platform.user.domain.AppUser; import org.mifosng.platform.user.domain.AppUserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; @@ -26,14 +39,21 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; /* + * + * @see http://viewfromthefringe.blogspot.com/2010/06/versioning-rest-services.html + * @see http://jersey.576304.n2.nabble.com/Restful-Service-Versioning-td6332833.html + * * Note: Jersey looks for 'requests' starting with 'api' e.g. this resources url is https://[localhost:8080]/api/v1/loanproducts - * Note: Called this class *ApiResource as if you leave it as same class name as older 'resource' class, jersey throws a wobbler. + * Note: Named this class *ApiResource as if you leave it as same class name as older 'resource' class, jersey throws a wobbler. * Note: no authentication scheme is in place so calls that match api/v1/** are not managed by spring security for now. * - * 1. resource is versioned + * 1. resource is versioned here but will move the 'version' part to web.xml when finished. * 2. using plural of resource e.g. loanproducts rather than loanproduct * 3. @GET results in list of all loan products being returned (no scoping relevant here) * 4. Only 'produce'ing JSON by limiting to @Produces({MediaType.APPLICATION_JSON}) + * 5. The java object returned is LoanProductData and LoanProductList when list of products returned. + * These java objects are annotated with @XmlRootElement so JAXB reader/writers will automatically translate to JSON format. + * 6. @GET /loanproducts/{productId} results in loan product of that identifier or appropiate error response */ @Path("/v1/loanproducts") @Component @@ -62,80 +82,142 @@ public class LoanProductApiResource { @Produces({MediaType.APPLICATION_JSON}) public Response retrieveAllLoanProducts() { - hardcodeUserIntoSecurityContext(); - - Collection products = this.readPlatformService.retrieveAllLoanProducts(); + try { + hardcodeUserIntoSecurityContext(); + + Collection products = this.readPlatformService.retrieveAllLoanProducts(); - return Response.ok().entity(new LoanProductList(products)).build(); + return Response.ok().entity(new LoanProductList(products)).build(); + } catch (ClientNotAuthenticatedException e) { + throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); + } catch (AccessDeniedException e) { + ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); + ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); + } catch (ApplicationDomainRuleException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); + } catch (NewDataValidationException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); + } } + + @GET + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON}) + public Response retrieveLoanProductDetails(@PathParam("productId") final Long productId) { -// @POST -// @Path("new") -// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) -// @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) -// public Response createLoanProduct(final CreateLoanProductCommand command) { -// -// try { -// EntityIdentifier entityIdentifier = this.writePlatformService.createLoanProduct(command); -// -// return Response.ok().entity(entityIdentifier).build(); -// } catch (ClientNotAuthenticatedException e) { -// throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); -// } catch (AccessDeniedException e) { -// ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); -// ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); -// } catch (ApplicationDomainRuleException e) { -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); -// } catch (NewDataValidationException e) { -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); -// } + try { + hardcodeUserIntoSecurityContext(); + + LoanProductData loanProduct = this.readPlatformService.retrieveLoanProduct(productId); + + return Response.ok().entity(loanProduct).build(); + } catch (ClientNotAuthenticatedException e) { + throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); + } catch (AccessDeniedException e) { + ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); + ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); + } catch (ApplicationDomainRuleException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); + } catch (NewDataValidationException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); + } + } + +// example POST request +// http://localhost:8085/mifosng-provider/api/v1/loanproducts/ +// Content-Type: application/json +// { +// "name": "test", +// "description": "test", +// "commonLoanProperties": { +// "currencyCode": "USD", +// "digitsAfterDecimal": 2, +// "principal": 100000, +// "repaymentEvery": 1, +// "repaymentFrequency": 2, +// "numberOfRepayments": 12, +// "amortizationMethod": 1, +// "inArrearsToleranceAmount": 1000, +// "interestRatePerPeriod": 2, +// "interestRateFrequencyMethod": 2, +// "interestMethod": 0, +// "interestCalculationPeriodMethod": 1 +// } // } -// -// @POST -// @Path("update") -// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) -// @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) -// public Response updateLoanProduct(final UpdateLoanProductCommand command) { -// -// try { -// EntityIdentifier entityIdentifier = this.writePlatformService.updateLoanProduct(command); -// return Response.ok().entity(entityIdentifier).build(); -// } catch (ClientNotAuthenticatedException e) { -// throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); -// } catch (AccessDeniedException e) { -// ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); -// ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); -// } catch (ApplicationDomainRuleException e) { -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); -// } catch (NewDataValidationException e) { -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); + @POST + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON}) + public Response createLoanProduct(CreateLoanProductCommand command) { + + try { + hardcodeUserIntoSecurityContext(); + + EntityIdentifier entityIdentifier = this.writePlatformService.createLoanProduct(command); + + return Response.ok().entity(entityIdentifier).build(); + } catch (ClientNotAuthenticatedException e) { + throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); + } catch (AccessDeniedException e) { + ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); + ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); + } catch (ApplicationDomainRuleException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); + } catch (NewDataValidationException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); + } + } + +// example PUT request +// http://localhost:8085/mifosng-provider/api/v1/loanproducts/ +// Content-Type: application/json +// { +// "id": 7, +// "name": "test", +// "description": "test", +// "externalId": "", +// "commonLoanProperties": { +// "currencyCode": "USD", +// "digitsAfterDecimal": 2, +// "principal": 100000, +// "repaymentEvery": 1, +// "repaymentFrequency": 2, +// "numberOfRepayments": 12, +// "amortizationMethod": 1, +// "inArrearsToleranceAmount": 1000, +// "interestRatePerPeriod": 2, +// "interestRateFrequencyMethod": 2, +// "interestMethod": 0, +// "interestCalculationPeriodMethod": 1 +// } // } -// } -// -// @GET -// @Path("{productId}") -// @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) -// @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) -// public Response retrieveLoanProductDetails(@PathParam("productId") final Long productId) { -// -// try { -// LoanProductData loanProduct = this.readPlatformService.retrieveLoanProduct(productId); -// -// return Response.ok().entity(loanProduct).build(); -// } catch (ClientNotAuthenticatedException e) { -// throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); -// } catch (AccessDeniedException e) { -// ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); -// ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); -// } catch (ApplicationDomainRuleException e) { -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); -// } catch (NewDataValidationException e) { -// throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); -// } -// } + @PUT + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response updateLoanProduct(final UpdateLoanProductCommand command) { + + try { + hardcodeUserIntoSecurityContext(); + + EntityIdentifier entityIdentifier = this.writePlatformService.updateLoanProduct(command); + + return Response.ok().entity(entityIdentifier).build(); + } catch (ClientNotAuthenticatedException e) { + throw new WebApplicationException(Response.status(Status.UNAUTHORIZED).build()); + } catch (AccessDeniedException e) { + ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission", "id"); + ErrorResponseList list = new ErrorResponseList(Arrays.asList(errorResponse)); + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(list).build()); + } catch (ApplicationDomainRuleException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getErrors())).build()); + } catch (NewDataValidationException e) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(new ErrorResponseList(e.getValidationErrors())).build()); + } + } + // // @GET // @Path("empty")