tidy up validation around office transactions api.

This commit is contained in:
Keith Woodlock
2013-02-01 09:37:18 +00:00
parent 4a07e78171
commit 65e7563748
7 changed files with 129 additions and 172 deletions
@@ -1,82 +0,0 @@
package org.mifosplatform.organisation.office.command;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
/**
* Immutable command for transferring money between two branches.
*/
public class BranchMoneyTransferCommand {
private final Long fromOfficeId;
private final Long toOfficeId;
private final LocalDate transactionDate;
private final String currencyCode;
private final BigDecimal transactionAmount;
private final String description;
public BranchMoneyTransferCommand(final Long fromOfficeId, final Long toOfficeId, final LocalDate transactionDate,
final String currencyCode, final BigDecimal transactionAmount, final String description) {
this.fromOfficeId = fromOfficeId;
this.toOfficeId = toOfficeId;
this.transactionDate = transactionDate;
this.currencyCode = currencyCode;
this.transactionAmount = transactionAmount;
this.description = description;
}
public Long getFromOfficeId() {
return fromOfficeId;
}
public Long getToOfficeId() {
return toOfficeId;
}
public LocalDate getTransactionDate() {
return transactionDate;
}
public String getCurrencyCode() {
return currencyCode;
}
public BigDecimal getTransactionAmount() {
return transactionAmount;
}
public String getDescription() {
return description;
}
public void validateBranchTransfer() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("office.money.transfer");
baseDataValidator.reset().parameter("fromOfficeId").value(this.fromOfficeId).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("toOfficeId").value(this.toOfficeId).ignoreIfNull().integerGreaterThanZero();
if (this.fromOfficeId == null && this.toOfficeId == null) {
baseDataValidator.reset().parameter("toOfficeId").value(this.toOfficeId).notNull();
}
if (this.fromOfficeId != null && this.toOfficeId != null) {
baseDataValidator.reset().parameter("fromOfficeId").value(this.fromOfficeId).notSameAsParameter("toOfficeId", this.toOfficeId);
}
baseDataValidator.reset().parameter("transactionDate").value(this.transactionDate).notNull();
baseDataValidator.reset().parameter("currencyCode").value(this.currencyCode).notBlank();
baseDataValidator.reset().parameter("transactionAmount").value(this.transactionAmount).notNull();
baseDataValidator.reset().parameter("description").value(this.description).notExceedingLengthOf(100);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -22,6 +22,6 @@ public class CreateOfficeTransactionCommandHandler implements NewCommandSourceHa
@Override
public CommandProcessingResult processCommand(final JsonCommand command) {
return this.writePlatformService.externalBranchMoneyTransfer(command);
return this.writePlatformService.officeTransaction(command);
}
}
@@ -1,63 +0,0 @@
package org.mifosplatform.organisation.office.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.organisation.office.command.BranchMoneyTransferCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for
* {@link BranchMoneyTransferCommand} 's.
*/
@Component
public final class BranchMoneyTransferCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<BranchMoneyTransferCommand> {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("fromOfficeId", "toOfficeId", "transactionDate",
"currencyCode", "transactionAmount", "description", "locale", "dateFormat"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public BranchMoneyTransferCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Override
public BranchMoneyTransferCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = fromApiJsonHelper.parse(json);
final Long fromOfficeId = fromApiJsonHelper.extractLongNamed("fromOfficeId", element);
final Long toOfficeId = fromApiJsonHelper.extractLongNamed("toOfficeId", element);
final LocalDate transactionLocalDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element);
final BigDecimal transactionAmountValue = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("transactionAmount", element);
final String description = fromApiJsonHelper.extractStringNamed("description", element);
return new BranchMoneyTransferCommand(fromOfficeId, toOfficeId, transactionLocalDate, currencyCode, transactionAmountValue,
description);
}
}
@@ -0,0 +1,84 @@
package org.mifosplatform.organisation.office.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public final class OfficeTransactionCommandFromApiJsonDeserializer {
/**
* The parameters supported for this command.
*/
private final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("fromOfficeId", "toOfficeId", "transactionDate",
"currencyCode", "transactionAmount", "description", "locale", "dateFormat"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public OfficeTransactionCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateOfficeTransfer(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("code");
final JsonElement element = fromApiJsonHelper.parse(json);
final Long fromOfficeId = fromApiJsonHelper.extractLongNamed("fromOfficeId", element);
baseDataValidator.reset().parameter("fromOfficeId").value(fromOfficeId).ignoreIfNull().integerGreaterThanZero();
final Long toOfficeId = fromApiJsonHelper.extractLongNamed("toOfficeId", element);
baseDataValidator.reset().parameter("toOfficeId").value(toOfficeId).ignoreIfNull().integerGreaterThanZero();
if (fromOfficeId == null && toOfficeId == null) {
baseDataValidator.reset().parameter("toOfficeId").value(toOfficeId).notNull();
}
if (fromOfficeId != null && toOfficeId != null) {
baseDataValidator.reset().parameter("fromOfficeId").value(fromOfficeId).notSameAsParameter("toOfficeId", toOfficeId);
}
final LocalDate transactionDate = fromApiJsonHelper.extractLocalDateNamed("transactionDate", element);
baseDataValidator.reset().parameter("transactionDate").value(transactionDate).notNull();
final String currencyCode = fromApiJsonHelper.extractStringNamed("currencyCode", element);
baseDataValidator.reset().parameter("currencyCode").value(currencyCode).notBlank().notExceedingLengthOf(3);
final BigDecimal transactionAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("transactionAmount", element);
baseDataValidator.reset().parameter("transactionAmount").value(transactionAmount).notNull().positiveAmount();
final String description = fromApiJsonHelper.extractStringNamed("description", element);
baseDataValidator.reset().parameter("description").value(description).notExceedingLengthOf(100);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -9,7 +9,7 @@ public interface OfficeWritePlatformService {
CommandProcessingResult updateOffice(Long officeId, JsonCommand command);
CommandProcessingResult externalBranchMoneyTransfer(JsonCommand command);
CommandProcessingResult officeTransaction(JsonCommand command);
CommandProcessingResult deleteOfficeTransaction(Long id, JsonCommand command);
}
@@ -13,14 +13,13 @@ import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyReposit
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.monetary.exception.CurrencyNotFoundException;
import org.mifosplatform.organisation.office.command.BranchMoneyTransferCommand;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.domain.OfficeTransaction;
import org.mifosplatform.organisation.office.domain.OfficeTransactionRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException;
import org.mifosplatform.organisation.office.serialization.BranchMoneyTransferCommandFromApiJsonDeserializer;
import org.mifosplatform.organisation.office.serialization.OfficeCommandFromApiJsonDeserializer;
import org.mifosplatform.organisation.office.serialization.OfficeTransactionCommandFromApiJsonDeserializer;
import org.mifosplatform.useradministration.domain.AppUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,7 +35,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
private final PlatformSecurityContext context;
private final OfficeCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final BranchMoneyTransferCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer;
private final OfficeTransactionCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer;
private final OfficeRepository officeRepository;
private final OfficeTransactionRepository officeTransactionRepository;
private final ApplicationCurrencyRepository applicationCurrencyRepository;
@@ -44,7 +43,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
@Autowired
public OfficeWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final OfficeCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final BranchMoneyTransferCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer,
final OfficeTransactionCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer,
final OfficeRepository officeRepository, final OfficeTransactionRepository officeMonetaryTransferRepository,
final ApplicationCurrencyRepository applicationCurrencyRepository) {
this.context = context;
@@ -79,8 +78,11 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
this.officeRepository.save(office);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(office.getId())
.withOfficeId(office.getId()).build();
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(office.getId()) //
.withOfficeId(office.getId()) //
.build();
} catch (DataIntegrityViolationException dve) {
handleOfficeDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
@@ -114,8 +116,12 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
this.officeRepository.saveAndFlush(office);
}
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(office.getId())
.withOfficeId(office.getId()).with(changes).build();
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(office.getId()) //
.withOfficeId(office.getId()) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) {
handleOfficeDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty();
@@ -124,40 +130,43 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
@Transactional
@Override
public CommandProcessingResult externalBranchMoneyTransfer(final JsonCommand command) {
public CommandProcessingResult officeTransaction(final JsonCommand command) {
context.authenticatedUser();
final BranchMoneyTransferCommand moneyTransferCommand = this.moneyTransferCommandFromApiJsonDeserializer.commandFromApiJson(command
.json());
moneyTransferCommand.validateBranchTransfer();
this.moneyTransferCommandFromApiJsonDeserializer.validateOfficeTransfer(command.json());
Long officeId = null;
Office fromOffice = null;
if (moneyTransferCommand.getFromOfficeId() != null) {
fromOffice = this.officeRepository.findOne(moneyTransferCommand.getFromOfficeId());
final Long fromOfficeId = command.longValueOfParameterNamed("fromOfficeId");
if (fromOfficeId != null) {
fromOffice = this.officeRepository.findOne(fromOfficeId);
officeId = fromOffice.getId();
}
Office toOffice = null;
if (moneyTransferCommand.getToOfficeId() != null) {
toOffice = this.officeRepository.findOne(moneyTransferCommand.getToOfficeId());
final Long toOfficeId = command.longValueOfParameterNamed("toOfficeId");
if (toOfficeId != null) {
toOffice = this.officeRepository.findOne(toOfficeId);
officeId = toOffice.getId();
}
if (fromOffice == null && toOffice == null) { throw new OfficeNotFoundException(moneyTransferCommand.getToOfficeId()); }
if (fromOffice == null && toOffice == null) { throw new OfficeNotFoundException(toOfficeId); }
final String currencyCode = moneyTransferCommand.getCurrencyCode();
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
final ApplicationCurrency appCurrency = this.applicationCurrencyRepository.findOneByCode(currencyCode);
if (appCurrency == null) { throw new CurrencyNotFoundException(currencyCode); }
final MonetaryCurrency currency = new MonetaryCurrency(appCurrency.getCode(), appCurrency.getDecimalPlaces());
final Money amount = Money.of(currency, moneyTransferCommand.getTransactionAmount());
final Money amount = Money.of(currency, command.bigDecimalValueOfParameterNamed("transactionAmount"));
final OfficeTransaction entity = OfficeTransaction.fromJson(fromOffice, toOffice, amount, command);
this.officeTransactionRepository.save(entity);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(entity.getId()).withOfficeId(officeId)
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(entity.getId()) //
.withOfficeId(officeId) //
.build();
}
@@ -166,7 +175,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
public CommandProcessingResult deleteOfficeTransaction(final Long transactionId, JsonCommand command) {
context.authenticatedUser();
this.officeTransactionRepository.delete(transactionId);
return new CommandProcessingResultBuilder() //
@@ -264,8 +264,12 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.clientIdentifierRepository.save(clientIdentifier);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(client.getOffice().getId())
.withClientId(clientId).withEntityId(clientIdentifier.getId()).build();
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(clientIdentifier.getId()) //
.build();
} catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return CommandProcessingResult.empty();
@@ -317,8 +321,13 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
}
final Client client = this.clientRepository.findOne(clientId);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(client.getOffice().getId())
.withClientId(clientId).withEntityId(identifierId).with(changes).build();
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(identifierId) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return new CommandProcessingResult(Long.valueOf(-1));