MIFOSX-939 - corrected order of saving transactions

This commit is contained in:
Pramod Nuthakki
2014-02-28 22:47:58 +05:30
parent e6b2a35f41
commit 59b7bcc499
8 changed files with 55 additions and 47 deletions
@@ -0,0 +1,4 @@
ALTER TABLE `m_savings_account_transaction`
ADD COLUMN `created_date` DATETIME NOT NULL AFTER `cumulative_balance_derived`;
update m_savings_account_transaction sat set sat.created_date=sat.transaction_date;
@@ -1,6 +1,7 @@
package org.mifosplatform.portfolio.savings.data; package org.mifosplatform.portfolio.savings.data;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.DateTimeFormatter;
@@ -12,13 +13,15 @@ public class SavingsAccountTransactionDTO {
private final LocalDate transactionDate; private final LocalDate transactionDate;
private final BigDecimal transactionAmount; private final BigDecimal transactionAmount;
private final PaymentDetail paymentDetail; private final PaymentDetail paymentDetail;
private final Date crecreatedDate;
public SavingsAccountTransactionDTO(final DateTimeFormatter formatter, final LocalDate transactionDate, public SavingsAccountTransactionDTO(final DateTimeFormatter formatter, final LocalDate transactionDate,
final BigDecimal transactionAmount, final PaymentDetail paymentDetail) { final BigDecimal transactionAmount, final PaymentDetail paymentDetail,final Date crecreatedDate) {
this.formatter = formatter; this.formatter = formatter;
this.transactionDate = transactionDate; this.transactionDate = transactionDate;
this.transactionAmount = transactionAmount; this.transactionAmount = transactionAmount;
this.paymentDetail = paymentDetail; this.paymentDetail = paymentDetail;
this.crecreatedDate = crecreatedDate;
} }
public DateTimeFormatter getFormatter() { public DateTimeFormatter getFormatter() {
@@ -36,4 +39,8 @@ public class SavingsAccountTransactionDTO {
public PaymentDetail getPaymentDetail() { public PaymentDetail getPaymentDetail() {
return this.paymentDetail; return this.paymentDetail;
} }
public Date getCrecreatedDate() {
return this.crecreatedDate;
}
} }
@@ -231,7 +231,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
@Embedded @Embedded
private SavingsAccountSummary summary; private SavingsAccountSummary summary;
@OrderBy(value = "dateOf, id") @OrderBy(value = "dateOf, createdDate, id")
@LazyCollection(LazyCollectionOption.FALSE) @LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true) @OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true)
private final List<SavingsAccountTransaction> transactions = new ArrayList<SavingsAccountTransaction>(); private final List<SavingsAccountTransaction> transactions = new ArrayList<SavingsAccountTransaction>();
@@ -495,13 +495,13 @@ public class SavingsAccount extends AbstractPersistable<Long> {
private List<SavingsAccountTransaction> retreiveListOfTransactions() { private List<SavingsAccountTransaction> retreiveListOfTransactions() {
final List<SavingsAccountTransaction> listOfTransactionsSorted = new ArrayList<SavingsAccountTransaction>(); final List<SavingsAccountTransaction> listOfTransactionsSorted = new ArrayList<SavingsAccountTransaction>();
for (final SavingsAccountTransaction transaction : this.transactions) { listOfTransactionsSorted.addAll(this.transactions);
/* for (final SavingsAccountTransaction transaction : this.transactions) {
listOfTransactionsSorted.add(transaction); listOfTransactionsSorted.add(transaction);
} }
*/
final SavingsAccountTransactionComparator transactionComparator = new SavingsAccountTransactionComparator(); final SavingsAccountTransactionComparator transactionComparator = new SavingsAccountTransactionComparator();
Collections.sort(listOfTransactionsSorted, transactionComparator); Collections.sort(listOfTransactionsSorted, transactionComparator);
return listOfTransactionsSorted; return listOfTransactionsSorted;
} }
@@ -615,7 +615,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final Money amount = Money.of(this.currency, transactionDTO.getTransactionAmount()); final Money amount = Money.of(this.currency, transactionDTO.getTransactionAmount());
final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(this, office(), transactionDTO.getPaymentDetail(), final SavingsAccountTransaction transaction = SavingsAccountTransaction.deposit(this, office(), transactionDTO.getPaymentDetail(),
transactionDTO.getTransactionDate(), amount); transactionDTO.getTransactionDate(), amount, transactionDTO.getCrecreatedDate());
this.transactions.add(transaction); this.transactions.add(transaction);
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions); this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
@@ -686,7 +686,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final Money transactionAmountMoney = Money.of(this.currency, transactionDTO.getTransactionAmount()); final Money transactionAmountMoney = Money.of(this.currency, transactionDTO.getTransactionAmount());
final SavingsAccountTransaction transaction = SavingsAccountTransaction.withdrawal(this, office(), final SavingsAccountTransaction transaction = SavingsAccountTransaction.withdrawal(this, office(),
transactionDTO.getPaymentDetail(), transactionDTO.getTransactionDate(), transactionAmountMoney); transactionDTO.getPaymentDetail(), transactionDTO.getTransactionDate(), transactionAmountMoney,
transactionDTO.getCrecreatedDate());
this.transactions.add(transaction); this.transactions.add(transaction);
if (applyWithdrawFee){ if (applyWithdrawFee){
@@ -1530,7 +1531,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance); final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance);
if (minRequiredOpeningBalance.isGreaterThanZero()) { if (minRequiredOpeningBalance.isGreaterThanZero()) {
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(), final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
minRequiredOpeningBalance.getAmount(), null); minRequiredOpeningBalance.getAmount(), null,new Date());
deposit(transactionDTO); deposit(transactionDTO);
// no openingBalance concept supported yet but probably will to // no openingBalance concept supported yet but probably will to
@@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.savings.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.MathContext; import java.math.MathContext;
import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -53,7 +54,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final Set<Long> existingReversedTransactionIds = new HashSet<Long>(); final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail); paymentDetail,new Date());
final SavingsAccountTransaction withdrawal = account.withdraw(transactionDTO, applyWithdrawFee); final SavingsAccountTransaction withdrawal = account.withdraw(transactionDTO, applyWithdrawFee);
final MathContext mc = MathContext.DECIMAL64; final MathContext mc = MathContext.DECIMAL64;
@@ -82,7 +83,7 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final Set<Long> existingReversedTransactionIds = new HashSet<Long>(); final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds); updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail); paymentDetail,new Date());
final SavingsAccountTransaction deposit = account.deposit(transactionDTO); final SavingsAccountTransaction deposit = account.deposit(transactionDTO);
final MathContext mc = MathContext.DECIMAL64; final MathContext mc = MathContext.DECIMAL64;
@@ -92,24 +92,29 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
@Column(name = "overdraft_amount_derived", scale = 6, precision = 19, nullable = true) @Column(name = "overdraft_amount_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal overdraftAmount; private BigDecimal overdraftAmount;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_date", nullable = false)
private final Date createdDate;
protected SavingsAccountTransaction() { protected SavingsAccountTransaction() {
this.dateOf = null; this.dateOf = null;
this.typeOf = null; this.typeOf = null;
this.createdDate = null;
} }
public static SavingsAccountTransaction deposit(final SavingsAccount savingsAccount, final Office office, public static SavingsAccountTransaction deposit(final SavingsAccount savingsAccount, final Office office,
final PaymentDetail paymentDetail, final LocalDate date, final Money amount) { final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate) {
final boolean isReversed = false; final boolean isReversed = false;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.DEPOSIT.getValue(), date, return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.DEPOSIT.getValue(), date,
amount, isReversed); createdDate, amount, isReversed);
} }
public static SavingsAccountTransaction withdrawal(final SavingsAccount savingsAccount, final Office office, public static SavingsAccountTransaction withdrawal(final SavingsAccount savingsAccount, final Office office,
final PaymentDetail paymentDetail, final LocalDate date, final Money amount) { final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate) {
final boolean isReversed = false; final boolean isReversed = false;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.WITHDRAWAL.getValue(), return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.WITHDRAWAL.getValue(),
date, amount, isReversed); date,createdDate, amount, isReversed);
} }
public static SavingsAccountTransaction interestPosting(final SavingsAccount savingsAccount, final Office office, final LocalDate date, public static SavingsAccountTransaction interestPosting(final SavingsAccount savingsAccount, final Office office, final LocalDate date,
@@ -151,7 +156,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
final boolean isReversed = false; final boolean isReversed = false;
final PaymentDetail paymentDetail = null; final PaymentDetail paymentDetail = null;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
SavingsAccountTransactionType.INITIATE_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), SavingsAccountTransactionType.INITIATE_TRANSFER.getValue(), date, new Date(),savingsAccount.getSummary().getAccountBalance(),
isReversed); isReversed);
} }
@@ -159,7 +164,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
final boolean isReversed = false; final boolean isReversed = false;
final PaymentDetail paymentDetail = null; final PaymentDetail paymentDetail = null;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
SavingsAccountTransactionType.APPROVE_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), SavingsAccountTransactionType.APPROVE_TRANSFER.getValue(), date,new Date(), savingsAccount.getSummary().getAccountBalance(),
isReversed); isReversed);
} }
@@ -167,29 +172,29 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
final boolean isReversed = false; final boolean isReversed = false;
final PaymentDetail paymentDetail = null; final PaymentDetail paymentDetail = null;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, return new SavingsAccountTransaction(savingsAccount, office, paymentDetail,
SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date,new Date(), savingsAccount.getSummary().getAccountBalance(),
isReversed); isReversed);
} }
public static SavingsAccountTransaction copyTransaction(SavingsAccountTransaction accountTransaction) { public static SavingsAccountTransaction copyTransaction(SavingsAccountTransaction accountTransaction) {
return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail, return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail,
accountTransaction.typeOf, accountTransaction.transactionLocalDate(), accountTransaction.amount, accountTransaction.typeOf, accountTransaction.transactionLocalDate(),accountTransaction.createdDate, accountTransaction.amount,
accountTransaction.reversed); accountTransaction.reversed);
} }
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf, private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf,
final LocalDate transactionLocalDate, final Money amount, final boolean isReversed) { final LocalDate transactionLocalDate, final Money amount, final boolean isReversed) {
this(savingsAccount, office, null, typeOf, transactionLocalDate, amount, isReversed); this(savingsAccount, office, null, typeOf, transactionLocalDate, new Date(),amount, isReversed);
} }
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail,
final Integer typeOf, final LocalDate transactionLocalDate, final Money amount, final boolean isReversed) { final Integer typeOf, final LocalDate transactionLocalDate,final Date createdDate, final Money amount, final boolean isReversed) {
this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate, amount.getAmount(), isReversed); this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate,createdDate, amount.getAmount(), isReversed);
} }
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail,
final Integer typeOf, final LocalDate transactionLocalDate, final BigDecimal amount, final boolean isReversed) { final Integer typeOf, final LocalDate transactionLocalDate, final Date createdDate, final BigDecimal amount, final boolean isReversed) {
this.savingsAccount = savingsAccount; this.savingsAccount = savingsAccount;
this.office = office; this.office = office;
this.typeOf = typeOf; this.typeOf = typeOf;
@@ -197,7 +202,7 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
this.amount = amount; this.amount = amount;
this.reversed = isReversed; this.reversed = isReversed;
this.paymentDetail = paymentDetail; this.paymentDetail = paymentDetail;
this.createdDate = createdDate;
} }
public LocalDate transactionLocalDate() { public LocalDate transactionLocalDate() {
@@ -555,5 +560,9 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
return Money.of(currency, this.overdraftAmount); return Money.of(currency, this.overdraftAmount);
} }
public Date createdDate() {
return this.createdDate;
}
} }
@@ -15,30 +15,18 @@ public class SavingsAccountTransactionComparator implements Comparator<SavingsAc
@Override @Override
public int compare(final SavingsAccountTransaction o1, final SavingsAccountTransaction o2) { public int compare(final SavingsAccountTransaction o1, final SavingsAccountTransaction o2) {
int compareResult = 0; int compareResult = 0;
final int comparsion = o1.transactionLocalDate().compareTo(o2.transactionLocalDate()); final int comparsion = o1.transactionLocalDate().compareTo(o2.transactionLocalDate());
if (comparsion == 0) { if (comparsion == 0) {
// equal transaction dates compareResult = o1.createdDate().compareTo(o2.createdDate());
if (o1.isInterestPostingAndNotReversed() && !o2.isInterestPostingAndNotReversed()) { if(compareResult == 0){
compareResult = -1; compareResult = o1.getId().compareTo(o2.getId());
} else if (!o1.isInterestPostingAndNotReversed() && o2.isInterestPostingAndNotReversed()) { }else{
compareResult = 1; compareResult = comparsion;
} else if (!o1.isDepositAndNotReversed() && o2.isDepositAndNotReversed()) { }
// push all deposit transactions before charge/withdrawal transactions on same day.
// activation charge is charged on account activation date, any
// adjustments with deposit amount
// resulting into negative balance, to fix this push deposit
// transactions before charge/withdrawal charges transactions.
compareResult = 1;
} else if (o1.isDepositAndNotReversed() && !o2.isDepositAndNotReversed()) {
compareResult = -1;
} else {
compareResult = 0;
}
} else { } else {
compareResult = comparsion; compareResult = comparsion;
} }
return compareResult; return compareResult;
} }
} }
@@ -543,7 +543,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
@Override @Override
public Collection<SavingsAccountTransactionData> retrieveAllTransactions(final Long savingsId) { public Collection<SavingsAccountTransactionData> retrieveAllTransactions(final Long savingsId) {
final String sql = "select " + this.transactionsMapper.schema() + " where sa.id = ? order by tr.transaction_date DESC, tr.id DESC"; final String sql = "select " + this.transactionsMapper.schema() + " where sa.id = ? order by tr.transaction_date DESC, tr.created_date DESC, tr.id DESC";
return this.jdbcTemplate.query(sql, this.transactionsMapper, new Object[] { savingsId }); return this.jdbcTemplate.query(sql, this.transactionsMapper, new Object[] { savingsId });
} }
@@ -441,13 +441,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
} }
SavingsAccountTransaction transaction = null; SavingsAccountTransaction transaction = null;
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail,savingsAccountTransaction.createdDate());
if (savingsAccountTransaction.isDeposit()) { if (savingsAccountTransaction.isDeposit()) {
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail);
transaction = account.deposit(transactionDTO); transaction = account.deposit(transactionDTO);
} else { } else {
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount,
paymentDetail);
transaction = account.withdraw(transactionDTO, true); transaction = account.withdraw(transactionDTO, true);
} }
final Long newtransactionId = saveTransactionToGenerateTransactionId(transaction); final Long newtransactionId = saveTransactionToGenerateTransactionId(transaction);