handle update of parent office error cases.

This commit is contained in:
Keith Woodlock
2012-05-30 12:23:15 +01:00
parent 3b212464fe
commit c3dade1b7d
10 changed files with 99 additions and 15 deletions
@@ -66,6 +66,21 @@ public class ApiGlobalErrorResponse {
return globalErrorResponse;
}
public static ApiGlobalErrorResponse domainRuleViolation(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
globalErrorResponse.setHttpStatusCode("403");
globalErrorResponse.setDeveloperMessage("Request was understoon but caused a domain rule violation.");
globalErrorResponse.setDeveloperDocLink("https://github.com/keithwoodlock/mifosx/wiki/HTTP-API-Error-codes");
globalErrorResponse.setUserMessageGlobalisationCode("validation.msg.domain.rule.violation");
globalErrorResponse.setDefaultUserMessage("Errors contain reason for domain rule violation.");
List<ApiParameterError> errors = new ArrayList<ApiParameterError>();
errors.add(ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs));
globalErrorResponse.setErrors(errors);
return globalErrorResponse;
}
public static ApiGlobalErrorResponse notFound(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
@@ -70,7 +70,7 @@ public class ApiParameterError {
}
this.args = messageArgs;
this.parameterName="identifier";
this.parameterName="id";
}
public String getDeveloperMessage() {
@@ -0,0 +1,30 @@
package org.mifosng.platform.api.errorhandling;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import org.mifosng.data.ApiGlobalErrorResponse;
import org.mifosng.platform.exceptions.AbstractPlatformDomainRuleException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* An {@link ExceptionMapper} to map {@link AbstractPlatformDomainRuleException} thrown by platform into a HTTP API friendly format.
*
* The {@link AbstractPlatformDomainRuleException} is thrown when an api call results is some internal business/domain logic been violated.
*/
@Provider
@Component
@Scope("singleton")
public class PlatformDomainRuleExceptionMapper implements ExceptionMapper<AbstractPlatformDomainRuleException> {
@Override
public Response toResponse(AbstractPlatformDomainRuleException exception) {
ApiGlobalErrorResponse notFoundErrorResponse = ApiGlobalErrorResponse.domainRuleViolation(exception.getGlobalisationMessageCode(), exception.getDefaultUserMessage(), exception.getDefaultUserMessageArgs());
// request understood but not carried out due to it violating some domain/business logic
return Response.status(Status.FORBIDDEN).entity(notFoundErrorResponse).build();
}
}
@@ -3,13 +3,13 @@ package org.mifosng.platform.exceptions;
/**
* A {@link RuntimeException} thrown when valid api request end up violating some domain rule.
*/
public class PlatformDomainRuleException extends RuntimeException {
public abstract class AbstractPlatformDomainRuleException extends RuntimeException {
private final String globalisationMessageCode;
private final String defaultUserMessage;
private final Object[] defaultUserMessageArgs;
public PlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
public AbstractPlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
this.globalisationMessageCode = globalisationMessageCode;
this.defaultUserMessage = defaultUserMessage;
this.defaultUserMessageArgs = defaultUserMessageArgs;
@@ -0,0 +1,12 @@
package org.mifosng.platform.exceptions;
/**
* Exception thrown when an attempt is made update the parent of a root office.
*/
public class CannotUpdateOfficeWithParentOfficeSameAsSelf extends
AbstractPlatformDomainRuleException {
public CannotUpdateOfficeWithParentOfficeSameAsSelf(final Long officeId, final Long parentId) {
super("error.msg.office.parentId.same.as.id", "Cannot update office with parent same as self.", officeId, parentId);
}
}
@@ -0,0 +1,13 @@
package org.mifosng.platform.exceptions;
/**
* {@link AbstractPlatformDomainRuleException} thrown when trying to delete a loan in an invalid state.
*/
public class LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted extends
AbstractPlatformDomainRuleException {
public LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted(final Long id) {
super("error.msg.loan.cannot.delete.loan.in.its.present.state", "Loan with identifier " + id + " cannot be deleted in its current state.", id);
}
}
@@ -0,0 +1,12 @@
package org.mifosng.platform.exceptions;
/**
* Exception thrown when an attempt is made update the parent of a root office.
*/
public class RootOfficeParentCannotBeUpdated extends
AbstractPlatformDomainRuleException {
public RootOfficeParentCannotBeUpdated() {
super("error.msg.office.cannot.update.parent.office.of.root.office", "The root office must not be set with a parent office.");
}
}
@@ -21,9 +21,9 @@ 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.exceptions.LoanNotFoundException;
import org.mifosng.platform.exceptions.LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted;
import org.mifosng.platform.exceptions.LoanTransactionNotFoundException;
import org.mifosng.platform.exceptions.NoAuthorizationException;
import org.mifosng.platform.exceptions.PlatformDomainRuleException;
import org.mifosng.platform.loan.domain.DefaultLoanLifecycleStateMachine;
import org.mifosng.platform.loan.domain.Loan;
import org.mifosng.platform.loan.domain.LoanLifecycleStateMachine;
@@ -113,7 +113,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
}
if (loan.isNotSubmittedAndPendingApproval()) {
throw new PlatformDomainRuleException("error.msg.cannot.delete.loan.in.its.present.state", "Loan with identifier {0} cannot be deleted in its current state.", loanId);
throw new LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted(loanId);
}
Long clientId = loan.getClient().getId();
@@ -18,6 +18,8 @@ import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.OfficeCommand;
import org.mifosng.platform.exceptions.CannotUpdateOfficeWithParentOfficeSameAsSelf;
import org.mifosng.platform.exceptions.RootOfficeParentCannotBeUpdated;
import org.mifosng.platform.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.user.domain.AppUser;
@@ -120,6 +122,12 @@ public class Office extends AbstractAuditableCustom<AppUser, Long> {
}
public void update(Office newParent) {
if (this.parent == null) {
throw new RootOfficeParentCannotBeUpdated();
}
if (this.identifiedBy(newParent.getId())) {
throw new CannotUpdateOfficeWithParentOfficeSameAsSelf(this.getId(), newParent.getId());
}
this.parent = newParent;
generateHierarchy();
}
@@ -43,9 +43,6 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
validator.validateForCreate();
Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId());
if (parent == null) {
throw new OfficeNotFoundException(command.getParentId());
}
Office office = Office.createNew(currentUser.getOrganisation(), parent, command.getName(), command.getOpeningLocalDate(), command.getExternalId());
@@ -74,17 +71,11 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
validator.validateForUpdate();
Office office = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getId());
if (office == null) {
throw new OfficeNotFoundException(command.getId());
}
office.update(command);
if (!command.isRootOffice() && command.getParentId() != null) {
if (command.getParentId() != null) {
Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId());
if (parent == null) {
throw new OfficeNotFoundException(command.getParentId());
}
office.update(parent);
}
@@ -130,6 +121,9 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
Office officeToReturn = userOffice;
if (!userOffice.identifiedBy(officeId)) {
officeToReturn = this.officeRepository.findOne(officesThatMatch(currentUser.getOrganisation(), officeId));
if (officeToReturn == null) {
throw new OfficeNotFoundException(officeId);
}
}
return officeToReturn;