diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java index 7c979b510..1226e081d 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java @@ -1,19 +1,28 @@ package org.mifosplatform.integrationtests; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; import java.util.HashMap; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mifosplatform.integrationtests.common.ClientHelper; +import org.mifosplatform.integrationtests.common.CommonConstants; import org.mifosplatform.integrationtests.common.Utils; import org.mifosplatform.integrationtests.common.accounting.Account; import org.mifosplatform.integrationtests.common.accounting.AccountHelper; import org.mifosplatform.integrationtests.common.accounting.JournalEntry; import org.mifosplatform.integrationtests.common.accounting.JournalEntryHelper; +import org.mifosplatform.integrationtests.common.charges.ChargesHelper; import org.mifosplatform.integrationtests.common.loans.LoanApplicationTestBuilder; import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder; import org.mifosplatform.integrationtests.common.loans.LoanStatusChecker; import org.mifosplatform.integrationtests.common.loans.LoanTransactionHelper; +import org.mifosplatform.integrationtests.common.savings.SavingsAccountHelper; +import org.mifosplatform.integrationtests.common.savings.SavingsProductHelper; +import org.mifosplatform.integrationtests.common.savings.SavingsStatusChecker; import com.jayway.restassured.builder.RequestSpecBuilder; import com.jayway.restassured.builder.ResponseSpecBuilder; @@ -21,7 +30,7 @@ import com.jayway.restassured.http.ContentType; import com.jayway.restassured.specification.RequestSpecification; import com.jayway.restassured.specification.ResponseSpecification; -@SuppressWarnings("rawtypes") +@SuppressWarnings({ "rawtypes", "unchecked" }) public class AccountingScenarioIntegrationTest { private RequestSpecification requestSpec; @@ -35,8 +44,19 @@ public class AccountingScenarioIntegrationTest { private final String LP_INTEREST_RATE = "1"; private final String EXPECTED_DISBURSAL_DATE = "04 March 2011"; private final String LOAN_APPLICATION_SUBMISSION_DATE = "3 March 2011"; + private final String TRANSACTION_DATE = "10 January 2013"; private final String LOAN_TERM_FREQUENCY = "10"; private final String INDIVIDUAL_LOAN = "individual"; + public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL"; + public static final String MINIMUM_OPENING_BALANCE = "1000.0"; + public static final String DEPOSIT_AMOUNT = "7000"; + public static final String WITHDRAWAL_AMOUNT = "3000"; + public static final String WITHDRAWAL_AMOUNT_ADJUSTED = "2000"; + + Float SP_BALANCE = new Float(MINIMUM_OPENING_BALANCE); + Float SP_DEPOSIT_AMOUNT = new Float(DEPOSIT_AMOUNT); + Float SP_WITHDRAWAL_AMOUNT = new Float(WITHDRAWAL_AMOUNT); + Float SP_WITHDRAWAL_AMOUNT_ADJUSTED = new Float(WITHDRAWAL_AMOUNT_ADJUSTED); private final String REPAYMENT_DATE[] = { "", "04 May 2011", "04 July 2011", "04 September 2011", "04 November 2011", "04 January 2012" }; private final Float REPAYMENT_AMOUNT[] = { .0f, 2200.0f, 3000.0f, 900.0f, 2000.0f, 2500.0f }; @@ -45,6 +65,7 @@ public class AccountingScenarioIntegrationTest { private LoanTransactionHelper loanTransactionHelper; private AccountHelper accountHelper; private JournalEntryHelper journalEntryHelper; + private SavingsAccountHelper savingsAccountHelper; @Before public void setup() { @@ -180,4 +201,113 @@ public class AccountingScenarioIntegrationTest { .withLoanType(this.INDIVIDUAL_LOAN).build(clientID.toString(), loanProductID.toString()); return this.loanTransactionHelper.getLoanId(loanApplicationJSON); } + + @Test + public void checkAccountingWithSavingsFlow() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account liabilityAccount = this.accountHelper.createLiabilityAccount(); + + final Integer savingsProductID = createSavingsProduct(MINIMUM_OPENING_BALANCE, assetAccount, incomeAccount, expenseAccount, + liabilityAccount); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, this.DATE_OF_JOINING); + final Integer savingsID = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsID); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsID); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsID); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + // Checking initial Account entries. + final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(this.SP_BALANCE, JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] liablilityAccountInitialEntry = { new JournalEntry(this.SP_BALANCE, + JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.TRANSACTION_DATE, assetAccountInitialEntry); + this.journalEntryHelper + .checkJournalEntryForLiabilityAccount(liabilityAccount, this.TRANSACTION_DATE, liablilityAccountInitialEntry); + + // First Transaction-Deposit + this.savingsAccountHelper.depositToSavingsAccount(savingsID, DEPOSIT_AMOUNT, SavingsAccountHelper.TRANSACTION_DATE, + CommonConstants.RESPONSE_RESOURCE_ID); + Float balance = SP_BALANCE + SP_DEPOSIT_AMOUNT; + HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsID); + assertEquals("Verifying Balance after Deposit", balance, summary.get("accountBalance")); + + System.out.println("----------------------Verifying Journal Entry after the Transaction Deposit----------------------------"); + final JournalEntry[] assetAccountFirstTransactionEntry = { new JournalEntry(this.SP_DEPOSIT_AMOUNT, + JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] liabililityAccountFirstTransactionEntry = { new JournalEntry(this.SP_DEPOSIT_AMOUNT, + JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.TRANSACTION_DATE, assetAccountFirstTransactionEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, this.TRANSACTION_DATE, + liabililityAccountFirstTransactionEntry); + + // Second Transaction-Withdrawal + this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsID, WITHDRAWAL_AMOUNT, SavingsAccountHelper.TRANSACTION_DATE, + CommonConstants.RESPONSE_RESOURCE_ID); + balance -= SP_WITHDRAWAL_AMOUNT; + summary = this.savingsAccountHelper.getSavingsSummary(savingsID); + assertEquals("Verifying Balance after Withdrawal", balance, summary.get("accountBalance")); + + System.out.println("-------------------Verifying Journal Entry after the Transaction Withdrawal----------------------"); + final JournalEntry[] assetAccountSecondTransactionEntry = { new JournalEntry(this.SP_WITHDRAWAL_AMOUNT, + JournalEntry.TransactionType.CREDIT) }; + final JournalEntry[] liabililityAccountSecondTransactionEntry = { new JournalEntry(this.SP_WITHDRAWAL_AMOUNT, + JournalEntry.TransactionType.DEBIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.TRANSACTION_DATE, assetAccountSecondTransactionEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, this.TRANSACTION_DATE, + liabililityAccountSecondTransactionEntry); + + // Third Transaction-Add Charges for Withdrawal Fee + final Integer withdrawalChargeId = ChargesHelper.createCharges(this.requestSpec, this.responseSpec, + ChargesHelper.getSavingsWithdrawalFeeJSON()); + Assert.assertNotNull(withdrawalChargeId); + + this.savingsAccountHelper.addChargesForSavings(savingsID, withdrawalChargeId); + ArrayList chargesPendingState = this.savingsAccountHelper.getSavingsCharges(savingsID); + Assert.assertEquals(1, chargesPendingState.size()); + HashMap savingsChargeForPay = chargesPendingState.get(0); + HashMap paidCharge = this.savingsAccountHelper.getSavingsCharge(savingsID, (Integer) savingsChargeForPay.get("id")); + Float chargeAmount = (Float) paidCharge.get("amount"); + + // assertEquals(savingsChargeForPay.get("amount"), + // paidCharge.get("amountPaid")); + + // Withdrawal after adding Charge of type Withdrawal Fee + this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsID, WITHDRAWAL_AMOUNT_ADJUSTED, + SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); + summary = this.savingsAccountHelper.getSavingsSummary(savingsID); + balance = balance - SP_WITHDRAWAL_AMOUNT_ADJUSTED - chargeAmount; + + final JournalEntry[] liabililityAccountThirdTransactionEntry = { + new JournalEntry(chargeAmount, JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.SP_WITHDRAWAL_AMOUNT_ADJUSTED, JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] assetAccountThirdTransactionEntry = { new JournalEntry(this.SP_WITHDRAWAL_AMOUNT_ADJUSTED, + JournalEntry.TransactionType.CREDIT) }; + final JournalEntry[] incomeAccountThirdTransactionEntry = { new JournalEntry(chargeAmount, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.TRANSACTION_DATE, assetAccountThirdTransactionEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, this.TRANSACTION_DATE, + liabililityAccountThirdTransactionEntry); + this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, this.TRANSACTION_DATE, incomeAccountThirdTransactionEntry); + + // Verifying Balance after applying Charge for Withdrawal Fee + assertEquals("Verifying Balance", balance, summary.get("accountBalance")); + } + + private Integer createSavingsProduct(final String minOpenningBalance, final Account... accounts) { + System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); + final String savingsProductJSON = new SavingsProductHelper().withInterestCompoundingPeriodTypeAsDaily() // + .withInterestPostingPeriodTypeAsQuarterly() // + .withInterestCalculationPeriodTypeAsDailyBalance() // + .withMinimumOpenningBalance(minOpenningBalance).withAccountingRuleAsCashBased(accounts).build(); + return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec); + } } diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java index fd7b88073..ea146b825 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java @@ -22,7 +22,7 @@ public class JournalEntryHelper { this.responseSpec = responseSpec; } - public void checkJournalEntryForExpenseAccount(final Account expenseAccount, final String date, final JournalEntry accountEntries) { + public void checkJournalEntryForExpenseAccount(final Account expenseAccount, final String date, final JournalEntry... accountEntries) { checkJournalEntry(expenseAccount, date, accountEntries); } @@ -30,9 +30,13 @@ public class JournalEntryHelper { checkJournalEntry(assetAccount, date, accountEntries); } - public void checkJournalEntryForIncomeAccount(final Account incomeAccount, final String date, final JournalEntry accountEntries) { + public void checkJournalEntryForIncomeAccount(final Account incomeAccount, final String date, final JournalEntry... accountEntries) { checkJournalEntry(incomeAccount, date, accountEntries); } + + public void checkJournalEntryForLiabilityAccount(final Account liabilityAccount, final String date, final JournalEntry... accountEntries) { + checkJournalEntry(liabilityAccount, date, accountEntries); + } private String getEntryValueFromJournalEntry(final ArrayList entryResponse, final int entryNumber) { final HashMap map = (HashMap) entryResponse.get(entryNumber).get("entryType"); diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java index 00cdf9a9e..d6eb80d6b 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/savings/SavingsProductHelper.java @@ -47,12 +47,15 @@ public class SavingsProductHelper { private String interestCalculationType = INTEREST_CALCULATION_USING_DAILY_BALANCE; private String nominalAnnualInterestRate = "10.0"; private String accountingRule = NONE; - private String savingsReferenceAccountId = "1"; - private String transfersInSuspenseAccountId = "4"; - private String savingsControlAccountId = "4"; - private String interestOnSavingsAccountId = "3"; - private String incomeFromFeeAccountId = "2"; - private String incomeFromPenaltyAccountId = "2"; + private String savingsReferenceAccountId = null; + private String transfersInSuspenseAccountId = null; + private String savingsControlAccountId = null; + private String interestOnSavingsAccountId = null; + private String incomeFromFeeAccountId = null; + private String incomeFromPenaltyAccountId = null; + private String overdraftPortfolioControlId = null; + private String incomeFromInterestId = null; + private String writeOffAccountId = null; private String minRequiredOpeningBalance = null; private String lockinPeriodFrequency = "0"; private String withdrawalFeeForTransfers = "true"; @@ -83,15 +86,16 @@ public class SavingsProductHelper { map.put("interestOnSavingsAccountId", this.interestOnSavingsAccountId); map.put("incomeFromFeeAccountId", this.incomeFromFeeAccountId); map.put("incomeFromPenaltyAccountId", this.incomeFromPenaltyAccountId); + map.put("overdraftPortfolioControlId", this.overdraftPortfolioControlId); + map.put("incomeFromInterestId", this.incomeFromInterestId); + map.put("writeOffAccountId", this.writeOffAccountId); map.put("minRequiredOpeningBalance", this.minRequiredOpeningBalance); map.put("lockinPeriodFrequency", this.lockinPeriodFrequency); map.put("lockinPeriodFrequencyType", this.lockingPeriodFrequencyType); map.put("withdrawalFeeForTransfers", this.withdrawalFeeForTransfers); if (this.accountingRule.equals(CASH_BASED)) { - Account[] account_list = { new Account(1, AccountType.ASSET) }; - withAccountingRuleAsCashBased(account_list); - map.putAll(getAccountMappingForCashBased(account_list)); + map.putAll(getAccountMappingForCashBased()); } String savingsProductCreateJson = new Gson().toJson(map); System.out.println(savingsProductCreateJson); @@ -154,13 +158,14 @@ public class SavingsProductHelper { return this; } - private Map getAccountMappingForCashBased(final Account[] accountList) { + private Map getAccountMappingForCashBased() { final Map map = new HashMap(); if (accountList != null) { for (int i = 0; i < this.accountList.length; i++) { if (this.accountList[i].getAccountType().equals(Account.AccountType.ASSET)) { final String ID = this.accountList[i].getAccountID().toString(); map.put("savingsReferenceAccountId", ID); + map.put("overdraftPortfolioControlId", ID); } if (this.accountList[i].getAccountType().equals(Account.AccountType.LIABILITY)) { final String ID = this.accountList[i].getAccountID().toString(); @@ -170,11 +175,13 @@ public class SavingsProductHelper { if (this.accountList[i].getAccountType().equals(Account.AccountType.EXPENSE)) { final String ID = this.accountList[i].getAccountID().toString(); map.put("interestOnSavingsAccountId", ID); + map.put("writeOffAccountId", ID); } if (this.accountList[i].getAccountType().equals(Account.AccountType.INCOME)) { final String ID = this.accountList[i].getAccountID().toString(); map.put("incomeFromFeeAccountId", ID); map.put("incomeFromPenaltyAccountId", ID); + map.put("incomeFromInterestId", ID); } } }