/* * Copyright (c) 2005-2011 Grameen Foundation USA * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * See also http://www.apache.org/licenses/LICENSE-2.0.html for an * explanation of the license and how it is applied. */ package org.mifos.accounts.financial.business.service.activity.accountingentry; import org.mifos.accounts.business.AccountPaymentEntity; import org.mifos.accounts.financial.business.FinancialActionTypeEntity; import org.mifos.accounts.financial.exceptions.FinancialException; import org.mifos.accounts.financial.util.helpers.FinancialActionConstants; import org.mifos.accounts.financial.util.helpers.FinancialConstants; import org.mifos.accounts.savings.business.SavingsBO; import org.mifos.accounts.savings.business.SavingsTrxnDetailEntity; import org.mifos.accounts.savings.util.helpers.SavingsHelper; /** * Create accounting entries for an adjustment to a deposit or withdrawal on a savings account. * <p> * Additional dependencies and collaborations: * <ul> * <li><code>BaseFinancialActivity</code> (parameter) -- knows the * <code>SavingsTrxnDetailEntity</code> instance for the activity. * <li><code>SavingsTrxnDetailEntity</code> instance knows * <ul> * <li>the <code>SavingsBO</code> instance * <li>the deposit or withdrawal amount of the adjustment * </ul> * <li><code>SavingsBO</code> instance knows * <ul> * <li>its last payment (the one to be adjusted) (<code>AccountPaymentEntity</code>) * <li>whether it is a mandatory or voluntary account. * <li>its associated <code>SavingsOfferingBO</code> instance * </ul> * <li>the <code>SavingsOfferingBO</code> knows its deposit and withdrawal GL codes. * <li><code>SavingsHelper</code> instance knows the payment action type (deposit or withdrawal) of the payment. * <li><code> * </ul> * * <h3>Post-conditions</h3> * <p> * Creates two <code>FinancialTransactionBO</code> and adds them to the financialActivity. These values * are set for both transactions: * <table border=1 cellspacing=0 cellpadding=5> * <tr><td>*accountTrxn </td><td>financialActivity.getAccountTrxn()c * <tr><td>*relatedFinancialTrxn</td><td>null</td></tr> * <tr><td>*actionDate </td><td>financialActivity.getAccountTrxn().getActionDate()</td></tr> * <tr><td>vpostedDate </td><td> is unspecified</td></tr> * <tr><td>*postedBy </td><td>financialActivity.getAccountTrxn().getPersonnel()</td></tr> * <tr><td>*accountingUpdated </td><td>(short) 1</td></tr> * <tr><td>balanceAmount </td><td>is unspecified</td></tr> * <tr><td>*notes </td><td>financialActivity.getAccountTrxn().getComments()</td></tr> * </table> * <p> * If the adjustment is to a savings withdrawal, these two transactions are created with these * additional field values: * * <ul> * <li>a FinancialTransactionBO debiting the savings account where: * * <p> * <table border=1 cellspacing=0 cellpadding=5 vspace=10> * <tr><td>postedAmount </td><td> <code>savingsTrxn.getWithdrawlAmount()</code>, adjusted for sign per specs<br/> * (see <code>BaseAccountingEntry.getAmountToPost()</code></td></tr> * <tr><td>financialAction </td><td> the FinancialActionBO corresponding to one of<br/> * FinancialActionConstants.MANDATORYWITHDRAWAL_ADJUSTMENT * <br/>or FinancialActionConstants.VOLUNTARYWITHDRAWAL_ADJUSTMENT * <br/>depending on the type of savings account.</td></tr> * <tr><td>glCode </td><td> savings.getSavingsOffering().getDepositGLCode()</td></tr> * <tr><td>postedAmount </td><td> SavingsTrxnDetailEntity.withdrawalAmount</td></tr> * <tr><td>debitCreditFlag </td><td> FinancialConstants.DEBIT</td></tr> * </table> * * <p> * <li>a financialTransactionBO crediting a savings or deposit liability account: * <p> * <table border=1 cellspacing=0 cellpadding=5 vspace=10> * <tr><td> postedAmount </td><td> <code>savingsTrxn.getWithdrawlAmount()</code>, adjusted for sign per specs <br/> * (see <code>BaseAccountingEntry.getAmountToPost()</code></td></tr> * <tr><td> financialAction </td><td> the FinancialActionBO corresponding to one o <br/> * FinancialActionConstants.MANDATORYWITHDRAWAL_ADJUSTMENT <br/> * or FinancialActionConstants.VOLUNTARYWITHDRAWAL_ADJUSTMENT <br/> * depending on the type of savings account.</td><tr> * <tr><td> glCode </td><td> **the GLCodeEntity of the GL account to debit for the above financial action</td><tr> * <tr><td> postedAmount </td><td> SavingsTrxnDetailEntity.withdrawalAmount</td><tr> * <tr><td> debitCreditFlag </td><td> FinancialConstants.CREDIT</td><tr> * </table> * </ul> * * <p> * If the adjustment is to a savings deposit, these two transactions are created with these * additional field values: * <ul> * <li>a FinancialTransactionBO debiting the savings account where: * <p> * <table border=1 cellspacing=0 cellpadding=5 vspace=10> * <tr><td> postedAmount </td><td> <code>savingsTrxn.getDepositAmount()</code>, adjusted for sign per specs <br/> * (see <code>BaseAccountingEntry.getAmountToPost()</code> </td><tr> * <tr><td> financialAction </td><td> the FinancialActionBO corresponding to one o <br/> * FinancialActionConstants.MANDATORYDEPOSIT_ADJUSTMENT <br/> * or FinancialActionConstants.VOLUNTARYDEPOSIT_ADJUSTMENT <br/> * depending on the type of savings account.</td><tr> * <tr><td> glCode </td><td> savings.getSavingsOffering().getDepositGLCode()</td><tr> * <tr><td> debitCreditFlag </td><td> FinancialConstants.DEBIT</td><tr> * </table> * <p> * <li>a financialTransactionBO crediting a savings or deposit liability account: * <p> * <table border=1 cellspacing=0 cellpadding=5 vspace=10> * <tr><td> postedAmount </td><td> <code>savingsTrxn.getDepositAmount()</code>, adjusted for sign per specs <br/> * (see <code>BaseAccountingEntry.getAmountToPost()</code></td><tr> * <tr><td> financialAction </td><td> the FinancialActionBO corresponding to one <br/> * FinancialActionConstants.MANDATORYDEPOSIT_ADJUSTMENT<br/> * or FinancialActionConstants.VOLUNTARYDEPOSIT_ADJUSTMENT<br/> * depending on the type of savings account.</td><tr> * <tr><td> glCode </td><td> **the GLCodeEntity of the GL account to credit for the above financial action</td><tr> * <tr><td> debitCreditFlag </td><td> FinancialConstants.CREDIT</td><tr> * </table> * </ul> * <p> * Notes: * <dl> * <dd>*Set by the superclass * <dd>**In most cases, the GL code mapped to by <code>FinancialRules</code> configuration. However, if the financial * action maps to a GL code that is not at the lowest level of hierarchy in the chart of accounts, the result * is a GL code chosen randomly among the lowest level descendants of the mapped GL code. * </dl> * * */ public class SavingsAdjustmentAccountingEntry extends BaseAccountingEntry { private SavingsHelper savingsHelper = new SavingsHelper(); //use fresh instance when not being injected @Override protected void applySpecificAccountActionEntry() throws FinancialException { SavingsTrxnDetailEntity savingsTrxn = (SavingsTrxnDetailEntity) financialActivity.getAccountTrxn(); SavingsBO savings = (SavingsBO) savingsTrxn.getAccount(); if (isAdjustmentForWithdrawal(savings)) { adjustWithdrawal(savings, savingsTrxn); } else { adjustDeposit(savings, savingsTrxn); } } /** * Added so that a mocked SavingsHelper can be injected by a unit test */ public SavingsHelper getSavingsHelper() { return savingsHelper; } public void setSavingsHelper(SavingsHelper helper) { this.savingsHelper = helper; } protected boolean isAdjustmentForWithdrawal(SavingsBO savings) { AccountPaymentEntity payment = savings.findMostRecentPaymentByPaymentDate(); boolean isWithdrawal = false; if (payment != null) { isWithdrawal = payment.isSavingsWithdrawal(); } return isWithdrawal; } private void adjustWithdrawal(SavingsBO savings, SavingsTrxnDetailEntity savingsTrxn) throws FinancialException { FinancialActionTypeEntity finActionWithrawal = null; if (savings.isMandatory()) { finActionWithrawal = getFinancialAction(FinancialActionConstants.MANDATORYWITHDRAWAL_ADJUSTMENT); } else if (savings.isVoluntary()) { finActionWithrawal = getFinancialAction(FinancialActionConstants.VOLUNTARYWITHDRAWAL_ADJUSTMENT); } addAccountEntryDetails(savingsTrxn.getWithdrawlAmount(), finActionWithrawal, savings .getSavingsOffering().getDepositGLCode(), FinancialConstants.CREDIT); addAccountEntryDetails(savingsTrxn.getWithdrawlAmount(), finActionWithrawal, getGLcode(finActionWithrawal.getApplicableDebitCharts()), FinancialConstants.DEBIT); } private void adjustDeposit(SavingsBO savings, SavingsTrxnDetailEntity savingsTrxn) throws FinancialException { FinancialActionTypeEntity finActionDeposit = null; if (savings.isMandatory()) { finActionDeposit = getFinancialAction(FinancialActionConstants.MANDATORYDEPOSIT_ADJUSTMENT); } else if (savings.isVoluntary()) { finActionDeposit = getFinancialAction(FinancialActionConstants.VOLUNTARYDEPOSIT_ADJUSTMENT); } addAccountEntryDetails(savingsTrxn.getDepositAmount(), finActionDeposit, getGLcode(finActionDeposit .getApplicableCreditCharts()), FinancialConstants.CREDIT); addAccountEntryDetails(savingsTrxn.getDepositAmount(), finActionDeposit, savings .getSavingsOffering().getDepositGLCode(), FinancialConstants.DEBIT); } }