Merge pull request #937 from pramodn02/MIFOSX-1270

MIFOSX-1270 : corrected accounting for  activation charge
This commit is contained in:
Vishwas Babu A J
2014-06-10 14:50:48 -07:00
2 changed files with 81 additions and 21 deletions
@@ -77,7 +77,7 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
transactionId, transactionDate, overdraftAmount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
ORGANIZATION_ACCOUNTS.LIABILITY_TRANSFER_SUSPENSE.getValue(),
@@ -88,7 +88,7 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount, isReversal);
transactionId, transactionDate, overdraftAmount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_REFERENCE.getValue(),
@@ -130,6 +130,23 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
* Handle Interest Applications and reversals of Interest
* Applications
**/
else if (savingsTransactionDTO.getTransactionType().isInterestPosting() && savingsTransactionDTO.isOverdraftTransaction()) {
// Post journal entry if earned interest amount is greater than
// zero
if (savingsTransactionDTO.getAmount().compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, overdraftAmount, isReversal);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavings(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS.getValue(),
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), savingsProductId, paymentTypeId, savingsId,
transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal);
}
}
}
else if (savingsTransactionDTO.getTransactionType().isInterestPosting()) {
// Post journal entry if earned interest amount is greater than
// zero
@@ -141,6 +158,33 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess
}
/** Handle Fees Deductions and reversals of Fees Deductions **/
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction() && savingsTransactionDTO.isOverdraftTransaction()) {
// Is the Charge a penalty?
if (penaltyPayments.size() > 0) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal,
penaltyPayments);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_PENALTIES,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate,
amount.subtract(overdraftAmount), isReversal, penaltyPayments);
}
} else {
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.OVERDRAFT_PORTFOLIO_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES,
savingsProductId, paymentTypeId, savingsId, transactionId, transactionDate, overdraftAmount, isReversal,
feePayments);
if (amount.subtract(overdraftAmount).compareTo(BigDecimal.ZERO) == 1) {
this.helper.createCashBasedJournalEntriesAndReversalsForSavingsCharges(office, currencyCode,
CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES, savingsProductId,
paymentTypeId, savingsId, transactionId, transactionDate, amount.subtract(overdraftAmount), isReversal,
feePayments);
}
}
}
else if (savingsTransactionDTO.getTransactionType().isFeeDeduction()) {
// Is the Charge a penalty?
if (penaltyPayments.size() > 0) {
@@ -449,9 +449,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
* calculate the amount of interest due at the end of each 'crediting'
* period check if an existing 'interest posting' transaction exists for
* date and matches the amount posted
* @param isInterestTransfer TODO
*
* @param isInterestTransfer
* TODO
*/
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate upToInterestCalculationDate, boolean isInterestTransfer) {
public List<PostingPeriod> calculateInterestUsing(final MathContext mc, final LocalDate upToInterestCalculationDate,
boolean isInterestTransfer) {
// no openingBalance concept supported yet but probably will to allow
// for migrations.
@@ -488,7 +491,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final PostingPeriod postingPeriod = PostingPeriod.createFrom(periodInterval, periodStartingBalance,
retreiveOrderedNonInterestPostingTransactions(), this.currency, compoundingPeriodType, interestCalculationType,
interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions, isInterestTransfer);
interestRateAsFraction, daysInYearType.getValue(), upToInterestCalculationDate, interestPostTransactions,
isInterestTransfer);
periodStartingBalance = postingPeriod.closingBalance();
@@ -587,9 +591,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
resetAccountTransactionsEndOfDayBalances(accountTransactionsSorted, interestPostingUpToDate);
}
protected void resetAccountTransactionsEndOfDayBalances(final List<SavingsAccountTransaction> accountTransactionsSorted, final LocalDate interestPostingUpToDate) {
// loop over transactions in reverse
protected void resetAccountTransactionsEndOfDayBalances(final List<SavingsAccountTransaction> accountTransactionsSorted,
final LocalDate interestPostingUpToDate) {
// loop over transactions in reverse
LocalDate endOfBalanceDate = interestPostingUpToDate;
for (int i = accountTransactionsSorted.size() - 1; i >= 0; i--) {
final SavingsAccountTransaction transaction = accountTransactionsSorted.get(i);
@@ -618,8 +623,9 @@ public class SavingsAccount extends AbstractPersistable<Long> {
if (isDateInTheFuture(transactionDTO.getTransactionDate())) {
final String defaultUserMessage = "Transaction date cannot be in the future.";
final ApiParameterError error = ApiParameterError.parameterError("error.msg." + resourceTypeName + ".transaction.in.the.future",
defaultUserMessage, "transactionDate", transactionDTO.getTransactionDate().toString(transactionDTO.getFormatter()));
final ApiParameterError error = ApiParameterError.parameterError(
"error.msg." + resourceTypeName + ".transaction.in.the.future", defaultUserMessage, "transactionDate", transactionDTO
.getTransactionDate().toString(transactionDTO.getFormatter()));
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
dataValidationErrors.add(error);
@@ -790,8 +796,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
if (runningBalance.isLessThanZero()) {
//
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + transactionAction);
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(depositAccountType()
.resourceName() + transactionAction);
if (this.allowOverdraft) {
Money limit = runningBalance.zero();
@@ -1316,7 +1322,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
if (transactionToUndo == null) { throw new SavingsAccountTransactionNotFoundException(this.getId(), transactionId); }
validateAttemptToUndoTransferRelatedTransactions(transactionToUndo);
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_UNDO_TRANSACTION, transactionToUndo.transactionLocalDate());
transactionToUndo.reverse();
@@ -1480,8 +1486,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.activateAction);
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(depositAccountType()
.resourceName() + SavingsApiConstants.activateAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.APPROVED.hasStateOf(currentStatus)) {
@@ -1553,10 +1559,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
validateActivityNotBeforeClientOrGroupTransferDate(SavingsEvent.SAVINGS_ACTIVATE, activationDate);
// auto enter deposit for minimum required opening balance when
// activating account.
processAccountUponActivation();
return actualChanges;
}
@@ -1592,11 +1594,25 @@ public class SavingsAccount extends AbstractPersistable<Long> {
}
private void payActivationCharges() {
boolean isSavingsChargeApplied = false;
for (SavingsAccountCharge savingsAccountCharge : this.charges()) {
if (savingsAccountCharge.isSavingsActivation()) {
isSavingsChargeApplied = true;
payCharge(savingsAccountCharge, savingsAccountCharge.getAmountOutstanding(getCurrency()), getActivationLocalDate());
}
}
if (isSavingsChargeApplied) {
final MathContext mc = MathContext.DECIMAL64;
boolean isInterestTransfer = false;
if (this.isBeforeLastPostingPeriod(getActivationLocalDate())) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
this.postInterest(mc, today, isInterestTransfer);
} else {
final LocalDate today = DateUtils.getLocalDateOfTenant();
this.calculateInterestUsing(mc, today, isInterestTransfer);
}
}
}
public Map<String, Object> close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) {
@@ -2027,7 +2043,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
baseDataValidator.reset().parameter(SavingsApiConstants.overdraftLimitParamName).value(this.overdraftLimit)
.failWithCode("cannot.exceed.product.value");
}
validateInterestPostingAndCompoundingPeriodTypes(baseDataValidator);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
@@ -2054,7 +2070,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
return getActivationLocalDate().isEqual(getSubmittedOnLocalDate());
}
public void validateInterestPostingAndCompoundingPeriodTypes(final DataValidatorBuilder baseDataValidator) {
Map<SavingsPostingInterestPeriodType, List<SavingsCompoundingInterestPeriodType>> postingtoCompoundMap = new HashMap<SavingsPostingInterestPeriodType, List<SavingsCompoundingInterestPeriodType>>();
postingtoCompoundMap.put(