/* * 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.persistence; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import junit.framework.Assert; import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLUnit; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.junit.Test; import org.mifos.accounts.AccountIntegrationTestCase; import org.mifos.accounts.business.AccountActionDateEntity; import org.mifos.accounts.business.AccountActionEntity; import org.mifos.accounts.business.AccountBO; import org.mifos.accounts.business.AccountPaymentEntity; import org.mifos.accounts.financial.business.COABO; import org.mifos.accounts.financial.business.COAHierarchyEntity; import org.mifos.accounts.financial.business.GLCategoryType; import org.mifos.accounts.loan.business.LoanScheduleEntity; import org.mifos.accounts.productdefinition.business.SavingsOfferingBO; import org.mifos.accounts.productdefinition.util.helpers.ApplicableTo; import org.mifos.accounts.productdefinition.util.helpers.InterestCalcType; import org.mifos.accounts.productdefinition.util.helpers.PrdStatus; import org.mifos.accounts.productdefinition.util.helpers.RecommendedAmountUnit; import org.mifos.accounts.productdefinition.util.helpers.SavingsType; import org.mifos.accounts.savings.business.SavingsBO; import org.mifos.accounts.savings.business.SavingsScheduleEntity; import org.mifos.accounts.savings.persistence.GenericDao; import org.mifos.accounts.savings.persistence.GenericDaoHibernate; import org.mifos.accounts.savings.util.helpers.SavingsTestHelper; import org.mifos.accounts.util.helpers.AccountActionTypes; import org.mifos.accounts.util.helpers.AccountState; import org.mifos.application.holiday.business.HolidayBO; import org.mifos.application.holiday.persistence.HolidayDao; import org.mifos.application.holiday.persistence.HolidayDaoHibernate; import org.mifos.application.master.business.PaymentTypeEntity; import org.mifos.application.master.persistence.LegacyMasterDao; import org.mifos.application.meeting.business.MeetingBO; import org.mifos.application.meeting.util.helpers.MeetingType; import org.mifos.application.meeting.util.helpers.RecurrenceType; import org.mifos.application.servicefacade.TestCollectionSheetRetrieveSavingsAccountsUtils; import org.mifos.customers.business.CustomerScheduleEntity; import org.mifos.customers.office.business.OfficeBO; import org.mifos.customers.office.persistence.OfficeDao; import org.mifos.customers.office.persistence.OfficeDaoHibernate; import org.mifos.customers.office.persistence.OfficePersistence; import org.mifos.domain.builders.HolidayBuilder; import org.mifos.framework.TestUtils; import org.mifos.framework.exceptions.PersistenceException; import org.mifos.framework.hibernate.helper.QueryResult; import org.mifos.framework.hibernate.helper.StaticHibernateUtil; import org.mifos.framework.util.DateTimeService; import org.mifos.framework.util.helpers.TestGeneralLedgerCode; import org.mifos.framework.util.helpers.TestObjectFactory; import org.springframework.beans.factory.annotation.Autowired; public class LegacyAccountDaoIntegrationTest extends AccountIntegrationTestCase { @Autowired LegacyMasterDao legacyMasterDao; @Autowired private LegacyAccountDao legacyAccountDao; public static final int LOAN_CUSTOMFIELDS_NUMBER = 1; private static final String ASSETS_GL_ACCOUNT_CODE = "10000"; private static final String DIRECT_EXPENDITURE_GL_ACCOUNT_CODE = "41000"; @Test public void testAddDuplicateGlAccounts() { String name = "New Account Name"; String name2 = "New Account Name 2"; String glCode = "999999"; String parentGlCode = ASSETS_GL_ACCOUNT_CODE; try { legacyAccountDao.addGeneralLedgerAccount(name, glCode, parentGlCode, null); legacyAccountDao.addGeneralLedgerAccount(name2, glCode, parentGlCode, null); Assert.fail(); } catch (Exception e) { Assert.assertTrue(e.getMessage().contains("An account already exists with glcode")); } } @Test public void testAddGlAccount() { String name = "New Account Name"; String glCode = "999999"; String parentGlCode = ASSETS_GL_ACCOUNT_CODE; COABO coa = legacyAccountDao.addGeneralLedgerAccount(name, glCode, parentGlCode, null); Assert.assertEquals(coa.getAccountId(), legacyAccountDao.getAccountIdFromGlCode(glCode)); } /** * The Chart of Accounts hierarchy is created when TestCaseInitializer is instantiated in parent class static * initializer. Verify it worked as planned. */ @Test public void testAddCoaHierarchy() { short id = TestGeneralLedgerCode.COST_OF_FUNDS; COAHierarchyEntity h = (COAHierarchyEntity) StaticHibernateUtil.getSessionTL().load(COAHierarchyEntity.class, id); Assert.assertEquals(DIRECT_EXPENDITURE_GL_ACCOUNT_CODE, h.getParentAccount().getCoa().getAssociatedGlcode() .getGlcode()); } /** * The top-level "ASSETS" general ledger account should always be the first one inserted. This will hopefully be * reliable enough for testing purposes. */ @Test public void testGetAccountIdForGLCode() { Assert.assertEquals(new Short((short) 1), TestGeneralLedgerCode.ASSETS); } @Test public void testTopLevelAccountPersisted() throws Exception { COABO incomeCategory = legacyAccountDao.getCategory(GLCategoryType.INCOME); Assert.assertEquals(GLCategoryType.INCOME, incomeCategory.getCategoryType()); } @Test public void testDumpChartOfAccounts() throws Exception { String expected_chart = "<configuration>" + " <ChartOfAccounts>" + " <GLAssetsAccount code=\"10000\" name=\"ASSETS\">" + " <GLAccount code=\"11000\" name=\"Cash and bank balances\">" + " <GLAccount code=\"11100\" name=\"Petty Cash Accounts\">" + " <GLAccount code=\"11101\" name=\"Cash 1\"/>" + " <GLAccount code=\"11102\" name=\"Cash 2\"/>" + " </GLAccount>" + " <GLAccount code=\"11200\" name=\"Bank Balances\">" + " <GLAccount code=\"11201\" name=\"Bank Account 1\"/>" + " <GLAccount code=\"11202\" name=\"Bank Account 2\"/>" + " </GLAccount>" + " <GLAccount code=\"11300\" name=\"Transfers\">" + " <GLAccount code=\"11301\" name=\"Inter Office Transfers\"/>" + " </GLAccount>" + " </GLAccount>" + " <GLAccount code=\"13000\" name=\"Loan Portfolio\">" + " <GLAccount code=\"13100\" name=\"Loans and Advances\">" + " <GLAccount code=\"13101\" name=\"Loans to clients\"/>" + " <GLAccount code=\"1501\" name=\"IGLoan\"/>" + " <GLAccount code=\"1502\" name=\"ManagedICICI-IGLoan\"/>" + " <GLAccount code=\"1503\" name=\"SPLoan\"/>" + " <GLAccount code=\"1504\" name=\"ManagedICICI-SPLoan\"/>" + " <GLAccount code=\"1505\" name=\"WFLoan\"/>" + " <GLAccount code=\"1506\" name=\"Managed WFLoan\"/>" + " <GLAccount code=\"1507\" name=\"Emergency Loans\"/>" + " <GLAccount code=\"1508\" name=\"Special Loans\"/>" + " <GLAccount code=\"1509\" name=\"Micro Enterprises Loans\"/>" + " </GLAccount>" + " <GLAccount code=\"13200\" name=\"Loan Loss Provisions\">" + " <GLAccount code=\"13201\" name=\"Write-offs\"/>" + " </GLAccount>" + " </GLAccount>" + " </GLAssetsAccount>" + " <GLLiabilitiesAccount code=\"20000\" name=\"LIABILITIES\">" + " <GLAccount code=\"22000\" name=\"Interest Payable\">" + " <GLAccount code=\"22100\" name=\"Interest payable on clients savings\">" + " <GLAccount code=\"22101\" name=\"Interest on mandatory savings\"/>" + " </GLAccount>" + " </GLAccount>" + " <GLAccount code=\"23000\" name=\"Clients Deposits\">" + " <GLAccount code=\"23100\" name=\"Clients Deposits\">" + " <GLAccount code=\"23101\" name=\"Savings accounts\"/>" + " <GLAccount code=\"4601\" name=\"Emergency Fund\"/>" + " <GLAccount code=\"4602\" name=\"Margin Money-1\"/>" + " <GLAccount code=\"4603\" name=\"Margin Money-2\"/>" + " <GLAccount code=\"4606\" name=\"Village Development Fund\"/>" + " </GLAccount>" + " </GLAccount>" + " <GLAccount code=\"24000\" name=\"Mandatory Savings\">" + " <GLAccount code=\"24100\" name=\"Mandatory Savings\">" + " <GLAccount code=\"24101\" name=\"Mandatory Savings Accounts\"/>" + " </GLAccount>" + " </GLAccount>" + " </GLLiabilitiesAccount>" + " <GLIncomeAccount code=\"30000\" name=\"INCOME\">" + " <GLAccount code=\"31000\" name=\"Direct Income\">" + " <GLAccount code=\"31100\" name=\"Interest income from loans\">" + " <GLAccount code=\"31101\" name=\"Interest on loans\"/>" + " <GLAccount code=\"31102\" name=\"Penalty\"/>" + " <GLAccount code=\"5001\" name=\"Interest\"/>" + " </GLAccount>" + " <GLAccount code=\"31300\" name=\"Income from micro credit & lending activities\">" + " <GLAccount code=\"31301\" name=\"Fees\"/>" + " <GLAccount code=\"5201\" name=\"Processing Fees\"/>" + " <GLAccount code=\"5202\" name=\"Annual Subscription Fee\"/>" + " <GLAccount code=\"5203\" name=\"Emergency Loan Documentation Fee\"/>" + " <GLAccount code=\"5204\" name=\"Sale of Publication\"/>" + " <GLAccount code=\"5205\" name=\"Fines & Penalties\"/>" + " <GLAccount code=\"6201\" name=\"Miscelleneous Income\"/>" + " </GLAccount>" + " </GLAccount>" + " <GLAccount code=\"31401\" name=\"Income from 999 Account\"/>" + " </GLIncomeAccount>" + " <GLExpenditureAccount code=\"40000\" name=\"EXPENDITURE\">" + " <GLAccount code=\"41000\" name=\"Direct Expenditure\">" + " <GLAccount code=\"41100\" name=\"Cost of Funds\">" + " <GLAccount code=\"41101\" name=\"Interest on clients voluntary savings\"/>" + " <GLAccount code=\"41102\" name=\"Interest on clients mandatory savings\"/>" + " </GLAccount>" + " </GLAccount>" + " </GLExpenditureAccount>" + " </ChartOfAccounts>" + "</configuration>"; String chart = legacyAccountDao.dumpChartOfAccounts(); // save old values so they can be restored when we clean up before // leaving this test method boolean ignoreWhitespace = XMLUnit.getIgnoreWhitespace(); XMLUnit.setIgnoreWhitespace(true); XMLAssert.assertXMLEqual(expected_chart, chart); XMLUnit.setIgnoreWhitespace(ignoreWhitespace); } @Test public void testSuccessGetNextInstallmentList() { List<AccountActionDateEntity> installmentIdList = groupLoan.getApplicableIdsForFutureInstallments(); Assert.assertEquals(5, installmentIdList.size()); } @Test public void testSuccessLoadBusinessObject() throws Exception { AccountBO readAccount = legacyAccountDao.getAccount(groupLoan.getAccountId()); Assert.assertEquals(AccountState.LOAN_ACTIVE_IN_GOOD_STANDING, readAccount.getState()); } @Test public void testFailureLoadBusinessObject() { try { legacyAccountDao.getAccount(null); Assert.fail(); } catch (PersistenceException expected) { } } @Test public void testGetAccountAction() throws Exception { AccountActionEntity accountAction = legacyMasterDao.getPersistentObject( AccountActionEntity.class, AccountActionTypes.SAVINGS_INTEREST_POSTING.getValue()); Assert.assertNotNull(accountAction); } @Test public void testOptionalAccountStates() throws Exception { Assert.assertEquals(1, legacyAccountDao.getAccountStates(Short.valueOf("0")).size()); } @Test public void testAccountStatesInUse() throws Exception { Assert.assertEquals(17, legacyAccountDao.getAccountStates(Short.valueOf("1")).size()); } @Test public void testSearchAccount() throws Exception { savingsBO = createSavingsAccount(); QueryResult queryResult = null; queryResult = legacyAccountDao.search(savingsBO.getGlobalAccountNum(), (short) 3); Assert.assertNotNull(queryResult); Assert.assertEquals(1, queryResult.getSize()); Assert.assertEquals(1, queryResult.get(0, 10).size()); } @Test public void testSearchCustomerAccount() throws Exception { QueryResult queryResult = null; queryResult = legacyAccountDao.search(center.getCustomerAccount().getGlobalAccountNum(), (short) 3); Assert.assertNull(queryResult); } @Test public void testGetListOfAccountIdsHavingLoanSchedulesWithinAHoliday() throws Exception { Set<HolidayBO> holidays; DateTime fromDate = new DateMidnight().toDateTime().plusDays(1); DateTime thruDate = new DateMidnight().toDateTime().plusDays(30); GenericDao genericDao = new GenericDaoHibernate(); OfficeDao officeDao = new OfficeDaoHibernate(genericDao); HolidayDao holidayDao = new HolidayDaoHibernate(genericDao); OfficeBO sampleBranch = officeDao.findOfficeById(this.getBranchOffice().getOfficeId()); holidays = new HashSet<HolidayBO>(); holiday = new HolidayBuilder().withName("Welcome Holiday").from(fromDate).to(thruDate).build(); holidayDao.save(holiday); holidays.add((HolidayBO) holiday); sampleBranch.setHolidays(holidays); new OfficePersistence().createOrUpdate(sampleBranch); StaticHibernateUtil.flushSession(); List<Object[]> AccountIds = legacyAccountDao.getListOfAccountIdsHavingLoanSchedulesWithinAHoliday( holiday); Assert.assertNotNull(AccountIds); assertThat(AccountIds.size(), is(2)); } @Test public void testGetListOfAccountIdsHavingCustomerSchedulesWithinAHoliday() throws Exception { Set<HolidayBO> holidays; DateTime fromDate = new DateMidnight().toDateTime().plusDays(1); DateTime thruDate = new DateMidnight().toDateTime().plusDays(30); GenericDao genericDao = new GenericDaoHibernate(); OfficeDao officeDao = new OfficeDaoHibernate(genericDao); HolidayDao holidayDao = new HolidayDaoHibernate(genericDao); OfficeBO sampleBranch = officeDao.findOfficeById(this.getBranchOffice().getOfficeId()); holidays = new HashSet<HolidayBO>(); holiday = new HolidayBuilder().withName("Welcome Holiday").from(fromDate).to(thruDate).build(); holidayDao.save(holiday); holidays.add((HolidayBO) holiday); sampleBranch.setHolidays(holidays); new OfficePersistence().createOrUpdate(sampleBranch); StaticHibernateUtil.flushSession(); List<Object[]> AccountIds = legacyAccountDao.getListOfAccountIdsHavingCustomerSchedulesWithinAHoliday( holiday); Assert.assertNotNull(AccountIds); assertThat(AccountIds.size(), is(3)); } @Test public void testGetLoanSchedulesForAccountThatAreWithinDates() throws Exception { DateTime fromDate = new DateMidnight().toDateTime().plusDays(1); DateTime thruDate = new DateMidnight().toDateTime().plusDays(30); List<LoanScheduleEntity> affectedDates = legacyAccountDao.getLoanSchedulesForAccountThatAreWithinDates( groupLoan.getAccountId(), fromDate, thruDate); Assert.assertNotNull(affectedDates); Assert.assertEquals(4, affectedDates.size()); } @Test public void testGetCustomerSchedulesForAccountThatAreWithinDates() throws Exception { DateTime fromDate = new DateMidnight().toDateTime().plusDays(1); DateTime thruDate = new DateMidnight().toDateTime().plusDays(23); List<CustomerScheduleEntity> affectedDates = legacyAccountDao .getCustomerSchedulesForAccountThatAreWithinDates(center.getCustomerAccount().getAccountId(), fromDate, thruDate); Assert.assertNotNull(affectedDates); Assert.assertEquals(3, affectedDates.size()); } @Test public void testGetSavingsSchedulesForAccountThatAreWithinDates() throws Exception { savingsBO = new TestCollectionSheetRetrieveSavingsAccountsUtils().createSavingsAccount(group, "clm", "3.0", false, false); DateTime fromDate = new DateMidnight().toDateTime().plusDays(1); DateTime thruDate = new DateMidnight().toDateTime().plusDays(37); List<SavingsScheduleEntity> affectedDates = legacyAccountDao.getSavingsSchedulesForAccountThatAreWithinDates( savingsBO.getAccountId(), fromDate, thruDate); Assert.assertNotNull(affectedDates); Assert.assertEquals(5, affectedDates.size()); } @Test public void testGetActiveCustomerAndSavingsAccountIdsForGenerateMeetingTaskShouldReturnNothing() throws Exception { // Superclass creates a center, a group, and a client that start meeting today // They should have 10 current or future meeting dates. Savings account should also have 10 deposit installments // so should not be retrieved. savingsBO = new SavingsTestHelper().createSavingsAccount(createSavingsOffering("qqqqq"), group, AccountState.SAVINGS_ACTIVE, TestUtils.makeUser()); List<Integer> accountIds = legacyAccountDao.getActiveCustomerAndSavingsAccountIdsForGenerateMeetingTask(); assertThat(accountIds.size(), is(0)); } @Test public void testGetActiveCustomerAndSavingsAccountIdsForGenerateMeetingTaskShouldReturnThreeCustomerAccounts() throws Exception { // Superclass creates a center, a group, and a client that start meeting today // They should have 10 current or future meeting dates // Set time ahead 7 weeks to force regenerating customer schedules. new DateTimeService().setCurrentDateTime(new DateTime().plusWeeks(7)); List<Integer> accountIds = legacyAccountDao.getActiveCustomerAndSavingsAccountIdsForGenerateMeetingTask(); assertThat(accountIds.size(), is(3)); assertThat(accountIds.contains(center.getCustomerAccount().getAccountId()), is(true)); assertThat(accountIds.contains(group.getCustomerAccount().getAccountId()), is(true)); assertThat(accountIds.contains(client.getCustomerAccount().getAccountId()), is(true)); } @Test public void testGetActiveCustomerAndSavingsAccountIdsForGenerateMeetingTaskShouldReturnThreeCustomerAccountsAndOneSavingsAccount() throws Exception { // Superclass creates a center, a group, and a client that start meeting today // They should have 10 current or future meeting dates // Set time ahead 7 weeks to force regenerating customer schedules. savingsBO = new SavingsTestHelper().createSavingsAccount(createSavingsOffering("qqqqq"), group, AccountState.SAVINGS_ACTIVE, TestUtils.makeUser()); new DateTimeService().setCurrentDateTime(new DateTime().plusWeeks(7)); List<Integer> accountIds = legacyAccountDao.getActiveCustomerAndSavingsAccountIdsForGenerateMeetingTask(); assertThat(accountIds.size(), is(4)); assertThat(accountIds.contains(center.getCustomerAccount().getAccountId()), is(true)); assertThat(accountIds.contains(group.getCustomerAccount().getAccountId()), is(true)); assertThat(accountIds.contains(client.getCustomerAccount().getAccountId()), is(true)); assertThat(accountIds.contains(savingsBO.getAccountId()), is(true)); } @Test public void testFindingAccountPaymentShouldReturnOnePayment() throws Exception { savingsBO = createSavingsAccount(); AccountPaymentEntity accountPaymentEntity = new AccountPaymentEntity(savingsBO, TestUtils.createMoney(100), "1111", new Date(System.currentTimeMillis()), new PaymentTypeEntity(Short.valueOf("1")), new Date(System.currentTimeMillis())); List<AccountPaymentEntity> payments = new ArrayList<AccountPaymentEntity>(); payments.add(accountPaymentEntity); savingsBO.setAccountPayments(payments); legacyAccountDao.createOrUpdate(savingsBO); StaticHibernateUtil.commitTransaction(); List<AccountPaymentEntity> result = legacyAccountDao.findAccountPaymentsByReceiptNumber("1111"); Assert.assertNotNull(result); Assert.assertEquals(1, result.size()); Assert.assertEquals("1111", result.get(0).getReceiptNumber()); } @Test public void testFindingAccountPaymentShouldReturnZeroPayments() throws Exception { savingsBO = createSavingsAccount(); AccountPaymentEntity accountPaymentEntity = new AccountPaymentEntity(savingsBO, TestUtils.createMoney(100), "2222", new Date(System.currentTimeMillis()), new PaymentTypeEntity(Short.valueOf("1")), new Date(System.currentTimeMillis())); List<AccountPaymentEntity> payments = new ArrayList<AccountPaymentEntity>(); payments.add(accountPaymentEntity); savingsBO.setAccountPayments(payments); legacyAccountDao.createOrUpdate(savingsBO); StaticHibernateUtil.commitTransaction(); List<AccountPaymentEntity> result = legacyAccountDao.findAccountPaymentsByReceiptNumber("1111"); Assert.assertNotNull(result); Assert.assertEquals(0, result.size()); } /** * ****************** * Helper methods * ****************** */ private SavingsBO createSavingsAccount() throws Exception { return TestObjectFactory.createSavingsAccount("12345678910", group, AccountState.SAVINGS_ACTIVE, new Date(), createSavingsOffering("qqqqq"), TestUtils.makeUser()); } private SavingsOfferingBO createSavingsOffering(String offeringName) { Date startDate = new Date(System.currentTimeMillis()); MeetingBO meetingIntCalc = TestObjectFactory.createMeeting(TestObjectFactory.getNewMeetingForToday(RecurrenceType.WEEKLY, TestObjectFactory.EVERY_WEEK, MeetingType.CUSTOMER_MEETING)); MeetingBO meetingIntPost = TestObjectFactory.createMeeting(TestObjectFactory.getNewMeetingForToday(RecurrenceType.WEEKLY, TestObjectFactory.EVERY_WEEK, MeetingType.CUSTOMER_MEETING)); return TestObjectFactory.createSavingsProduct(offeringName, ApplicableTo.GROUPS, startDate, PrdStatus.SAVINGS_ACTIVE, 300.0, RecommendedAmountUnit.PER_INDIVIDUAL, 1.2, 200.0, 200.0, SavingsType.VOLUNTARY, InterestCalcType.MINIMUM_BALANCE, meetingIntCalc, meetingIntPost); } }