MIFOSX-43: tidy up approval code so exception isnt thrown and no need for new data object to pass details around.

This commit is contained in:
Keith Woodlock
2012-08-30 10:31:49 +01:00
parent 508a46e537
commit 57b38e463a
4 changed files with 33 additions and 107 deletions
@@ -15,6 +15,7 @@ import javax.persistence.UniqueConstraint;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.currency.domain.Money;
@@ -41,25 +42,21 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "external_id")
private String externalId;
@SuppressWarnings("unused")
@Embedded
private MonetaryCurrency currency;
@Column(name = "deposit_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal depositAmount;
@SuppressWarnings("unused")
@Column(name = "maturity_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal interestRate;
@Column(name = "tenure_months", nullable=false)
private Integer tenureInMonths;
@SuppressWarnings("unused")
@Column(name = "interest_compounded_every", nullable = false)
private Integer interestCompoundedEvery;
@SuppressWarnings("unused")
@Column(name = "interest_compounded_every_period_enum", nullable = false)
private Integer interestCompoundedFrequencyType;
@@ -220,35 +217,39 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
public void approve(
final LocalDate actualCommencementDate,
final DepositLifecycleStateMachine depositLifecycleStateMachine,
final DepositApprovalData depositApprovalData,
final BigDecimal depositAmount) {
final DepositStateTransitionApprovalCommand command,
final FixedTermDepositInterestCalculator calculator) {
DepositStatus statusEnum = depositLifecycleStateMachine.transition(DepositEvent.DEPOSIT_APPROVED, DepositStatus.fromInt(this.depositStatus));
this.depositStatus = statusEnum.getValue();
this.tenureInMonths = depositApprovalData.getTenureInMonths();
this.depositAmount = depositAmount;
this.interestCompoundedFrequencyType = depositApprovalData.getInterestCompoundedEveryPeriodType().getValue();
this.actualCommencementDate = actualCommencementDate.toDateTimeAtCurrentTime().toDate();
if (command.getTenureInMonths() != null) {
this.tenureInMonths = command.getTenureInMonths();
}
if(this.actualCommencementDate != null)
if (command.getDepositAmount() != null) {
this.depositAmount = command.getDepositAmount();
}
if (command.getInterestCompoundedEveryPeriodType() != null) {
this.interestCompoundedFrequencyType = PeriodFrequencyType.fromInt(command.getInterestCompoundedEveryPeriodType()).getValue();
}
this.actualCommencementDate = actualCommencementDate.toDate();
this.actualMaturityDate = new LocalDate(this.actualCommencementDate).plusMonths(this.tenureInMonths).toDate();
FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator = depositApprovalData.getFixedTermDepositInterestCalculator();
Money futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths,
this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
Money futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(depositApprovalData.getDeposit(), depositApprovalData.getTenureInMonths(),
depositApprovalData.getMaturityInterestRate(), depositApprovalData.getInterestCompoundedEvery(), depositApprovalData.getInterestCompoundedEveryPeriodType());
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(depositApprovalData.getDeposit()).getAmount();
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(getDeposit()).getAmount();
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
LocalDate submittalDate = new LocalDate(this.projectedCommencementDate);
if (actualCommencementDate.isBefore(submittalDate)) {
final String errorMessage = "The date on which a deposit is approved cannot be before its submittal date: " + submittalDate.toString();
throw new InvalidDepositStateTransitionException("approval", "cannot.be.before.submittal.date", errorMessage, getActualCommencementDate(), submittalDate);
}
if (actualCommencementDate.isAfter(new LocalDate())) {
final String errorMessage = "The date on which a deposit is approved cannot be in the future.";
throw new InvalidDepositStateTransitionException("approval", "cannot.be.a.future.date", errorMessage, getActualCommencementDate());
@@ -339,4 +340,12 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.actualCommencementDate = null;
this.actualMaturityDate = null;
}
public PeriodFrequencyType getInterestCompoundedFrequencyType() {
return PeriodFrequencyType.fromInt(this.interestCompoundedFrequencyType);
}
public Money getDeposit() {
return Money.of(this.currency, this.depositAmount);
}
}
@@ -1,55 +0,0 @@
package org.mifosng.platform.saving.domain;
import java.math.BigDecimal;
import org.mifosng.platform.currency.domain.Money;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
public class DepositApprovalData {
private final Integer tenureInMonths;
private final Money deposit;
private final BigDecimal maturityInterestRate;
private final Integer interestCompoundedEvery;
private final PeriodFrequencyType interestCompoundedEveryPeriodType;
private final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator;
public DepositApprovalData(
final Integer tenureInMonths,
final Money deposit,
final BigDecimal maturityInterestRate,
final Integer interestCompoundedEvery,
final PeriodFrequencyType interestCompoundedEveryPeriodType,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) {
this.tenureInMonths = tenureInMonths;
this.deposit = deposit;
this.maturityInterestRate = maturityInterestRate;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.fixedTermDepositInterestCalculator = fixedTermDepositInterestCalculator;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public Money getDeposit() {
return deposit;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public PeriodFrequencyType getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public FixedTermDepositInterestCalculator getFixedTermDepositInterestCalculator() {
return fixedTermDepositInterestCalculator;
}
}
@@ -5,7 +5,6 @@ import java.util.Arrays;
import java.util.List;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.client.domain.Client;
import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.currency.domain.Money;
@@ -13,7 +12,6 @@ import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.DepositProductNotFoundException;
import org.mifosng.platform.loan.domain.PeriodFrequencyType;
import org.mifosng.platform.saving.domain.DepositAccount;
import org.mifosng.platform.saving.domain.DepositApprovalData;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachineImpl;
import org.mifosng.platform.saving.domain.DepositStatus;
@@ -97,28 +95,6 @@ public class DepositAccountAssembler {
return account;
}
public DepositApprovalData assembleFrom(DepositStateTransitionApprovalCommand command){
DepositProduct product = this.depositProductRepository.findOne(command.getProductId());
if (product == null || product.isDeleted()) {
throw new DepositProductNotFoundException(command.getProductId());
}
PeriodFrequencyType interestCompoundedEveryPeriodType= product.getInterestCompoundedEveryPeriodType();
if (command.getInterestCompoundedEveryPeriodType() != null) {
interestCompoundedEveryPeriodType = PeriodFrequencyType.fromInt(command.getInterestCompoundedEveryPeriodType());
}
Integer tenureInMonths = command.getTenureInMonths();
Money deposit = Money.of(product.getCurrency(), command.getDepositAmount());
BigDecimal maturityInterestRate = product.getMaturityDefaultInterestRate();
Integer interestCompoundedEvery = product.getInterestCompoundedEvery();
return new DepositApprovalData(tenureInMonths, deposit, maturityInterestRate, interestCompoundedEvery, interestCompoundedEveryPeriodType, this.fixedTermDepositInterestCalculator);
}
private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() {
List<DepositStatus> allowedDepositStatuses = Arrays.asList(DepositStatus.values());
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
@@ -1,6 +1,5 @@
package org.mifosng.platform.saving.service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
@@ -16,10 +15,10 @@ import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
import org.mifosng.platform.exceptions.ProductNotFoundException;
import org.mifosng.platform.saving.domain.DepositAccount;
import org.mifosng.platform.saving.domain.DepositAccountRepository;
import org.mifosng.platform.saving.domain.DepositApprovalData;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachineImpl;
import org.mifosng.platform.saving.domain.DepositStatus;
import org.mifosng.platform.saving.domain.FixedTermDepositInterestCalculator;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.slf4j.Logger;
@@ -37,16 +36,18 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
private final PlatformSecurityContext context;
private final DepositAccountRepository depositAccountRepository;
private final DepositAccountAssembler depositAccountAssembler;
private final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator;
@Autowired
public DepositAccountWritePlatformServiceJpaRepositoryImpl(
final PlatformSecurityContext context,
final DepositAccountRepository depositAccountRepository,
final DepositAccountAssembler depositAccountAssembler) {
final DepositAccountAssembler depositAccountAssembler,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) {
this.context=context;
this.depositAccountRepository = depositAccountRepository;
this.depositAccountAssembler = depositAccountAssembler;
this.fixedTermDepositInterestCalculator = fixedTermDepositInterestCalculator;
}
/*
@@ -136,23 +137,18 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
DepositStateTransitionApprovalCommandValidator validator = new DepositStateTransitionApprovalCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
DepositApprovalData depositApprovalData=this.depositAccountAssembler.assembleFrom(command);
// FIXME - madhukar - you are checking for loan permission here instead of some specific deposit account permission.
LocalDate eventDate = command.getEventDate();
if (this.isBeforeToday(eventDate) && currentUser.canNotApproveLoanInPast()) {
throw new NoAuthorizationException("User has no authority to approve deposit with a date in the past.");
}
BigDecimal depositAmount = command.getDepositAmount();
account.approve(eventDate, defaultDepositLifecycleStateMachine(), depositApprovalData, depositAmount);
account.approve(eventDate, defaultDepositLifecycleStateMachine(), command, this.fixedTermDepositInterestCalculator);
this.depositAccountRepository.save(account);
return new EntityIdentifier(account.getId());