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 @Override
public CommandProcessingResult processCommand(final JsonCommand command) { 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 updateOffice(Long officeId, JsonCommand command);
CommandProcessingResult externalBranchMoneyTransfer(JsonCommand command); CommandProcessingResult officeTransaction(JsonCommand command);
CommandProcessingResult deleteOfficeTransaction(Long id, 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.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.monetary.exception.CurrencyNotFoundException; 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.Office;
import org.mifosplatform.organisation.office.domain.OfficeRepository; import org.mifosplatform.organisation.office.domain.OfficeRepository;
import org.mifosplatform.organisation.office.domain.OfficeTransaction; import org.mifosplatform.organisation.office.domain.OfficeTransaction;
import org.mifosplatform.organisation.office.domain.OfficeTransactionRepository; import org.mifosplatform.organisation.office.domain.OfficeTransactionRepository;
import org.mifosplatform.organisation.office.exception.OfficeNotFoundException; 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.OfficeCommandFromApiJsonDeserializer;
import org.mifosplatform.organisation.office.serialization.OfficeTransactionCommandFromApiJsonDeserializer;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -36,7 +35,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final OfficeCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final OfficeCommandFromApiJsonDeserializer fromApiJsonDeserializer;
private final BranchMoneyTransferCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer; private final OfficeTransactionCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer;
private final OfficeRepository officeRepository; private final OfficeRepository officeRepository;
private final OfficeTransactionRepository officeTransactionRepository; private final OfficeTransactionRepository officeTransactionRepository;
private final ApplicationCurrencyRepository applicationCurrencyRepository; private final ApplicationCurrencyRepository applicationCurrencyRepository;
@@ -44,7 +43,7 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
@Autowired @Autowired
public OfficeWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public OfficeWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final OfficeCommandFromApiJsonDeserializer fromApiJsonDeserializer, final OfficeCommandFromApiJsonDeserializer fromApiJsonDeserializer,
final BranchMoneyTransferCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer, final OfficeTransactionCommandFromApiJsonDeserializer moneyTransferCommandFromApiJsonDeserializer,
final OfficeRepository officeRepository, final OfficeTransactionRepository officeMonetaryTransferRepository, final OfficeRepository officeRepository, final OfficeTransactionRepository officeMonetaryTransferRepository,
final ApplicationCurrencyRepository applicationCurrencyRepository) { final ApplicationCurrencyRepository applicationCurrencyRepository) {
this.context = context; this.context = context;
@@ -79,8 +78,11 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
this.officeRepository.save(office); this.officeRepository.save(office);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(office.getId()) return new CommandProcessingResultBuilder() //
.withOfficeId(office.getId()).build(); .withCommandId(command.commandId()) //
.withEntityId(office.getId()) //
.withOfficeId(office.getId()) //
.build();
} catch (DataIntegrityViolationException dve) { } catch (DataIntegrityViolationException dve) {
handleOfficeDataIntegrityIssues(command, dve); handleOfficeDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty(); return CommandProcessingResult.empty();
@@ -114,8 +116,12 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
this.officeRepository.saveAndFlush(office); this.officeRepository.saveAndFlush(office);
} }
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(office.getId()) return new CommandProcessingResultBuilder() //
.withOfficeId(office.getId()).with(changes).build(); .withCommandId(command.commandId()) //
.withEntityId(office.getId()) //
.withOfficeId(office.getId()) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) { } catch (DataIntegrityViolationException dve) {
handleOfficeDataIntegrityIssues(command, dve); handleOfficeDataIntegrityIssues(command, dve);
return CommandProcessingResult.empty(); return CommandProcessingResult.empty();
@@ -124,40 +130,43 @@ public class OfficeWritePlatformServiceJpaRepositoryImpl implements OfficeWriteP
@Transactional @Transactional
@Override @Override
public CommandProcessingResult externalBranchMoneyTransfer(final JsonCommand command) { public CommandProcessingResult officeTransaction(final JsonCommand command) {
context.authenticatedUser(); context.authenticatedUser();
final BranchMoneyTransferCommand moneyTransferCommand = this.moneyTransferCommandFromApiJsonDeserializer.commandFromApiJson(command this.moneyTransferCommandFromApiJsonDeserializer.validateOfficeTransfer(command.json());
.json());
moneyTransferCommand.validateBranchTransfer();
Long officeId = null; Long officeId = null;
Office fromOffice = null; Office fromOffice = null;
if (moneyTransferCommand.getFromOfficeId() != null) { final Long fromOfficeId = command.longValueOfParameterNamed("fromOfficeId");
fromOffice = this.officeRepository.findOne(moneyTransferCommand.getFromOfficeId()); if (fromOfficeId != null) {
fromOffice = this.officeRepository.findOne(fromOfficeId);
officeId = fromOffice.getId(); officeId = fromOffice.getId();
} }
Office toOffice = null; Office toOffice = null;
if (moneyTransferCommand.getToOfficeId() != null) { final Long toOfficeId = command.longValueOfParameterNamed("toOfficeId");
toOffice = this.officeRepository.findOne(moneyTransferCommand.getToOfficeId()); if (toOfficeId != null) {
toOffice = this.officeRepository.findOne(toOfficeId);
officeId = toOffice.getId(); 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); final ApplicationCurrency appCurrency = this.applicationCurrencyRepository.findOneByCode(currencyCode);
if (appCurrency == null) { throw new CurrencyNotFoundException(currencyCode); } if (appCurrency == null) { throw new CurrencyNotFoundException(currencyCode); }
final MonetaryCurrency currency = new MonetaryCurrency(appCurrency.getCode(), appCurrency.getDecimalPlaces()); 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); final OfficeTransaction entity = OfficeTransaction.fromJson(fromOffice, toOffice, amount, command);
this.officeTransactionRepository.save(entity); 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(); .build();
} }
@@ -264,8 +264,12 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
this.clientIdentifierRepository.save(clientIdentifier); this.clientIdentifierRepository.save(clientIdentifier);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(client.getOffice().getId()) return new CommandProcessingResultBuilder() //
.withClientId(clientId).withEntityId(clientIdentifier.getId()).build(); .withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(clientIdentifier.getId()) //
.build();
} catch (DataIntegrityViolationException dve) { } catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve); handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return CommandProcessingResult.empty(); return CommandProcessingResult.empty();
@@ -317,8 +321,13 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
} }
final Client client = this.clientRepository.findOne(clientId); final Client client = this.clientRepository.findOne(clientId);
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withOfficeId(client.getOffice().getId()) return new CommandProcessingResultBuilder() //
.withClientId(clientId).withEntityId(identifierId).with(changes).build(); .withCommandId(command.commandId()) //
.withOfficeId(client.getOffice().getId()) //
.withClientId(clientId) //
.withEntityId(identifierId) //
.with(changes) //
.build();
} catch (DataIntegrityViolationException dve) { } catch (DataIntegrityViolationException dve) {
handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve); handleClientIdentifierDataIntegrityViolation(documentTypeLabel, documentTypeId, documentKey, dve);
return new CommandProcessingResult(Long.valueOf(-1)); return new CommandProcessingResult(Long.valueOf(-1));