Transactions for DepositAccounts

This commit is contained in:
Madhukar
2012-09-05 18:29:04 +05:30
parent 464f146a7c
commit 4a90cb091a
5 changed files with 216 additions and 4 deletions
@@ -1,18 +1,25 @@
package org.mifosng.platform.saving.domain;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
@@ -126,6 +133,14 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
@Temporal(TemporalType.DATE)
@Column(name = "withdrawnon_date")
private Date withdrawnOnDate;
// see
// http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags
@OrderBy(value = "id")
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "depositAccount", orphanRemoval = true)
private final List<DepositAccountTransaction> depositaccountTransactions = new ArrayList<DepositAccountTransaction>();
public DepositAccount openNew(
final Client client, final DepositProduct product,
@@ -241,8 +256,13 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
Money futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths,
this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(getDeposit()).getAmount();
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.interestAccrued = futureValueOnMaturity.minus(getDeposit()).getAmount();
this.total = futureValueOnMaturity.getAmount();
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.deposit(futureValueOnMaturity,new LocalDate(this.actualCommencementDate));
this.depositaccountTransactions.add(depositaccountTransaction);
depositaccountTransaction.updateAccount(this);
LocalDate submittalDate = new LocalDate(this.projectedCommencementDate);
if (actualCommencementDate.isBefore(submittalDate)) {
@@ -339,6 +359,9 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.actualCommencementDate = null;
this.actualMaturityDate = null;
this.total=null;
this.interestAccrued=null;
this.depositaccountTransactions.clear();
}
public PeriodFrequencyType getInterestCompoundedFrequencyType() {
@@ -0,0 +1,133 @@
package org.mifosng.platform.saving.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.joda.time.LocalDate;
import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.currency.domain.Money;
import org.springframework.data.jpa.domain.AbstractPersistable;
import org.springframework.format.annotation.DateTimeFormat;
@Entity
@Table(name="m_deposit_account_transaction")
public class DepositAccountTransaction extends AbstractPersistable<Long> {
@ManyToOne(optional = false)
@JoinColumn(name = "deposit_account_id", nullable=false)
private DepositAccount depositAccount;
@Enumerated(EnumType.ORDINAL)
@Column(name = "transaction_type_enum", nullable = false)
private DepositTransactionType typeOf;
@OneToOne(optional=true, cascade={CascadeType.PERSIST})
@JoinColumn(name="contra_id")
private DepositAccountTransaction contra;
@Temporal(TemporalType.DATE)
@Column(name = "transaction_date", nullable=false)
private final Date dateOf;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private final BigDecimal amount;
protected DepositAccountTransaction(){
this.depositAccount=null;
this.typeOf=null;
this.amount=null;
this.dateOf=null;
}
private DepositAccountTransaction(DepositTransactionType type, final BigDecimal amount, final LocalDate date) {
this.typeOf = type;
this.amount = amount;
this.dateOf = date.toDateMidnight().toDate();
}
public Date getDateOf() {
return dateOf;
}
public BigDecimal getAmount() {
return amount;
}
public DepositTransactionType getTypeOf() {
return typeOf;
}
public Money getAmount(MonetaryCurrency currency) {
return Money.of(currency, this.amount);
}
@DateTimeFormat(style="-M")
public LocalDate getTransactionDate() {
return new LocalDate(this.dateOf);
}
public DepositAccountTransaction getContra() {
return contra;
}
public boolean isNotContra() {
return this.contra == null;
}
public boolean isDeposit(){
return DepositTransactionType.DEPOSIT.equals(typeOf) && isNotContra();
}
public static DepositAccountTransaction deposit(Money amount, LocalDate paymentDate) {
return new DepositAccountTransaction(DepositTransactionType.DEPOSIT, amount.getAmount(), paymentDate);
}
public static DepositAccountTransaction withdraw(Money amount, LocalDate paymentDate) {
return new DepositAccountTransaction(DepositTransactionType.WITHDRAW, amount.getAmount(), paymentDate);
}
private static DepositAccountTransaction contra(DepositAccountTransaction originalTransaction) {
DepositAccountTransaction contra = new DepositAccountTransaction(DepositTransactionType.REVERSAL, originalTransaction.getAmount().negate(), new LocalDate(originalTransaction.getDateOf()));
contra.updateContra(originalTransaction);
return contra;
}
public void updateContra(DepositAccountTransaction transaction) {
this.contra = transaction;
}
public DepositAccount getDepositAccount() {
return depositAccount;
}
public void setDepositAccount(DepositAccount depositAccount) {
this.depositAccount = depositAccount;
}
public void updateAccount(DepositAccount depositAccount) {
this.depositAccount=depositAccount;
}
}
@@ -0,0 +1,53 @@
package org.mifosng.platform.saving.domain;
public enum DepositTransactionType {
INVALID(0, "depositTransactionType.invalid"), DEPOSIT(1, "depositTransactionType.deposit"), WITHDRAW(2, "depositTransactionType.withdraw"), REVERSAL(3, "depositTransactionType.reversal");
private final Integer value;
private final String code;
private DepositTransactionType(final Integer value, final String code) {
this.value=value;
this.code=code;
}
public Integer getValue() {
return value;
}
public String getCode() {
return code;
}
public static DepositTransactionType fromInt(final Integer transactionType){
if (transactionType == null) {
return DepositTransactionType.INVALID;
}
DepositTransactionType depositTransactionType=null;
switch (transactionType) {
case 1:
depositTransactionType=DepositTransactionType.DEPOSIT;
break;
case 2:
depositTransactionType=DepositTransactionType.WITHDRAW;
break;
case 3:
depositTransactionType=DepositTransactionType.REVERSAL;
break;
default :
depositTransactionType=DepositTransactionType.INVALID;
break;
}
return depositTransactionType;
}
}
@@ -43,7 +43,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final PlatformSecurityContext context,
final DepositAccountRepository depositAccountRepository,
final DepositAccountAssembler depositAccountAssembler,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) {
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator
) {
this.context=context;
this.depositAccountRepository = depositAccountRepository;
this.depositAccountAssembler = depositAccountAssembler;
@@ -149,7 +150,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
}
account.approve(eventDate, defaultDepositLifecycleStateMachine(), command, this.fixedTermDepositInterestCalculator);
this.depositAccountRepository.save(account);
return new EntityIdentifier(account.getId());
@@ -25,7 +25,7 @@ public class DepositStateTransitionApprovalCommandValidator {
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("eventDate").value(command.getEventDate()).notNull();
baseDataValidator.reset().parameter("depositAmount").value(command.getDepositAmount()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("depositAmount").value(command.getDepositAmount()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);