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; 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) { public static ApiGlobalErrorResponse notFound(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
@@ -70,7 +70,7 @@ public class ApiParameterError {
} }
this.args = messageArgs; this.args = messageArgs;
this.parameterName="identifier"; this.parameterName="id";
} }
public String getDeveloperMessage() { 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. * 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 globalisationMessageCode;
private final String defaultUserMessage; private final String defaultUserMessage;
private final Object[] defaultUserMessageArgs; private final Object[] defaultUserMessageArgs;
public PlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) { public AbstractPlatformDomainRuleException(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
this.globalisationMessageCode = globalisationMessageCode; this.globalisationMessageCode = globalisationMessageCode;
this.defaultUserMessage = defaultUserMessage; this.defaultUserMessage = defaultUserMessage;
this.defaultUserMessageArgs = defaultUserMessageArgs; 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.MonetaryCurrency;
import org.mifosng.platform.currency.domain.Money; import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.exceptions.LoanNotFoundException; import org.mifosng.platform.exceptions.LoanNotFoundException;
import org.mifosng.platform.exceptions.LoanNotInSubmittedAndPendingApprovalStateCannotBeDeleted;
import org.mifosng.platform.exceptions.LoanTransactionNotFoundException; import org.mifosng.platform.exceptions.LoanTransactionNotFoundException;
import org.mifosng.platform.exceptions.NoAuthorizationException; 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.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;
@@ -113,7 +113,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
} }
if (loan.isNotSubmittedAndPendingApproval()) { 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(); Long clientId = loan.getClient().getId();
@@ -18,6 +18,8 @@ import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.OfficeCommand; 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.infrastructure.AbstractAuditableCustom;
import org.mifosng.platform.user.domain.AppUser; import org.mifosng.platform.user.domain.AppUser;
@@ -120,6 +122,12 @@ public class Office extends AbstractAuditableCustom<AppUser, Long> {
} }
public void update(Office newParent) { 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; this.parent = newParent;
generateHierarchy(); generateHierarchy();
} }
@@ -43,9 +43,6 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
validator.validateForCreate(); validator.validateForCreate();
Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId()); 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()); Office office = Office.createNew(currentUser.getOrganisation(), parent, command.getName(), command.getOpeningLocalDate(), command.getExternalId());
@@ -74,17 +71,11 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
validator.validateForUpdate(); validator.validateForUpdate();
Office office = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getId()); Office office = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getId());
if (office == null) {
throw new OfficeNotFoundException(command.getId());
}
office.update(command); office.update(command);
if (!command.isRootOffice() && command.getParentId() != null) { if (command.getParentId() != null) {
Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId()); Office parent = validateUserPriviledgeOnOfficeAndRetrieve(currentUser, command.getParentId());
if (parent == null) {
throw new OfficeNotFoundException(command.getParentId());
}
office.update(parent); office.update(parent);
} }
@@ -130,6 +121,9 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
Office officeToReturn = userOffice; Office officeToReturn = userOffice;
if (!userOffice.identifiedBy(officeId)) { if (!userOffice.identifiedBy(officeId)) {
officeToReturn = this.officeRepository.findOne(officesThatMatch(currentUser.getOrganisation(), officeId)); officeToReturn = this.officeRepository.findOne(officesThatMatch(currentUser.getOrganisation(), officeId));
if (officeToReturn == null) {
throw new OfficeNotFoundException(officeId);
}
} }
return officeToReturn; return officeToReturn;