add remaining state transitions and loan transactions to api format.

This commit is contained in:
Keith Woodlock
2012-05-17 02:07:41 +01:00
parent 8bc0b7461f
commit 7bb8b9359e
28 changed files with 397 additions and 1462 deletions
@@ -11,9 +11,12 @@ public class AdjustLoanTransactionCommand {
private Long loanId; private Long loanId;
private Long repaymentId; private Long repaymentId;
private LocalDate paymentDate; private String dateFormat;
private String transactionDateFormatted;
private LocalDate transactionDate;
private String comment; private String comment;
private BigDecimal paymentAmount; private String transactionAmountFormatted;
private BigDecimal transactionAmount;
protected AdjustLoanTransactionCommand() { protected AdjustLoanTransactionCommand() {
// //
@@ -24,9 +27,9 @@ public class AdjustLoanTransactionCommand {
final BigDecimal paymentAmount) { final BigDecimal paymentAmount) {
this.loanId = loanId; this.loanId = loanId;
this.repaymentId = repaymentId; this.repaymentId = repaymentId;
this.paymentDate = paymentDate; this.transactionDate = paymentDate;
this.comment = comment; this.comment = comment;
this.paymentAmount = paymentAmount; this.transactionAmount = paymentAmount;
} }
public Long getLoanId() { public Long getLoanId() {
@@ -37,30 +40,6 @@ public class AdjustLoanTransactionCommand {
this.loanId = loanId; this.loanId = loanId;
} }
public String getComment() {
return this.comment;
}
public void setComment(final String comment) {
this.comment = comment;
}
public LocalDate getPaymentDate() {
return this.paymentDate;
}
public void setPaymentDate(final LocalDate paymentDate) {
this.paymentDate = paymentDate;
}
public BigDecimal getPaymentAmount() {
return this.paymentAmount;
}
public void setPaymentAmount(final BigDecimal paymentAmount) {
this.paymentAmount = paymentAmount;
}
public Long getRepaymentId() { public Long getRepaymentId() {
return repaymentId; return repaymentId;
} }
@@ -68,4 +47,52 @@ public class AdjustLoanTransactionCommand {
public void setRepaymentId(Long repaymentId) { public void setRepaymentId(Long repaymentId) {
this.repaymentId = repaymentId; this.repaymentId = repaymentId;
} }
public String getDateFormat() {
return dateFormat;
}
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
public String getTransactionDateFormatted() {
return transactionDateFormatted;
}
public void setTransactionDateFormatted(String transactionDateFormatted) {
this.transactionDateFormatted = transactionDateFormatted;
}
public LocalDate getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(LocalDate transactionDate) {
this.transactionDate = transactionDate;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getTransactionAmountFormatted() {
return transactionAmountFormatted;
}
public void setTransactionAmountFormatted(String transactionAmountFormatted) {
this.transactionAmountFormatted = transactionAmountFormatted;
}
public BigDecimal getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(BigDecimal transactionAmount) {
this.transactionAmount = transactionAmount;
}
} }
@@ -10,9 +10,12 @@ import org.joda.time.LocalDate;
public class LoanTransactionCommand { public class LoanTransactionCommand {
private Long loanId; private Long loanId;
private LocalDate paymentDate; private String dateFormat;
private String transactionDateFormatted;
private LocalDate transactionDate;
private String comment; private String comment;
private BigDecimal paymentAmount; private String transactionAmountFormatted;
private BigDecimal transactionAmount;
protected LoanTransactionCommand() { protected LoanTransactionCommand() {
// //
@@ -22,9 +25,9 @@ public class LoanTransactionCommand {
final LocalDate paymentDate, final String comment, final LocalDate paymentDate, final String comment,
final BigDecimal paymentAmount) { final BigDecimal paymentAmount) {
this.loanId = loanId; this.loanId = loanId;
this.paymentDate = paymentDate; this.transactionDate = paymentDate;
this.comment = comment; this.comment = comment;
this.paymentAmount = paymentAmount; this.transactionAmount = paymentAmount;
} }
public Long getLoanId() { public Long getLoanId() {
@@ -43,19 +46,43 @@ public class LoanTransactionCommand {
this.comment = comment; this.comment = comment;
} }
public LocalDate getPaymentDate() { public String getDateFormat() {
return this.paymentDate; return dateFormat;
} }
public void setPaymentDate(final LocalDate paymentDate) { public void setDateFormat(String dateFormat) {
this.paymentDate = paymentDate; this.dateFormat = dateFormat;
} }
public BigDecimal getPaymentAmount() { public String getTransactionDateFormatted() {
return this.paymentAmount; return transactionDateFormatted;
} }
public void setPaymentAmount(final BigDecimal paymentAmount) { public void setTransactionDateFormatted(String transactionDateFormatted) {
this.paymentAmount = paymentAmount; this.transactionDateFormatted = transactionDateFormatted;
}
public LocalDate getTransactionDate() {
return transactionDate;
}
public void setTransactionDate(LocalDate transactionDate) {
this.transactionDate = transactionDate;
}
public String getTransactionAmountFormatted() {
return transactionAmountFormatted;
}
public void setTransactionAmountFormatted(String transactionAmountFormatted) {
this.transactionAmountFormatted = transactionAmountFormatted;
}
public BigDecimal getTransactionAmount() {
return transactionAmount;
}
public void setTransactionAmount(BigDecimal transactionAmount) {
this.transactionAmount = transactionAmount;
} }
} }
@@ -74,8 +74,6 @@ dependencies {
[group: 'com.sun.jersey', name: 'jersey-core', version: jerseyVersion], [group: 'com.sun.jersey', name: 'jersey-core', version: jerseyVersion],
[group: 'com.sun.jersey', name: 'jersey-client', version: jerseyVersion], [group: 'com.sun.jersey', name: 'jersey-client', version: jerseyVersion],
[group: 'org.codehaus.jackson', name: 'jackson-mapper-asl', version: '1.9.4'], [group: 'org.codehaus.jackson', name: 'jackson-mapper-asl', version: '1.9.4'],
[group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.2'],
[group: 'net.sf.kxml', name: 'kxml2-min', version: '2.3.0'],
[group: 'joda-time', name: 'joda-time', version: '2.1'], [group: 'joda-time', name: 'joda-time', version: '2.1'],
[group: 'commons-lang', name: 'commons-lang', version: '2.4'], [group: 'commons-lang', name: 'commons-lang', version: '2.4'],
@@ -15,7 +15,6 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.mifosng.ui.JaxRs311ErrorResponseHandler;
import org.springframework.security.oauth.common.OAuthProviderParameter; import org.springframework.security.oauth.common.OAuthProviderParameter;
import org.springframework.security.oauth.consumer.OAuthConsumerToken; import org.springframework.security.oauth.consumer.OAuthConsumerToken;
import org.springframework.security.oauth.consumer.OAuthRequestFailedException; import org.springframework.security.oauth.consumer.OAuthRequestFailedException;
@@ -27,11 +26,9 @@ import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
public class MifosNgOauthConsumerContextFilter extends public class MifosNgOauthConsumerContextFilter extends OAuthConsumerContextFilter {
OAuthConsumerContextFilter {
private static final Log LOG = LogFactory private static final Log LOG = LogFactory.getLog(MifosNgOauthConsumerContextFilter.class);
.getLog(MifosNgOauthConsumerContextFilter.class);
private RestTemplate noAuthRestTemplate; private RestTemplate noAuthRestTemplate;
@@ -41,10 +38,8 @@ public class MifosNgOauthConsumerContextFilter extends
throws IOException, ServletException { throws IOException, ServletException {
ResponseErrorHandler defaultResponseErrorHandler = new DefaultResponseErrorHandler(); ResponseErrorHandler defaultResponseErrorHandler = new DefaultResponseErrorHandler();
ResponseErrorHandler jaxrs311ErrorResponseHandler = new JaxRs311ErrorResponseHandler(
defaultResponseErrorHandler);
this.noAuthRestTemplate = new RestTemplate(); this.noAuthRestTemplate = new RestTemplate();
this.noAuthRestTemplate.setErrorHandler(jaxrs311ErrorResponseHandler); this.noAuthRestTemplate.setErrorHandler(defaultResponseErrorHandler);
HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse; HttpServletResponse response = (HttpServletResponse) servletResponse;
@@ -1,11 +1,5 @@
package org.mifosng.ui; package org.mifosng.ui;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.springframework.security.oauth.consumer.ProtectedResourceDetails; import org.springframework.security.oauth.consumer.ProtectedResourceDetails;
public interface CommonRestOperations { public interface CommonRestOperations {
@@ -13,20 +7,4 @@ public interface CommonRestOperations {
void logout(String accessToken); void logout(String accessToken);
void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById); void updateProtectedResource(ProtectedResourceDetails loadProtectedResourceDetailsById);
EntityIdentifier disburseLoan(LoanStateTransitionCommand command);
EntityIdentifier undloLoanDisbursal(UndoLoanDisbursalCommand command);
LoanRepaymentData retrieveNewLoanRepaymentDetails(Long loanId);
LoanRepaymentData retrieveLoanRepaymentDetails(Long loanId, Long repaymentId);
EntityIdentifier makeLoanRepayment(LoanTransactionCommand command);
EntityIdentifier adjustLoanRepayment(AdjustLoanTransactionCommand command);
LoanRepaymentData retrieveNewLoanWaiverDetails(Long loanId);
EntityIdentifier waiveLoanAmount(LoanTransactionCommand command);
} }
@@ -1,34 +1,15 @@
package org.mifosng.ui; package org.mifosng.ui;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.configuration.ApplicationConfigurationService; import org.mifosng.configuration.ApplicationConfigurationService;
import org.mifosng.data.ClientList;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.ErrorResponse;
import org.mifosng.data.ErrorResponseList;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.ui.loanproduct.ClientValidationException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth.consumer.ProtectedResourceDetails; import org.springframework.security.oauth.consumer.ProtectedResourceDetails;
import org.springframework.security.oauth.consumer.client.OAuthRestTemplate; import org.springframework.security.oauth.consumer.client.OAuthRestTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
import com.thoughtworks.xstream.XStream;
@Service(value = "commonRestOperations") @Service(value = "commonRestOperations")
public class CommonRestOperationsImpl implements CommonRestOperations { public class CommonRestOperationsImpl implements CommonRestOperations {
@@ -65,231 +46,12 @@ public class CommonRestOperationsImpl implements CommonRestOperations {
this.oauthRestServiceTemplate = new OAuthRestTemplate(resource); this.oauthRestServiceTemplate = new OAuthRestTemplate(resource);
} }
private HttpEntity<ClientList> emptyRequest() { private HttpEntity<Object> emptyRequest() {
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml"); requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml"); requestHeaders.set("Content-Type", "application/xml");
HttpEntity<ClientList> requestEntity = new HttpEntity<ClientList>( HttpEntity<Object> requestEntity = new HttpEntity<Object>(requestHeaders);
requestHeaders);
return requestEntity; return requestEntity;
} }
private ErrorResponseList parseErrors(HttpStatusCodeException e) {
XStream xstream = new XStream();
xstream.alias("errorResponseList", ErrorResponseList.class);
xstream.alias("errorResponse", ErrorResponse.class);
ErrorResponseList errorList = new ErrorResponseList();
if (HttpStatus.BAD_REQUEST.equals(e.getStatusCode())) {
errorList = (ErrorResponseList) xstream.fromXML(e
.getResponseBodyAsString());
} else if (HttpStatus.NOT_FOUND.equals(e.getStatusCode())) {
List<ErrorResponse> errors = new ArrayList<ErrorResponse>();
errors.add(new ErrorResponse(e.getMessage(), "error", e
.getMessage()));
errorList = new ErrorResponseList(errors);
} else if (HttpStatus.UNAUTHORIZED.equals(e.getStatusCode())) {
throw new AccessDeniedException(e.getMessage());
} else {
throw e;
}
return errorList;
}
@Override
public EntityIdentifier disburseLoan(
final LoanStateTransitionCommand command) {
try {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/loan/disburse"));
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
.postForEntity(restUri,
loanStateTransitionApplicationRequest(command),
EntityIdentifier.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public EntityIdentifier undloLoanDisbursal(
final UndoLoanDisbursalCommand command) {
try {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/loan/undodisbursal"));
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
.postForEntity(restUri, undoLoanDisbursalRequest(command),
EntityIdentifier.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public LoanRepaymentData retrieveNewLoanRepaymentDetails(Long loanId) {
try {
URI restUri = URI.create(getBaseServerUrl()
.concat("api/protected/loan/").concat(loanId.toString())
.concat("/repayment/"));
ResponseEntity<LoanRepaymentData> s = this.oauthRestServiceTemplate
.exchange(restUri, HttpMethod.GET, emptyRequest(),
LoanRepaymentData.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public LoanRepaymentData retrieveLoanRepaymentDetails(Long loanId,
Long repaymentId) {
try {
URI restUri = URI.create(getBaseServerUrl()
.concat("api/protected/loan/").concat(loanId.toString())
.concat("/repayment/").concat(repaymentId.toString()));
ResponseEntity<LoanRepaymentData> s = this.oauthRestServiceTemplate
.exchange(restUri, HttpMethod.GET, emptyRequest(),
LoanRepaymentData.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public EntityIdentifier makeLoanRepayment(
final LoanTransactionCommand command) {
try {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/loan/repayment"));
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
.postForEntity(restUri, loanTransactionRequest(command),
EntityIdentifier.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public EntityIdentifier adjustLoanRepayment(
AdjustLoanTransactionCommand command) {
try {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/loan/repayment/adjust"));
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
.postForEntity(restUri,
adjustLoanRepaymentRequest(command),
EntityIdentifier.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public LoanRepaymentData retrieveNewLoanWaiverDetails(Long loanId) {
try {
URI restUri = URI.create(getBaseServerUrl()
.concat("api/protected/loan/").concat(loanId.toString())
.concat("/waive/"));
ResponseEntity<LoanRepaymentData> s = this.oauthRestServiceTemplate
.exchange(restUri, HttpMethod.GET, emptyRequest(),
LoanRepaymentData.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
@Override
public EntityIdentifier waiveLoanAmount(LoanTransactionCommand command) {
try {
URI restUri = URI.create(getBaseServerUrl().concat(
"api/protected/loan/waive"));
ResponseEntity<EntityIdentifier> s = this.oauthRestServiceTemplate
.postForEntity(restUri, loanTransactionRequest(command),
EntityIdentifier.class);
return s.getBody();
} catch (HttpStatusCodeException e) {
ErrorResponseList errorList = parseErrors(e);
throw new ClientValidationException(errorList.getErrors());
}
}
private HttpEntity<LoanTransactionCommand> loanTransactionRequest(
final LoanTransactionCommand command) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml");
return new HttpEntity<LoanTransactionCommand>(command, requestHeaders);
}
private HttpEntity<AdjustLoanTransactionCommand> adjustLoanRepaymentRequest(
final AdjustLoanTransactionCommand command) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml");
return new HttpEntity<AdjustLoanTransactionCommand>(command,
requestHeaders);
}
private HttpEntity<UndoLoanDisbursalCommand> undoLoanDisbursalRequest(
final UndoLoanDisbursalCommand command) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml");
return new HttpEntity<UndoLoanDisbursalCommand>(command, requestHeaders);
}
private HttpEntity<UndoLoanApprovalCommand> undoLoanApprovalRequest(
final UndoLoanApprovalCommand command) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml");
return new HttpEntity<UndoLoanApprovalCommand>(command, requestHeaders);
}
private HttpEntity<LoanStateTransitionCommand> loanStateTransitionApplicationRequest(
final LoanStateTransitionCommand command) {
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("Accept", "application/xml");
requestHeaders.set("Content-Type", "application/xml");
return new HttpEntity<LoanStateTransitionCommand>(command,
requestHeaders);
}
} }
@@ -1,34 +0,0 @@
package org.mifosng.ui;
import org.mifosng.data.ErrorResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestClientException;
public class Jax2bRestClientException extends RestClientException {
private final HttpStatus statusCode;
private final MediaType contentType;
private final ErrorResponse errorResponse;
public Jax2bRestClientException(final HttpStatus statusCode,
final MediaType contentType, final ErrorResponse errorResponse) {
super(statusCode.name() + ": on client http rest request.");
this.statusCode = statusCode;
this.contentType = contentType;
this.errorResponse = errorResponse;
}
public HttpStatus getStatusCode() {
return this.statusCode;
}
public MediaType getContentType() {
return this.contentType;
}
public ErrorResponse getErrorResponse() {
return this.errorResponse;
}
}
@@ -1,34 +0,0 @@
package org.mifosng.ui;
import org.mifosng.data.ErrorResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestClientException;
public class Jax2bRestServerException extends RestClientException {
private final HttpStatus statusCode;
private final MediaType contentType;
private final ErrorResponse errorResponse;
public Jax2bRestServerException(final HttpStatus statusCode,
final MediaType contentType, final ErrorResponse errorResponse) {
super(statusCode.name() + ": on client http rest request.");
this.statusCode = statusCode;
this.contentType = contentType;
this.errorResponse = errorResponse;
}
public HttpStatus getStatusCode() {
return this.statusCode;
}
public MediaType getContentType() {
return this.contentType;
}
public ErrorResponse getErrorResponse() {
return this.errorResponse;
}
}
@@ -1,49 +0,0 @@
package org.mifosng.ui;
import java.io.IOException;
import org.mifosng.data.ErrorResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClientException;
public class JaxRs311ErrorResponseHandler implements ResponseErrorHandler {
private final ResponseErrorHandler delegateResponseErrorHandler;
public JaxRs311ErrorResponseHandler(
final ResponseErrorHandler delegateResponseErrorHandler) {
this.delegateResponseErrorHandler = delegateResponseErrorHandler;
}
@Override
public boolean hasError(final ClientHttpResponse response) throws IOException {
return this.delegateResponseErrorHandler.hasError(response);
}
@Override
public void handleError(final ClientHttpResponse response) throws IOException {
HttpStatus statusCode = response.getStatusCode();
MediaType contentType = response.getHeaders().getContentType();
Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();
ErrorResponse errorResponse = (ErrorResponse) converter.read(
ErrorResponse.class, response);
switch (statusCode.series()) {
case CLIENT_ERROR:
throw new Jax2bRestClientException(statusCode, contentType, errorResponse);
case SERVER_ERROR:
throw new Jax2bRestServerException(statusCode, contentType,
errorResponse);
default:
throw new RestClientException("Unknown status code [" + statusCode
+ "]");
}
}
}
@@ -1,15 +1,9 @@
package org.mifosng.ui.configuration; package org.mifosng.ui.configuration;
import java.util.Collection;
import javax.servlet.http.HttpServletResponse;
import org.mifosng.configuration.ApplicationConfigurationService; import org.mifosng.configuration.ApplicationConfigurationService;
import org.mifosng.configuration.OAuthProviderDetails; import org.mifosng.configuration.OAuthProviderDetails;
import org.mifosng.data.ErrorResponse;
import org.mifosng.oauth.RefreshableProtectedResourceDetailsService; import org.mifosng.oauth.RefreshableProtectedResourceDetailsService;
import org.mifosng.ui.CommonRestOperations; import org.mifosng.ui.CommonRestOperations;
import org.mifosng.ui.loanproduct.ClientValidationException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.oauth.consumer.ProtectedResourceDetailsService; import org.springframework.security.oauth.consumer.ProtectedResourceDetailsService;
@@ -18,7 +12,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@@ -44,17 +37,6 @@ public class ConfigurationController {
return "unAuthorizedAction"; return "unAuthorizedAction";
} }
@ExceptionHandler(ClientValidationException.class)
public @ResponseBody
Collection<ErrorResponse> validationException(ClientValidationException ex,
HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setContentType("application/json");
return ex.getValidationErrors();
}
@ModelAttribute("oauthSettingsFormBean") @ModelAttribute("oauthSettingsFormBean")
@RequestMapping(value = "oauth/configuration/edit", method = RequestMethod.GET) @RequestMapping(value = "oauth/configuration/edit", method = RequestMethod.GET)
public ModelAndView showOAuthConfiguration() { public ModelAndView showOAuthConfiguration() {
@@ -1,82 +0,0 @@
package org.mifosng.ui.loan;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.data.CurrencyData;
import org.mifosng.data.MoneyData;
import org.mifosng.ui.CommonRestOperations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @deprecated - some initial work around cashflow for CreoCore that can be deleted later.
*/
@Deprecated
@Controller
public class CashflowController {
// private final CommonRestOperations commonRestOperations;
@Autowired
public CashflowController(final CommonRestOperations commonRestOperations) {
// this.commonRestOperations = commonRestOperations;
}
@RequestMapping(value = "/portfolio/client/{clientId}/cashflow/new", method = RequestMethod.GET)
public String submitNewCashflowAnalysis(@PathVariable("clientId") final Long clientId) {
return "redirect:/createCashflowAnalysis?loanId=0&clientId={clientId}";
}
// called from webflow
public void populateLoanDetailsForCashflow(final CashflowFormBean formBean, Long loanId, Long clientId) {
formBean.setBusinessName("Fixed Example Business (Sole Trader)");
formBean.setClientName("Fixed Example Client");
CurrencyData currency = new CurrencyData("XOF", "", 0, "CFA", "currency.XOF");
MoneyData amount = MoneyData.of(currency, BigDecimal.valueOf(0));
formBean.setExpectedLoanTerm(12);
List<MultiTermExpense> investments = new ArrayList<MultiTermExpense>();
investments.add(new MultiTermExpense("equipment purchase", Integer.valueOf(0), amount.getAmount(), formBean.getExpectedLoanTerm()));
investments.add(new MultiTermExpense("Option two", Integer.valueOf(0), amount.getAmount(), formBean.getExpectedLoanTerm()));
investments.add(new MultiTermExpense("Option three", Integer.valueOf(0), amount.getAmount(), formBean.getExpectedLoanTerm()));
formBean.setInvestments(investments);
List<OneOffExpense> fixedExpenses = new ArrayList<OneOffExpense>();
fixedExpenses.add(new OneOffExpense("Fixed one", amount.getAmount()));
fixedExpenses.add(new OneOffExpense("Fixed two", amount.getAmount()));
fixedExpenses.add(new OneOffExpense("Fixed three", amount.getAmount()));
formBean.setFixedExpenses(fixedExpenses);
List<UnitInformationOfProduct> products = new ArrayList<UnitInformationOfProduct>();
products.add(new UnitInformationOfProduct("First Product", Integer.valueOf(10), BigDecimal.valueOf(Double.valueOf("12.00")), BigDecimal.valueOf(Double.valueOf("23.00"))));
products.add(new UnitInformationOfProduct("Second Product", Integer.valueOf(500), BigDecimal.valueOf(Double.valueOf("10.00")), BigDecimal.valueOf(Double.valueOf("15.00"))));
formBean.setProducts(products);
// List<ClientReadModel> individualClients = new ArrayList<ClientReadModel>(this.commonRestOperations.retrieveLoan);
// List<LoanProductReadModel> loanProducts = new ArrayList<LoanProductReadModel>(
// this.commonRestOperations.retrieveAllLoanProducts());
//
// loanFormBean.setApplicantOptions(individualClients);
// if (individualClients.size() == 1) {
// loanFormBean.setSelectedApplicantOption(individualClients.get(0)
// .getId());
// }
//
// loanFormBean.setLoanProductOptions(loanProducts);
// if (loanProducts.size() == 1) {
// loanFormBean.setSelectedLoanProductOption(loanProducts.get(0)
// .getId());
// }
}
}
@@ -1,76 +0,0 @@
package org.mifosng.ui.loan;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class CashflowFormBean implements Serializable {
private String clientName;
private String businessName;
private Integer expectedLoanTerm = Integer.valueOf(12);
private List<MultiTermExpense> investments = new ArrayList<MultiTermExpense>();
private List<OneOffExpense> fixedExpenses = new ArrayList<OneOffExpense>();
private List<UnitInformationOfProduct> products = new ArrayList<UnitInformationOfProduct>();
private Number entrepreneurInput = Double.valueOf("0");
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public String getBusinessName() {
return businessName;
}
public void setBusinessName(String businessName) {
this.businessName = businessName;
}
public List<OneOffExpense> getFixedExpenses() {
return fixedExpenses;
}
public void setFixedExpenses(List<OneOffExpense> fixedExpenses) {
this.fixedExpenses = fixedExpenses;
}
public List<UnitInformationOfProduct> getProducts() {
return products;
}
public void setProducts(List<UnitInformationOfProduct> products) {
this.products = products;
}
public Integer getExpectedLoanTerm() {
return expectedLoanTerm;
}
public void setExpectedLoanTerm(Integer expectedLoanTerm) {
this.expectedLoanTerm = expectedLoanTerm;
}
public List<MultiTermExpense> getInvestments() {
return investments;
}
public void setInvestments(List<MultiTermExpense> investments) {
this.investments = investments;
}
public Number getEntrepreneurInput() {
return entrepreneurInput;
}
public void setEntrepreneurInput(Number entrepreneurInput) {
this.entrepreneurInput = entrepreneurInput;
}
}
@@ -1,191 +0,0 @@
package org.mifosng.ui.loan;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.ErrorResponse;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.ui.CommonRestOperations;
import org.mifosng.ui.loanproduct.ClientValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
@Controller
public class LoanTransactionController {
private final CommonRestOperations commonRestOperations;
@Autowired
public LoanTransactionController(final CommonRestOperations commonRestOperations) {
this.commonRestOperations = commonRestOperations;
}
@ExceptionHandler(AccessDeniedException.class)
public String accessDeniedException() {
return "unAuthorizedAction";
}
@ExceptionHandler(ClientValidationException.class)
public @ResponseBody Collection<ErrorResponse> validationException(ClientValidationException ex, HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
response.setContentType("application/json");
return ex.getValidationErrors();
}
private LocalDate parseStringToLocalDate(String eventDate, String dateFieldIdentifier) {
LocalDate eventLocalDate = null;
if (StringUtils.isNotBlank(eventDate)) {
try {
Locale locale = LocaleContextHolder.getLocale();
eventLocalDate = DateTimeFormat.forPattern("dd MMMM yyyy").withLocale(locale).parseLocalDate(eventDate.toLowerCase(locale));
} catch (IllegalArgumentException e) {
List<ErrorResponse> validationErrors = new ArrayList<ErrorResponse>();
validationErrors.add(new ErrorResponse("validation.msg.invalid.date.format", dateFieldIdentifier, eventDate));
throw new ClientValidationException(validationErrors);
}
}
return eventLocalDate;
}
private BigDecimal parseStringToBigDecimal(String source) {
try {
BigDecimal number = null;
if (StringUtils.isNotBlank(source)) {
String sourceWithoutSpaces = source.replaceAll(" ", "");
Locale locale = LocaleContextHolder.getLocale();
NumberFormat format = NumberFormat.getNumberInstance(locale);
Number parsedNumber = format.parse(sourceWithoutSpaces);
number = BigDecimal.valueOf(Double.valueOf(parsedNumber
.doubleValue()));
}
return number;
} catch (ParseException e) {
List<ErrorResponse> validationErrors = new ArrayList<ErrorResponse>();
validationErrors.add(new ErrorResponse("validation.msg.invalid.number.format", "amount", source));
throw new ClientValidationException(validationErrors);
}
}
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/portfolio/loan/{loanId}/disburse", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody EntityIdentifier disburseLoan(
@PathVariable("loanId") final Long loanId,
@RequestParam(value="eventDate", required=false) String eventDate,
@RequestParam(value="comment", required=false) String comment) {
LocalDate disbursalDate = parseStringToLocalDate(eventDate, "eventDate");
LoanStateTransitionCommand command = new LoanStateTransitionCommand(loanId, disbursalDate, comment);
return this.commonRestOperations.disburseLoan(command);
}
@RequestMapping(value = "/portfolio/loan/{loanId}/undodisbursal", method = RequestMethod.POST)
public String undoLoanDisbursal(@PathVariable final Long loanId) {
UndoLoanDisbursalCommand command = new UndoLoanDisbursalCommand(loanId);
EntityIdentifier clientAccountId = this.commonRestOperations
.undloLoanDisbursal(command);
return "redirect:/portfolio/client/" + clientAccountId.getEntityId();
}
@RequestMapping(consumes="application/json", produces="application/json", value ="/portfolio/loan/{loanId}/repayment", method = RequestMethod.GET)
public @ResponseBody LoanRepaymentData retrieveNewLoanRepaymentDetail(@PathVariable("loanId") final Long loanId) {
return this.commonRestOperations.retrieveNewLoanRepaymentDetails(loanId);
}
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/portfolio/loan/{loanId}/repayment", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody EntityIdentifier enterRepaymentOnLoan(
@PathVariable("loanId") final Long loanId,
@RequestParam(value="transactionDate", required=false) String transactionDate,
@RequestParam(value="transactionComment", required=false) String transactionComment,
@RequestParam(value="transactionAmount", required=false) String transactionAmount) {
LocalDate repaymentDate = parseStringToLocalDate(transactionDate, "transactionDate");
BigDecimal repaymentAmount = parseStringToBigDecimal(transactionAmount);
LoanTransactionCommand command = new LoanTransactionCommand(loanId,
repaymentDate, transactionComment, repaymentAmount);
return this.commonRestOperations.makeLoanRepayment(command);
}
@RequestMapping(consumes="application/json", produces="application/json", value = "/portfolio/loan/{loanId}/repayment/{repaymentId}/adjust", method = RequestMethod.GET)
public @ResponseBody LoanRepaymentData retrieveLoanRepayment(@PathVariable("loanId") final Long loanId, @PathVariable("repaymentId") final Long repaymentId) {
return this.commonRestOperations.retrieveLoanRepaymentDetails(loanId, repaymentId);
}
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/portfolio/loan/{loanId}/repayment/{repaymentId}/adjust", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody EntityIdentifier adjustPreviousRepaymentOnLoan(
@PathVariable("loanId") final Long loanId, @PathVariable("repaymentId") final Long repaymentId,
@RequestParam(value="transactionDate", required=false) String transactionDate,
@RequestParam(value="transactionComment", required=false) String transactionComment,
@RequestParam(value="transactionAmount", required=false) String transactionAmount) {
LocalDate repaymentDate = parseStringToLocalDate(transactionDate, "transactionDate");
BigDecimal repaymentAmount = parseStringToBigDecimal(transactionAmount);
AdjustLoanTransactionCommand command = new AdjustLoanTransactionCommand(loanId, repaymentId, repaymentDate, transactionComment, repaymentAmount);
return this.commonRestOperations.adjustLoanRepayment(command);
}
@RequestMapping(consumes="application/json", produces="application/json", value = "/portfolio/loan/{loanId}/waive", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody LoanRepaymentData retrievePossibleWaiveDetails(@PathVariable("loanId") final Long loanId) {
return this.commonRestOperations.retrieveNewLoanWaiverDetails(loanId);
}
@RequestMapping(consumes="application/x-www-form-urlencoded", produces="application/json", value = "/portfolio/loan/{loanId}/waive", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.OK)
public @ResponseBody EntityIdentifier waiveLoanAmount(
@PathVariable("loanId") final Long loanId,
@RequestParam(value="transactionDate", required=false) String transactionDate,
@RequestParam(value="transactionComment", required=false) String transactionComment,
@RequestParam(value="transactionAmount", required=false) String transactionAmount) {
LocalDate waiveDate = parseStringToLocalDate(transactionDate, "transactionDate");
BigDecimal waiveAmount = parseStringToBigDecimal(transactionAmount);
LoanTransactionCommand command = new LoanTransactionCommand(loanId,
waiveDate, transactionComment, waiveAmount);
return this.commonRestOperations.waiveLoanAmount(command);
}
}
@@ -1,79 +0,0 @@
package org.mifosng.ui.loan;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class MultiTermExpense implements Serializable {
private String name;
private String description;
private Integer fullTermInMonths;
private Number fullAmount;
private Integer applicableTermInMonths;
private Number applicableAmount;
public MultiTermExpense() {
//
}
public MultiTermExpense(String name, Integer fullTermInMonths, BigDecimal fullAmount, Integer applicableTermInMonths) {
this.name = name;
this.fullTermInMonths = fullTermInMonths;
this.fullAmount = fullAmount;
this.applicableTermInMonths = applicableTermInMonths;
this.applicableAmount = fullAmount;
BigDecimal fullAmountAsDecimal = BigDecimal.valueOf(this.fullAmount.longValue());
if (!fullAmountAsDecimal.equals(BigDecimal.ZERO)) {
this.applicableAmount = fullAmountAsDecimal.divide(BigDecimal.valueOf(applicableTermInMonths.longValue()), RoundingMode.HALF_EVEN);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getFullTermInMonths() {
return fullTermInMonths;
}
public void setFullTermInMonths(Integer fullTermInMonths) {
this.fullTermInMonths = fullTermInMonths;
}
public Number getFullAmount() {
return fullAmount;
}
public void setFullAmount(Number fullAmount) {
this.fullAmount = fullAmount;
}
public Integer getApplicableTermInMonths() {
return applicableTermInMonths;
}
public void setApplicableTermInMonths(Integer applicableTermInMonths) {
this.applicableTermInMonths = applicableTermInMonths;
}
public Number getApplicableAmount() {
return applicableAmount;
}
public void setApplicableAmount(Number applicableAmount) {
this.applicableAmount = applicableAmount;
}
}
@@ -1,45 +0,0 @@
package org.mifosng.ui.loan;
import java.io.Serializable;
import java.math.BigDecimal;
public class OneOffExpense implements Serializable {
private String name;
private String description;
private Number amount;
public OneOffExpense() {
//
}
public OneOffExpense(String name, BigDecimal amount) {
this.name = name;
this.amount = amount;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Number getAmount() {
return amount;
}
public void setAmount(Number amount) {
this.amount = amount;
}
}
@@ -1,57 +0,0 @@
package org.mifosng.ui.loan;
import java.io.Serializable;
import java.math.BigDecimal;
public class UnitInformationOfProduct implements Serializable {
private String name;
private Number unitsSold = Integer.valueOf(0);
private Number costPerUnit = BigDecimal.ZERO;
private Number pricePerUnit = BigDecimal.ZERO;
public UnitInformationOfProduct() {
//
}
public UnitInformationOfProduct(String name, Integer unitsSold,
BigDecimal costPerUnit, BigDecimal pricePerUnit) {
this.name = name;
this.unitsSold = unitsSold;
this.costPerUnit = costPerUnit;
this.pricePerUnit = pricePerUnit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Number getUnitsSold() {
return unitsSold;
}
public void setUnitsSold(Number unitsSold) {
this.unitsSold = unitsSold;
}
public Number getCostPerUnit() {
return costPerUnit;
}
public void setCostPerUnit(Number costPerUnit) {
this.costPerUnit = costPerUnit;
}
public Number getPricePerUnit() {
return pricePerUnit;
}
public void setPricePerUnit(Number pricePerUnit) {
this.pricePerUnit = pricePerUnit;
}
}
@@ -1,19 +0,0 @@
package org.mifosng.ui.loanproduct;
import java.util.List;
import org.mifosng.data.ErrorResponse;
public class ClientValidationException extends RuntimeException {
private final List<ErrorResponse> validationErrors;
public ClientValidationException(List<ErrorResponse> validationErrors) {
super("Validation errors exist");
this.validationErrors = validationErrors;
}
public List<ErrorResponse> getValidationErrors() {
return validationErrors;
}
}
@@ -508,6 +508,14 @@ $(document).ready(function() {
offsetToApprovalDate = data.maxApprovedOnOffsetFromToday; offsetToApprovalDate = data.maxApprovedOnOffsetFromToday;
offsetToDisbursalDate = data.maxDisbursedOnOffsetFromToday; offsetToDisbursalDate = data.maxDisbursedOnOffsetFromToday;
var $loantabs = $(".loantabs").tabs({
"show": function(event, ui) {
var curTab = $('#newtabs .ui-tabs-panel:not(.ui-tabs-hide)');
var curTabID = curTab.prop("id")
}
});
$('.rejectloan').button().click(function(e) { $('.rejectloan').button().click(function(e) {
var linkId = this.id; var linkId = this.id;
var loanId = linkId.replace("rejectbtn", ""); var loanId = linkId.replace("rejectbtn", "");
@@ -579,7 +587,7 @@ $(document).ready(function() {
var linkId = this.id; var linkId = this.id;
var loanId = linkId.replace("undodisbursalbtn", ""); var loanId = linkId.replace("undodisbursalbtn", "");
var postUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '?command=undodisbursal'; var postUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '/undo?command=undodisbursal';
var width = 400; var width = 400;
var height = 150; var height = 150;
popupConfirmationDialogAndPost(postUrl, 'POST', 'dialog.title.undo.loan.disbursal', width, height, currentTabIndex); popupConfirmationDialogAndPost(postUrl, 'POST', 'dialog.title.undo.loan.disbursal', width, height, currentTabIndex);
@@ -605,54 +613,73 @@ $(document).ready(function() {
var linkId = this.id; var linkId = this.id;
var loanId = linkId.replace("repaymentbtn", ""); var loanId = linkId.replace("repaymentbtn", "");
var url = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId; var getUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '/transactions/template?transactionType=repayment';
var postUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '/transactions?transactionType=repayment';
var templateSelector = "#transactionLoanFormTemplate"; var templateSelector = "#transactionLoanFormTemplate";
var width = 500; var width = 500;
var height = 350; var height = 350;
var defaultOffset = offsetToApprovalDate; var defaultOffset = offsetToApprovalDate;
popupDialogWithFormView(url, 'dialog.title.loan.repayment', templateSelector, width, height, currentTabIndex, offsetToSubmittedDate, defaultOffset, maxOffset)
var saveSuccessFunction = function(data, textStatus, jqXHR) {
$("#dialog-form").dialog("close");
$newtabs.tabs('load', currentTabIndex);
}
popupDialogWithFormView(getUrl, postUrl, 'POST', "dialog.title.loan.repayment", templateSelector, width, height, saveSuccessFunction);
//popupDialogWithFormView(getUrl, postUrl, 'POST', 'dialog.title.loan.repayment', templateSelector, width, height, currentTabIndex, offsetToSubmittedDate, defaultOffset, maxOffset)
e.preventDefault(); e.preventDefault();
}); });
$('button.repaymentloan span').text(jQuery.i18n.prop('dialog.button.loan.repayment')); $('button.repaymentloan span').text(jQuery.i18n.prop('dialog.button.loan.repayment'));
$('.waiveloan').button().click(function(e) {
var linkId = this.id;
var loanId = linkId.replace("waivebtn", "");
var getUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '/transactions/template?transactionType=waiver';
var postUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '/transactions?transactionType=waiver';
var templateSelector = "#transactionLoanFormTemplate";
var width = 500;
var height = 350;
var defaultOffset = offsetToApprovalDate;
var saveSuccessFunction = function(data, textStatus, jqXHR) {
$("#dialog-form").dialog("close");
$newtabs.tabs('load', currentTabIndex);
}
popupDialogWithFormView(getUrl, postUrl, 'POST', "dialog.title.waive.loan", templateSelector, width, height, saveSuccessFunction);
//popupDialogWithFormView(getUrl, postUrl, 'POST', 'dialog.title.waive.loan', templateSelector, width, height, currentTabIndex, offsetToSubmittedDate, defaultOffset, maxOffset)
e.preventDefault();
});
$('button.waiveloan span').text(jQuery.i18n.prop('dialog.button.loan.waive'));
$('.adjustloanrepayment').button().click(function(e) { $('.adjustloanrepayment').button().click(function(e) {
var linkId = this.id; var linkId = this.id;
var loanAndRepaymentId = linkId.replace("adjustrepaymentbtn", ""); var loanAndRepaymentId = linkId.replace("adjustrepaymentbtn", "");
var ids = loanAndRepaymentId.split("_"); var ids = loanAndRepaymentId.split("_");
var loanId = ids[0];
var transactionId = ids[1];
var getAndPutUrl = 'http://localhost:8080/mifosng-provider/api/v1/loans/' + loanId + '/transactions/' + transactionId;
var url = '${rootContext}portfolio/loan/' + ids[0] + '/repayment/' + ids[1] + '/adjust';
var templateSelector = "#transactionLoanFormTemplate"; var templateSelector = "#transactionLoanFormTemplate";
var width = 500; var width = 500;
var height = 350; var height = 350;
var defaultOffset = offsetToApprovalDate; var defaultOffset = offsetToApprovalDate;
popupDialogWithFormView(url, 'dialog.title.adjust.loan.repayment', templateSelector, width, height, currentTabIndex, offsetToSubmittedDate, defaultOffset, maxOffset)
var saveSuccessFunction = function(data, textStatus, jqXHR) {
$("#dialog-form").dialog("close");
$newtabs.tabs('load', currentTabIndex);
}
popupDialogWithFormView(getAndPutUrl, getAndPutUrl, 'PUT', "dialog.title.adjust.loan.repayment", templateSelector, width, height, saveSuccessFunction);
// popupDialogWithFormView(getAndPutUrl, getAndPutUrl, 'PUT', 'dialog.title.adjust.loan.repayment', templateSelector, width, height, currentTabIndex, offsetToSubmittedDate, defaultOffset, maxOffset)
e.preventDefault(); e.preventDefault();
}); });
$('button.adjustloanrepayment span').text(jQuery.i18n.prop('dialog.button.adjust.loan.repayment')); $('button.adjustloanrepayment span').text(jQuery.i18n.prop('dialog.button.adjust.loan.repayment'));
$('.waiveloan').button().click(function(e) {
var linkId = this.id;
var loanId = linkId.replace("waivebtn", "");
var url = '${rootContext}portfolio/loan/' + loanId + '/waive';
var templateSelector = "#transactionLoanFormTemplate";
var width = 500;
var height = 350;
var defaultOffset = offsetToApprovalDate;
popupDialogWithFormView(url, 'dialog.title.waive.loan', templateSelector, width, height, currentTabIndex, offsetToSubmittedDate, defaultOffset, maxOffset)
e.preventDefault();
});
$('button.waiveloan span').text(jQuery.i18n.prop('dialog.button.loan.waive'));
var $loantabs = $(".loantabs").tabs({
"show": function(event, ui) {
var curTab = $('#newtabs .ui-tabs-panel:not(.ui-tabs-hide)');
var curTabID = curTab.prop("id")
}
});
// additional data // additional data
var additionalFieldsParams = { var additionalFieldsParams = {
url: "http://localhost:8080/mifosng-provider/", url: "http://localhost:8080/mifosng-provider/",
@@ -816,14 +816,15 @@
<form id="entityform"> <form id="entityform">
<div id="formerrors"></div> <div id="formerrors"></div>
<label for="transactionDate"><spring:message code="label.loan.transaction.on"/></label> <input type="hidden" id="dateFormat" name="dateFormat" value="dd MMMM yyyy" />
<input id="transactionDate" name="transactionDate" cssClass="text ui-widget-content ui-corner-all" title="" class="datepickerfield" value="{{=$ctx.globalDate(date)}}"/> <label for="transactionDateFormatted"><spring:message code="label.loan.transaction.on"/></label>
<input id="transactionDateFormatted" name="transactionDateFormatted" cssClass="text ui-widget-content ui-corner-all" title="" class="datepickerfield" value="{{=$ctx.globalDate(date)}}"/>
<label for="transactionAmount"><spring:message code="label.loan.transaction.amount"/></label> <label for="transactionAmountFormatted"><spring:message code="label.loan.transaction.amount"/></label>
<input id="transactionAmount" name="transactionAmount" cssClass="text ui-widget-content ui-corner-all" title="" value="{{=$ctx.money(total)}}" /> <input id="transactionAmountFormatted" name="transactionAmountFormatted" cssClass="text ui-widget-content ui-corner-all" title="" value="{{=$ctx.money(total)}}" />
<label for="transactionComment"><spring:message code="label.loan.action.note"/></label> <label for="comment"><spring:message code="label.loan.action.note"/></label>
<textarea rows="3" cols="53" id="transactionComment" name="transactionComment" cssClass="text ui-widget-content ui-corner-all"></textarea> <textarea rows="3" cols="53" id="comment" name="comment" cssClass="text ui-widget-content ui-corner-all"></textarea>
</form> </form>
</script> </script>
@@ -29,12 +29,12 @@ public class AdjustLoanTransactionCommandValidator {
dataValidationErrors.add(error); dataValidationErrors.add(error);
} }
if (command.getPaymentDate() == null) { if (command.getTransactionDate() == null) {
ErrorResponse error = new ErrorResponse("validation.msg.loan.repayment.date.cannot.be.blank", "paymentDate"); ErrorResponse error = new ErrorResponse("validation.msg.loan.repayment.date.cannot.be.blank", "paymentDate");
dataValidationErrors.add(error); dataValidationErrors.add(error);
} }
if (command.getPaymentAmount() == null || command.getPaymentAmount().doubleValue() < 0) { if (command.getTransactionAmount() == null || command.getTransactionAmount().doubleValue() < 0) {
ErrorResponse error = new ErrorResponse("validation.msg.loan.adjustment.must.be.zero.or.greater", "paymentAmount"); ErrorResponse error = new ErrorResponse("validation.msg.loan.adjustment.must.be.zero.or.greater", "paymentAmount");
dataValidationErrors.add(error); dataValidationErrors.add(error);
} }
@@ -247,9 +247,9 @@ public class ImportPlatformServiceImpl implements ImportPlatformService {
for (LoanTransactionCommand repaymentDetail : command.getRepayments()) { for (LoanTransactionCommand repaymentDetail : command.getRepayments()) {
Loan loan = findLoanByIdentifier(allLoans, repaymentDetail.getLoanId().toString()); Loan loan = findLoanByIdentifier(allLoans, repaymentDetail.getLoanId().toString());
Money repaymentAmount = Money.of(loan.getCurrency(), repaymentDetail.getPaymentAmount()); Money repaymentAmount = Money.of(loan.getCurrency(), repaymentDetail.getTransactionAmount());
LoanTransaction loanRepayment = LoanTransaction.repayment(repaymentAmount, repaymentDetail.getPaymentDate()); LoanTransaction loanRepayment = LoanTransaction.repayment(repaymentAmount, repaymentDetail.getTransactionDate());
loan.makeRepayment(loanRepayment, loanLifecycleStateMachine); loan.makeRepayment(loanRepayment, loanLifecycleStateMachine);
} }
@@ -24,12 +24,12 @@ public class LoanTransactionValidator {
dataValidationErrors.add(error); dataValidationErrors.add(error);
} }
if (command.getPaymentDate() == null) { if (command.getTransactionDate() == null) {
ErrorResponse error = new ErrorResponse("validation.msg.loan.repayment.date.cannot.be.blank", "transactionDate"); ErrorResponse error = new ErrorResponse("validation.msg.loan.repayment.date.cannot.be.blank", "transactionDate");
dataValidationErrors.add(error); dataValidationErrors.add(error);
} }
if (command.getPaymentAmount() == null || command.getPaymentAmount().doubleValue() <= 0) { if (command.getTransactionAmount() == null || command.getTransactionAmount().doubleValue() <= 0) {
ErrorResponse error = new ErrorResponse("validation.msg.loan.repayment.must.be.greater.than.zero", "transactionAmount"); ErrorResponse error = new ErrorResponse("validation.msg.loan.repayment.must.be.greater.than.zero", "transactionAmount");
dataValidationErrors.add(error); dataValidationErrors.add(error);
} }
@@ -2,9 +2,7 @@ package org.mifosng.platform;
import org.mifosng.data.EntityIdentifier; import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand; import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.data.command.UpdateUsernamePasswordCommand; import org.mifosng.data.command.UpdateUsernamePasswordCommand;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -12,12 +10,6 @@ public interface WritePlatformService {
void updateUsernamePasswordOnFirstTimeLogin(UpdateUsernamePasswordCommand command); void updateUsernamePasswordOnFirstTimeLogin(UpdateUsernamePasswordCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DISBURSE_LOAN_ROLE', 'CAN_DISBURSE_LOAN_IN_THE_PAST_ROLE')")
EntityIdentifier disburseLoan(LoanStateTransitionCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_UNDO_LOAN_DISBURSAL_ROLE')")
public EntityIdentifier undloLoanDisbursal(UndoLoanDisbursalCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_MAKE_LOAN_REPAYMENT_ROLE', 'CAN_MAKE_LOAN_REPAYMENT_IN_THE_PAST_ROLE')") @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_MAKE_LOAN_REPAYMENT_ROLE', 'CAN_MAKE_LOAN_REPAYMENT_IN_THE_PAST_ROLE')")
public EntityIdentifier makeLoanRepayment(LoanTransactionCommand command); public EntityIdentifier makeLoanRepayment(LoanTransactionCommand command);
@@ -3,7 +3,6 @@ package org.mifosng.platform;
import static org.mifosng.platform.Specifications.loansThatMatch; import static org.mifosng.platform.Specifications.loansThatMatch;
import static org.mifosng.platform.Specifications.usersThatMatch; import static org.mifosng.platform.Specifications.usersThatMatch;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -11,18 +10,11 @@ import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosng.data.EntityIdentifier; import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.ErrorResponse; import org.mifosng.data.ErrorResponse;
import org.mifosng.data.LoanSchedule;
import org.mifosng.data.ScheduledLoanInstallment;
import org.mifosng.data.command.AdjustLoanTransactionCommand; import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand; import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.data.command.UpdateUsernamePasswordCommand; import org.mifosng.data.command.UpdateUsernamePasswordCommand;
import org.mifosng.platform.client.domain.Note; import org.mifosng.platform.client.domain.Note;
import org.mifosng.platform.client.domain.NoteRepository; import org.mifosng.platform.client.domain.NoteRepository;
import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.currency.domain.Money; import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.exceptions.ApplicationDomainRuleException; import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException; import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
@@ -33,13 +25,11 @@ import org.mifosng.platform.infrastructure.UsernameAlreadyExistsException;
import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine; import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine;
import org.mifosng.platform.loan.domain.Loan; import org.mifosng.platform.loan.domain.Loan;
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine; import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
import org.mifosng.platform.loan.domain.LoanRepaymentScheduleInstallment;
import org.mifosng.platform.loan.domain.LoanRepository; import org.mifosng.platform.loan.domain.LoanRepository;
import org.mifosng.platform.loan.domain.LoanStatus; import org.mifosng.platform.loan.domain.LoanStatus;
import org.mifosng.platform.loan.domain.LoanStatusRepository; import org.mifosng.platform.loan.domain.LoanStatusRepository;
import org.mifosng.platform.loan.domain.LoanTransaction; import org.mifosng.platform.loan.domain.LoanTransaction;
import org.mifosng.platform.loan.domain.LoanTransactionRepository; import org.mifosng.platform.loan.domain.LoanTransactionRepository;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.loan.service.CalculationPlatformService; import org.mifosng.platform.loan.service.CalculationPlatformService;
import org.mifosng.platform.user.domain.AppUser; import org.mifosng.platform.user.domain.AppUser;
import org.mifosng.platform.user.domain.AppUserRepository; import org.mifosng.platform.user.domain.AppUserRepository;
@@ -141,128 +131,6 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
return Arrays.asList(errorResponse); return Arrays.asList(errorResponse);
} }
@Transactional
@Override
public EntityIdentifier disburseLoan(final LoanStateTransitionCommand command) {
AppUser currentUser = extractAuthenticatedUser();
LoanStateTransitionCommandValidator validator = new LoanStateTransitionCommandValidator(command);
validator.validate();
Loan loan = this.loanRepository.findOne(loansThatMatch(
currentUser.getOrganisation(), command.getLoanId()));
if (loan == null) {
throw new ApplicationDomainRuleException(loanIdentifierDoesNotExistError(command.getLoanId()), "No loan exists with id: " + command.getLoanId());
}
if (this.isBeforeToday(command.getEventDate()) && currentUser.canNotDisburseLoanInPast()) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission.to.disburse.loan.in.past", "eventDate");
throw new ApplicationDomainRuleException(Arrays.asList(errorResponse));
}
LocalDate disbursedOn = command.getEventDate();
String comment = command.getComment();
LocalDate actualDisbursementDate = new LocalDate(disbursedOn);
if (loan.isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate)) {
LocalDate repaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate();
LocalDate interestCalculatedFromDate = loan.getInterestCalculatedFromDate();
Number principalAsDecimal = loan.getLoanRepaymentScheduleDetail().getPrincipal().getAmount();
String currencyCode = loan.getLoanRepaymentScheduleDetail().getPrincipal().getCurrencyCode();
int currencyDigits = loan.getLoanRepaymentScheduleDetail().getPrincipal().getCurrencyDigitsAfterDecimal();
Number interestRatePerYear = loan.getLoanRepaymentScheduleDetail().getAnnualNominalInterestRate();
Integer numberOfInstallments = loan.getLoanRepaymentScheduleDetail().getNumberOfRepayments();
Integer repaidEvery = loan.getLoanRepaymentScheduleDetail().getRepayEvery();
Integer selectedRepaymentFrequency = loan.getLoanRepaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue();
Integer selectedRepaymentSchedule = loan.getLoanRepaymentScheduleDetail().getAmortizationMethod().getValue();
// use annual percentage rate to re-calculate loan schedule for late disbursement
Number interestRatePerPeriod = interestRatePerYear;
Integer interestRateFrequencyMethod = PeriodFrequencyType.YEARS.getValue();
Integer interestMethod = loan.getLoanRepaymentScheduleDetail().getInterestMethod().getValue();
Integer interestCalculationInPeriod = loan.getLoanRepaymentScheduleDetail().getInterestCalculationPeriodMethod().getValue();
CalculateLoanScheduleCommand calculateCommand = new CalculateLoanScheduleCommand(currencyCode, currencyDigits, principalAsDecimal,
interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestCalculationInPeriod,
repaidEvery, selectedRepaymentFrequency, numberOfInstallments,
selectedRepaymentSchedule, actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateCommand);
List<LoanRepaymentScheduleInstallment> modifiedLoanRepaymentSchedule = new ArrayList<LoanRepaymentScheduleInstallment>();
for (ScheduledLoanInstallment scheduledLoanInstallment : loanSchedule
.getScheduledLoanInstallments()) {
final MonetaryCurrency monetaryCurrency = new MonetaryCurrency(
scheduledLoanInstallment.getPrincipalDue().getCurrencyCode(),
scheduledLoanInstallment.getPrincipalDue().getCurrencyDigitsAfterDecimal());
Money principal = Money.of(monetaryCurrency,
scheduledLoanInstallment.getPrincipalDue().getAmount());
Money interest = Money.of(monetaryCurrency,
scheduledLoanInstallment.getInterestDue().getAmount());
LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(
loan, scheduledLoanInstallment.getInstallmentNumber(),
scheduledLoanInstallment.getPeriodStart(),
scheduledLoanInstallment.getPeriodEnd(), principal.getAmount(),
interest.getAmount());
modifiedLoanRepaymentSchedule.add(installment);
}
loan.disburseWithModifiedRepaymentSchedule(disbursedOn, comment, modifiedLoanRepaymentSchedule, defaultLoanLifecycleStateMachine());
} else {
loan.disburse(disbursedOn, defaultLoanLifecycleStateMachine());
}
this.loanRepository.save(loan);
if (StringUtils.isNotBlank(command.getComment())) {
Note note = Note.loanNote(currentUser.getOrganisation(), loan, command.getComment());
this.noteRepository.save(note);
}
return new EntityIdentifier(loan.getClient().getId());
}
@Transactional
@Override
public EntityIdentifier undloLoanDisbursal(
final UndoLoanDisbursalCommand command) {
AppUser currentUser = extractAuthenticatedUser();
Loan loan = this.loanRepository.findOne(loansThatMatch(
currentUser.getOrganisation(), command.getLoanId()));
if (loan == null) {
throw new ApplicationDomainRuleException(loanIdentifierDoesNotExistError(command.getLoanId()), "No loan exists with id: " + command.getLoanId());
}
if (loan.isActualDisbursedOnDateEarlierOrLaterThanExpected()) {
// recalculate loan schedule using original settings.
}
loan.undoDisbursal(defaultLoanLifecycleStateMachine());
this.loanRepository.save(loan);
// TODO - this may not be wanted.
Note note = Note.loanNote(currentUser.getOrganisation(), loan, "Undo of disbursal.");
this.noteRepository.save(note);
return new EntityIdentifier(loan.getClient().getId());
}
@Transactional @Transactional
@Override @Override
public EntityIdentifier makeLoanRepayment(final LoanTransactionCommand command) { public EntityIdentifier makeLoanRepayment(final LoanTransactionCommand command) {
@@ -278,16 +146,16 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
throw new ApplicationDomainRuleException(loanIdentifierDoesNotExistError(command.getLoanId()), "No loan exists with id: " + command.getLoanId()); throw new ApplicationDomainRuleException(loanIdentifierDoesNotExistError(command.getLoanId()), "No loan exists with id: " + command.getLoanId());
} }
if (this.isBeforeToday(command.getPaymentDate()) && currentUser.canNotMakeRepaymentOnLoanInPast()) { if (this.isBeforeToday(command.getTransactionDate()) && currentUser.canNotMakeRepaymentOnLoanInPast()) {
ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission.to.make.repayment.on.loan.in.past", "eventDate"); ErrorResponse errorResponse = new ErrorResponse("error.msg.no.permission.to.make.repayment.on.loan.in.past", "eventDate");
throw new ApplicationDomainRuleException(Arrays.asList(errorResponse)); throw new ApplicationDomainRuleException(Arrays.asList(errorResponse));
} }
Money repayment = Money.of(loan.getLoanRepaymentScheduleDetail() Money repayment = Money.of(loan.getLoanRepaymentScheduleDetail()
.getPrincipal().getCurrency(), .getPrincipal().getCurrency(),
command.getPaymentAmount()); command.getTransactionAmount());
LoanTransaction loanRepayment = LoanTransaction.repayment(repayment, command.getPaymentDate()); LoanTransaction loanRepayment = LoanTransaction.repayment(repayment, command.getTransactionDate());
loan.makeRepayment(loanRepayment, defaultLoanLifecycleStateMachine()); loan.makeRepayment(loanRepayment, defaultLoanLifecycleStateMachine());
this.loanTransactionRepository.save(loanRepayment); this.loanTransactionRepository.save(loanRepayment);
this.loanRepository.save(loan); this.loanRepository.save(loan);
@@ -323,12 +191,12 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
Money transactionAmount = Money.of(loan Money transactionAmount = Money.of(loan
.getLoanRepaymentScheduleDetail().getPrincipal() .getLoanRepaymentScheduleDetail().getPrincipal()
.getCurrency(), command.getPaymentAmount()); .getCurrency(), command.getTransactionAmount());
// adjustment is only supported for repayments and waivers at present // adjustment is only supported for repayments and waivers at present
LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmount, command.getPaymentDate()); LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmount, command.getTransactionDate());
if (transactionToAdjust.isWaiver()) { if (transactionToAdjust.isWaiver()) {
newTransactionDetail = LoanTransaction.waiver(transactionAmount, command.getPaymentDate()); newTransactionDetail = LoanTransaction.waiver(transactionAmount, command.getTransactionDate());
} }
loan.adjustExistingTransaction(transactionToAdjust, newTransactionDetail, defaultLoanLifecycleStateMachine()); loan.adjustExistingTransaction(transactionToAdjust, newTransactionDetail, defaultLoanLifecycleStateMachine());
@@ -363,9 +231,9 @@ public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformServi
Money waived = Money.of(loan.getLoanRepaymentScheduleDetail() Money waived = Money.of(loan.getLoanRepaymentScheduleDetail()
.getPrincipal().getCurrency(), .getPrincipal().getCurrency(),
command.getPaymentAmount()); command.getTransactionAmount());
LoanTransaction waiver = LoanTransaction.waiver(waived, command.getPaymentDate()); LoanTransaction waiver = LoanTransaction.waiver(waived, command.getTransactionDate());
loan.waive(waiver, defaultLoanLifecycleStateMachine()); loan.waive(waiver, defaultLoanLifecycleStateMachine());
@@ -7,6 +7,7 @@ import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE; import javax.ws.rs.DELETE;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@@ -18,10 +19,13 @@ import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosng.data.EntityIdentifier; import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.LoanAccountData; import org.mifosng.data.LoanAccountData;
import org.mifosng.data.LoanRepaymentData;
import org.mifosng.data.LoanSchedule; import org.mifosng.data.LoanSchedule;
import org.mifosng.data.NewLoanWorkflowStepOneData; import org.mifosng.data.NewLoanWorkflowStepOneData;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.CalculateLoanScheduleCommand; import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.SubmitLoanApplicationCommand; import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand; import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand; import org.mifosng.data.command.UndoLoanDisbursalCommand;
@@ -159,9 +163,12 @@ public class LoansApiResource {
@Path("{loanId}") @Path("{loanId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON}) @Produces({ MediaType.APPLICATION_JSON})
public Response rejectLoanApplication(@PathParam("loanId") final Long loanId, @QueryParam("command") final String commandParam, public Response stateTransitions(@PathParam("loanId") final Long loanId,
@QueryParam("command") final String commandParam,
final LoanStateTransitionCommand command) { final LoanStateTransitionCommand command) {
hardcodeUserIntoSecurityContext();
LocalDate eventDate = this.apiDataConversionService.convertFrom(command.getEventDateFormatted(), "eventDateFormatted", command.getDateFormat()); LocalDate eventDate = this.apiDataConversionService.convertFrom(command.getEventDateFormatted(), "eventDateFormatted", command.getDateFormat());
command.setLoanId(loanId); command.setLoanId(loanId);
@@ -176,9 +183,8 @@ public class LoansApiResource {
} else if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("approve")) { } else if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("approve")) {
EntityIdentifier identifier = this.loanWritePlatformService.approveLoanApplication(command); EntityIdentifier identifier = this.loanWritePlatformService.approveLoanApplication(command);
return Response.ok().entity(identifier).build(); return Response.ok().entity(identifier).build();
} else if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("undoapproval")) { } else if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("disburse")) {
UndoLoanApprovalCommand undoCommand = new UndoLoanApprovalCommand(loanId); EntityIdentifier identifier = this.loanWritePlatformService.disburseLoan(command);
EntityIdentifier identifier = this.loanWritePlatformService.undoLoanApproval(undoCommand);
return Response.ok().entity(identifier).build(); return Response.ok().entity(identifier).build();
} }
@@ -187,10 +193,11 @@ public class LoansApiResource {
@POST @POST
@Path("{loanId}/undo") @Path("{loanId}/undo")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({ MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON})
public Response rejectLoanApplication(@PathParam("loanId") final Long loanId, @QueryParam("command") final String commandParam) { public Response undoStateTransitions(@PathParam("loanId") final Long loanId, @QueryParam("command") final String commandParam) {
hardcodeUserIntoSecurityContext();
if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("undoapproval")) { if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("undoapproval")) {
UndoLoanApprovalCommand undoCommand = new UndoLoanApprovalCommand(loanId); UndoLoanApprovalCommand undoCommand = new UndoLoanApprovalCommand(loanId);
@@ -198,10 +205,87 @@ public class LoansApiResource {
return Response.ok().entity(identifier).build(); return Response.ok().entity(identifier).build();
} else if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("undodisbursal")) { } else if (StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase("undodisbursal")) {
UndoLoanDisbursalCommand undoCommand = new UndoLoanDisbursalCommand(loanId); UndoLoanDisbursalCommand undoCommand = new UndoLoanDisbursalCommand(loanId);
EntityIdentifier identifier = this.writePlatformService.undloLoanDisbursal(undoCommand); EntityIdentifier identifier = this.loanWritePlatformService.undloLoanDisbursal(undoCommand);
return Response.ok().entity(identifier).build(); return Response.ok().entity(identifier).build();
} }
return Response.ok().build(); return Response.ok().build();
} }
@POST
@Path("{loanId}/transactions")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON})
public Response executeLoanTransaction(@PathParam("loanId") final Long loanId, @QueryParam("transactionType") final String transactionType, final LoanTransactionCommand command) {
hardcodeUserIntoSecurityContext();
command.setLoanId(loanId);
LocalDate transactionDate = apiDataConversionService.convertFrom(command.getTransactionDateFormatted(), "transactionDateFormatted", command.getDateFormat());
command.setTransactionDate(transactionDate);
BigDecimal transactionAmount = apiDataConversionService.convertFrom(command.getTransactionAmountFormatted(), "transactionAmountFormatted", Locale.UK);
command.setTransactionAmount(transactionAmount);
if (StringUtils.isNotBlank(transactionType) && transactionType.trim().equalsIgnoreCase("waiver")) {
EntityIdentifier identifier = this.writePlatformService.waiveLoanAmount(command);
return Response.ok().entity(identifier).build();
}
EntityIdentifier identifier = this.writePlatformService.makeLoanRepayment(command);
return Response.ok().entity(identifier).build();
}
@GET
@Path("{loanId}/transactions/template")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON})
public Response retrieveNewRepaymentDetails(@PathParam("loanId") final Long loanId, @QueryParam("type") final String transactionType) {
hardcodeUserIntoSecurityContext();
if (StringUtils.isNotBlank(transactionType) && transactionType.trim().equalsIgnoreCase("waiver")) {
LoanRepaymentData loanWaiverData = this.readPlatformService.retrieveNewLoanWaiverDetails(loanId);
return Response.ok().entity(loanWaiverData).build();
}
LoanRepaymentData loanRepaymentData = this.readPlatformService.retrieveNewLoanRepaymentDetails(loanId);
return Response.ok().entity(loanRepaymentData).build();
}
@GET
@Path("{loanId}/transactions/{repaymentId}")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON})
public Response retrieveRepaymentDetails(@PathParam("loanId") final Long loanId, @PathParam("repaymentId") final Long repaymentId) {
hardcodeUserIntoSecurityContext();
LoanRepaymentData loanRepaymentData = this.readPlatformService.retrieveLoanRepaymentDetails(loanId, repaymentId);
return Response.ok().entity(loanRepaymentData).build();
}
@PUT
@Path("{loanId}/transactions/{repaymentId}")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response adjustLoanTransaction(@PathParam("loanId") final Long loanId, @PathParam("repaymentId") final Long repaymentId, final AdjustLoanTransactionCommand command) {
hardcodeUserIntoSecurityContext();
command.setLoanId(loanId);
command.setRepaymentId(repaymentId);
LocalDate transactionDate = apiDataConversionService.convertFrom(command.getTransactionDateFormatted(), "transactionDateFormatted", command.getDateFormat());
command.setTransactionDate(transactionDate);
BigDecimal transactionAmount = apiDataConversionService.convertFrom(command.getTransactionAmountFormatted(), "transactionAmountFormatted", Locale.UK);
command.setTransactionAmount(transactionAmount);
EntityIdentifier identifier = this.writePlatformService.adjustLoanTransaction(command);
return Response.ok().entity(identifier).build();
}
} }
@@ -4,6 +4,7 @@ import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.SubmitLoanApplicationCommand; import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand; import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
public interface LoanWritePlatformService { public interface LoanWritePlatformService {
@@ -25,4 +26,10 @@ public interface LoanWritePlatformService {
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_WITHDRAW_LOAN_ROLE', 'CAN_WITHDRAW_LOAN_IN_THE_PAST_ROLE')") @PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_WITHDRAW_LOAN_ROLE', 'CAN_WITHDRAW_LOAN_IN_THE_PAST_ROLE')")
EntityIdentifier withdrawLoan(LoanStateTransitionCommand command); EntityIdentifier withdrawLoan(LoanStateTransitionCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_DISBURSE_LOAN_ROLE', 'CAN_DISBURSE_LOAN_IN_THE_PAST_ROLE')")
EntityIdentifier disburseLoan(LoanStateTransitionCommand command);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE', 'CAN_UNDO_LOAN_DISBURSAL_ROLE')")
public EntityIdentifier undloLoanDisbursal(UndoLoanDisbursalCommand command);
} }
@@ -3,6 +3,7 @@ package org.mifosng.platform.loan.service;
import static org.mifosng.platform.Specifications.loansThatMatch; import static org.mifosng.platform.Specifications.loansThatMatch;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@@ -11,15 +12,18 @@ import org.mifosng.data.EntityIdentifier;
import org.mifosng.data.LoanSchedule; import org.mifosng.data.LoanSchedule;
import org.mifosng.data.MoneyData; import org.mifosng.data.MoneyData;
import org.mifosng.data.ScheduledLoanInstallment; import org.mifosng.data.ScheduledLoanInstallment;
import org.mifosng.data.command.CalculateLoanScheduleCommand;
import org.mifosng.data.command.LoanStateTransitionCommand; import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.SubmitLoanApplicationCommand; import org.mifosng.data.command.SubmitLoanApplicationCommand;
import org.mifosng.data.command.UndoLoanApprovalCommand; import org.mifosng.data.command.UndoLoanApprovalCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.platform.LoanStateTransitionCommandValidator; import org.mifosng.platform.LoanStateTransitionCommandValidator;
import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientRepository; import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.client.domain.Note; import org.mifosng.platform.client.domain.Note;
import org.mifosng.platform.client.domain.NoteRepository; import org.mifosng.platform.client.domain.NoteRepository;
import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.exceptions.NoAuthorizationException; import org.mifosng.platform.exceptions.NoAuthorizationException;
import org.mifosng.platform.exceptions.PlatformDomainRuleException; import org.mifosng.platform.exceptions.PlatformDomainRuleException;
import org.mifosng.platform.exceptions.PlatformResourceNotFoundException; import org.mifosng.platform.exceptions.PlatformResourceNotFoundException;
@@ -54,19 +58,20 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private final LoanStatusRepository loanStatusRepository; private final LoanStatusRepository loanStatusRepository;
private final ClientRepository clientRepository; private final ClientRepository clientRepository;
private final NoteRepository noteRepository; private final NoteRepository noteRepository;
private final CalculationPlatformService calculationPlatformService;
private final AprCalculator aprCalculator = new AprCalculator(); private final AprCalculator aprCalculator = new AprCalculator();
@Autowired @Autowired
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final LoanRepository loanRepository, final LoanStatusRepository loanStatusRepository, final LoanProductRepository loanProductRepository, final LoanRepository loanRepository, final LoanStatusRepository loanStatusRepository, final LoanProductRepository loanProductRepository,
final ClientRepository clientRepository, final NoteRepository noteRepository) { final ClientRepository clientRepository, final NoteRepository noteRepository, final CalculationPlatformService calculationPlatformService) {
this.context = context; this.context = context;
this.loanRepository = loanRepository; this.loanRepository = loanRepository;
this.loanProductRepository = loanProductRepository; this.loanProductRepository = loanProductRepository;
this.clientRepository = clientRepository; this.clientRepository = clientRepository;
this.loanStatusRepository = loanStatusRepository; this.loanStatusRepository = loanStatusRepository;
this.noteRepository = noteRepository; this.noteRepository = noteRepository;
this.calculationPlatformService = calculationPlatformService;
} }
private boolean isBeforeToday(final LocalDate date) { private boolean isBeforeToday(final LocalDate date) {
@@ -279,4 +284,120 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
return new EntityIdentifier(loan.getClient().getId()); return new EntityIdentifier(loan.getClient().getId());
} }
@Transactional
@Override
public EntityIdentifier disburseLoan(final LoanStateTransitionCommand command) {
AppUser currentUser = context.authenticatedUser();
LoanStateTransitionCommandValidator validator = new LoanStateTransitionCommandValidator(command);
validator.validate();
Loan loan = this.loanRepository.findOne(loansThatMatch(currentUser.getOrganisation(), command.getLoanId()));
if (loan == null) {
throw new PlatformResourceNotFoundException("error.msg.loan.id.invalid", "Loan with identifier {0} does not exist", command.getLoanId());
}
if (this.isBeforeToday(command.getEventDate()) && currentUser.canNotDisburseLoanInPast()) {
throw new NoAuthorizationException("User has no authority to disburse loan with a date in the past.");
}
LocalDate disbursedOn = command.getEventDate();
String comment = command.getComment();
LocalDate actualDisbursementDate = new LocalDate(disbursedOn);
if (loan.isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate)) {
LocalDate repaymentsStartingFromDate = loan.getExpectedFirstRepaymentOnDate();
LocalDate interestCalculatedFromDate = loan.getInterestCalculatedFromDate();
Number principalAsDecimal = loan.getLoanRepaymentScheduleDetail().getPrincipal().getAmount();
String currencyCode = loan.getLoanRepaymentScheduleDetail().getPrincipal().getCurrencyCode();
int currencyDigits = loan.getLoanRepaymentScheduleDetail().getPrincipal().getCurrencyDigitsAfterDecimal();
Number interestRatePerYear = loan.getLoanRepaymentScheduleDetail().getAnnualNominalInterestRate();
Integer numberOfInstallments = loan.getLoanRepaymentScheduleDetail().getNumberOfRepayments();
Integer repaidEvery = loan.getLoanRepaymentScheduleDetail().getRepayEvery();
Integer selectedRepaymentFrequency = loan.getLoanRepaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue();
Integer selectedRepaymentSchedule = loan.getLoanRepaymentScheduleDetail().getAmortizationMethod().getValue();
// use annual percentage rate to re-calculate loan schedule for late disbursement
Number interestRatePerPeriod = interestRatePerYear;
Integer interestRateFrequencyMethod = PeriodFrequencyType.YEARS.getValue();
Integer interestMethod = loan.getLoanRepaymentScheduleDetail().getInterestMethod().getValue();
Integer interestCalculationInPeriod = loan.getLoanRepaymentScheduleDetail().getInterestCalculationPeriodMethod().getValue();
CalculateLoanScheduleCommand calculateCommand = new CalculateLoanScheduleCommand(currencyCode, currencyDigits, principalAsDecimal,
interestRatePerPeriod, interestRateFrequencyMethod, interestMethod, interestCalculationInPeriod,
repaidEvery, selectedRepaymentFrequency, numberOfInstallments,
selectedRepaymentSchedule, actualDisbursementDate, repaymentsStartingFromDate, interestCalculatedFromDate);
LoanSchedule loanSchedule = this.calculationPlatformService.calculateLoanSchedule(calculateCommand);
List<LoanRepaymentScheduleInstallment> modifiedLoanRepaymentSchedule = new ArrayList<LoanRepaymentScheduleInstallment>();
for (ScheduledLoanInstallment scheduledLoanInstallment : loanSchedule
.getScheduledLoanInstallments()) {
final MonetaryCurrency monetaryCurrency = new MonetaryCurrency(
scheduledLoanInstallment.getPrincipalDue().getCurrencyCode(),
scheduledLoanInstallment.getPrincipalDue().getCurrencyDigitsAfterDecimal());
Money principal = Money.of(monetaryCurrency,
scheduledLoanInstallment.getPrincipalDue().getAmount());
Money interest = Money.of(monetaryCurrency,
scheduledLoanInstallment.getInterestDue().getAmount());
LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(
loan, scheduledLoanInstallment.getInstallmentNumber(),
scheduledLoanInstallment.getPeriodStart(),
scheduledLoanInstallment.getPeriodEnd(), principal.getAmount(),
interest.getAmount());
modifiedLoanRepaymentSchedule.add(installment);
}
loan.disburseWithModifiedRepaymentSchedule(disbursedOn, comment, modifiedLoanRepaymentSchedule, defaultLoanLifecycleStateMachine());
} else {
loan.disburse(disbursedOn, defaultLoanLifecycleStateMachine());
}
this.loanRepository.save(loan);
if (StringUtils.isNotBlank(command.getComment())) {
Note note = Note.loanNote(currentUser.getOrganisation(), loan, command.getComment());
this.noteRepository.save(note);
}
return new EntityIdentifier(loan.getClient().getId());
}
@Transactional
@Override
public EntityIdentifier undloLoanDisbursal(final UndoLoanDisbursalCommand command) {
AppUser currentUser = context.authenticatedUser();
Loan loan = this.loanRepository.findOne(loansThatMatch(currentUser.getOrganisation(), command.getLoanId()));
if (loan == null) {
throw new PlatformResourceNotFoundException("error.msg.loan.id.invalid", "Loan with identifier {0} does not exist", command.getLoanId());
}
if (loan.isActualDisbursedOnDateEarlierOrLaterThanExpected()) {
// FIXME - handle this use case - recalculate loan schedule using original settings.
}
loan.undoDisbursal(defaultLoanLifecycleStateMachine());
this.loanRepository.save(loan);
// TODO - this may not be wanted.
Note note = Note.loanNote(currentUser.getOrganisation(), loan, "Undo of disbursal.");
this.noteRepository.save(note);
return new EntityIdentifier(loan.getClient().getId());
}
} }
@@ -1,268 +0,0 @@
package org.mifosng.platform.rest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
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.LoanRepaymentData;
import org.mifosng.data.command.AdjustLoanTransactionCommand;
import org.mifosng.data.command.LoanStateTransitionCommand;
import org.mifosng.data.command.LoanTransactionCommand;
import org.mifosng.data.command.UndoLoanDisbursalCommand;
import org.mifosng.platform.ReadPlatformService;
import org.mifosng.platform.ReadPlatformServiceImpl;
import org.mifosng.platform.WritePlatformService;
import org.mifosng.platform.exceptions.ApplicationDomainRuleException;
import org.mifosng.platform.exceptions.NewDataValidationException;
import org.mifosng.platform.exceptions.UnAuthenticatedUserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
@Path("/protected/loan")
@Component
@Scope("singleton")
public class LoanResource {
private final static Logger logger = LoggerFactory.getLogger(ReadPlatformServiceImpl.class);
@Autowired
private ReadPlatformService readPlatformService;
@Autowired
private WritePlatformService writePlatformService;
@POST
@Path("disburse")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response disburseLoanApplication(final LoanStateTransitionCommand command) {
try {
EntityIdentifier identifier = this.writePlatformService.disburseLoan(command);
return Response.ok().entity(identifier).build();
} catch (UnAuthenticatedUserException 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
@Path("undodisbursal")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response undoLoanDisbursal(final UndoLoanDisbursalCommand command) {
try {
EntityIdentifier identifier = this.writePlatformService.undloLoanDisbursal(command);
return Response.ok().entity(identifier).build();
} catch (UnAuthenticatedUserException 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("{loanId}/repayment")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveNewRepaymentDetails(@PathParam("loanId") final Long loanId) {
try {
LoanRepaymentData loanRepaymentData = this.readPlatformService.retrieveNewLoanRepaymentDetails(loanId);
return Response.ok().entity(loanRepaymentData).build();
} catch (UnAuthenticatedUserException 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("{loanId}/repayment/{repaymentId}")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveRepaymentDetails(@PathParam("loanId") final Long loanId, @PathParam("repaymentId") final Long repaymentId) {
try {
LoanRepaymentData loanRepaymentData = this.readPlatformService.retrieveLoanRepaymentDetails(loanId, repaymentId);
return Response.ok().entity(loanRepaymentData).build();
} catch (UnAuthenticatedUserException 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
@Path("repayment")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response makeLoanRepayment(final LoanTransactionCommand command) {
try {
EntityIdentifier identifier = this.writePlatformService.makeLoanRepayment(command);
return Response.ok().entity(identifier).build();
} catch (UnAuthenticatedUserException 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());
} catch (Exception e) {
logger.error(e.getMessage(), e);
List<ErrorResponse> allErrors = new ArrayList<ErrorResponse>();
ErrorResponse err = new ErrorResponse("unknown.error", "error",
e.getMessage());
allErrors.add(err);
throw new WebApplicationException(Response
.status(Status.BAD_REQUEST)
.entity(new ErrorResponseList(allErrors)).build());
}
}
@POST
@Path("repayment/adjust")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response adjustLoanTransaction(final AdjustLoanTransactionCommand command) {
try {
EntityIdentifier identifier = this.writePlatformService.adjustLoanTransaction(command);
return Response.ok().entity(identifier).build();
} catch (UnAuthenticatedUserException 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());
} catch (Exception e) {
logger.error(e.getMessage(), e);
List<ErrorResponse> allErrors = new ArrayList<ErrorResponse>();
ErrorResponse err = new ErrorResponse("unknown.error", "error",
e.getMessage());
allErrors.add(err);
throw new WebApplicationException(Response
.status(Status.BAD_REQUEST)
.entity(new ErrorResponseList(allErrors)).build());
}
}
@GET
@Path("{loanId}/waive")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response retrieveNewWaiverDetails(@PathParam("loanId") final Long loanId) {
try {
LoanRepaymentData loanRepaymentData = this.readPlatformService.retrieveNewLoanWaiverDetails(loanId);
return Response.ok().entity(loanRepaymentData).build();
} catch (UnAuthenticatedUserException 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
@Path("waive")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response waiveLoanAmount(final LoanTransactionCommand command) {
try {
EntityIdentifier identifier = this.writePlatformService.waiveLoanAmount(command);
return Response.ok().entity(identifier).build();
} catch (UnAuthenticatedUserException 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());
} catch (Exception e) {
logger.error(e.getMessage(), e);
List<ErrorResponse> allErrors = new ArrayList<ErrorResponse>();
ErrorResponse err = new ErrorResponse("unknown.error", "error",
e.getMessage());
allErrors.add(err);
throw new WebApplicationException(Response
.status(Status.BAD_REQUEST)
.entity(new ErrorResponseList(allErrors)).build());
}
}
}