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