Transactions for DepositAccounts
This commit is contained in:
+25
-2
@@ -1,18 +1,25 @@
|
|||||||
package org.mifosng.platform.saving.domain;
|
package org.mifosng.platform.saving.domain;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Embedded;
|
import javax.persistence.Embedded;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OrderBy;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.LazyCollection;
|
||||||
|
import org.hibernate.annotations.LazyCollectionOption;
|
||||||
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.api.commands.DepositStateTransitionApprovalCommand;
|
||||||
@@ -127,6 +134,14 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
@Column(name = "withdrawnon_date")
|
@Column(name = "withdrawnon_date")
|
||||||
private Date withdrawnOnDate;
|
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(
|
public DepositAccount openNew(
|
||||||
final Client client, final DepositProduct product,
|
final Client client, final DepositProduct product,
|
||||||
final String externalId, final Money deposit, final BigDecimal maturityInterestRate, final Integer tenureInMonths,
|
final String externalId, final Money deposit, final BigDecimal maturityInterestRate, final Integer tenureInMonths,
|
||||||
@@ -241,8 +256,13 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
Money futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths,
|
Money futureValueOnMaturity = calculator.calculateInterestOnMaturityFor(getDeposit(), this.tenureInMonths,
|
||||||
this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
|
this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
|
||||||
|
|
||||||
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(getDeposit()).getAmount();
|
this.interestAccrued = futureValueOnMaturity.minus(getDeposit()).getAmount();
|
||||||
this.projectedTotalOnMaturity = futureValueOnMaturity.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);
|
LocalDate submittalDate = new LocalDate(this.projectedCommencementDate);
|
||||||
if (actualCommencementDate.isBefore(submittalDate)) {
|
if (actualCommencementDate.isBefore(submittalDate)) {
|
||||||
@@ -339,6 +359,9 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
|
|||||||
|
|
||||||
this.actualCommencementDate = null;
|
this.actualCommencementDate = null;
|
||||||
this.actualMaturityDate = null;
|
this.actualMaturityDate = null;
|
||||||
|
this.total=null;
|
||||||
|
this.interestAccrued=null;
|
||||||
|
this.depositaccountTransactions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PeriodFrequencyType getInterestCompoundedFrequencyType() {
|
public PeriodFrequencyType getInterestCompoundedFrequencyType() {
|
||||||
|
|||||||
+133
@@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+53
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+4
-1
@@ -43,7 +43,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
|||||||
final PlatformSecurityContext context,
|
final PlatformSecurityContext context,
|
||||||
final DepositAccountRepository depositAccountRepository,
|
final DepositAccountRepository depositAccountRepository,
|
||||||
final DepositAccountAssembler depositAccountAssembler,
|
final DepositAccountAssembler depositAccountAssembler,
|
||||||
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) {
|
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator
|
||||||
|
) {
|
||||||
this.context=context;
|
this.context=context;
|
||||||
this.depositAccountRepository = depositAccountRepository;
|
this.depositAccountRepository = depositAccountRepository;
|
||||||
this.depositAccountAssembler = depositAccountAssembler;
|
this.depositAccountAssembler = depositAccountAssembler;
|
||||||
@@ -149,8 +150,10 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
|
|||||||
}
|
}
|
||||||
|
|
||||||
account.approve(eventDate, defaultDepositLifecycleStateMachine(), command, this.fixedTermDepositInterestCalculator);
|
account.approve(eventDate, defaultDepositLifecycleStateMachine(), command, this.fixedTermDepositInterestCalculator);
|
||||||
|
|
||||||
this.depositAccountRepository.save(account);
|
this.depositAccountRepository.save(account);
|
||||||
|
|
||||||
|
|
||||||
return new EntityIdentifier(account.getId());
|
return new EntityIdentifier(account.getId());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ public class DepositStateTransitionApprovalCommandValidator {
|
|||||||
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
|
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
|
||||||
baseDataValidator.reset().parameter("eventDate").value(command.getEventDate()).notNull();
|
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("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().integerGreaterThanZero();
|
||||||
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);
|
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user