/* * 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.business.service; import static org.mifos.application.meeting.util.helpers.MeetingType.CUSTOMER_MEETING; import static org.mifos.application.meeting.util.helpers.RecurrenceType.WEEKLY; import static org.mifos.framework.util.helpers.TestObjectFactory.EVERY_WEEK; import java.sql.Date; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; import junit.framework.Assert; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.mifos.accounts.business.AccountActionDateEntity; import org.mifos.accounts.business.AccountActionEntity; import org.mifos.accounts.business.AccountBO; import org.mifos.accounts.business.AccountFeesActionDetailEntity; import org.mifos.accounts.business.AccountFeesEntity; import org.mifos.accounts.business.AccountStateEntity; import org.mifos.accounts.business.AccountStateMachines; import org.mifos.accounts.business.AccountTestUtils; import org.mifos.accounts.fees.business.FeeBO; import org.mifos.accounts.fees.util.helpers.FeeCategory; import org.mifos.accounts.fees.util.helpers.FeeFormula; import org.mifos.accounts.fees.util.helpers.FeePayment; import org.mifos.accounts.fees.util.helpers.FeeStatus; import org.mifos.accounts.loan.business.LoanBOTestUtils; import org.mifos.accounts.loan.business.LoanFeeScheduleEntity; import org.mifos.accounts.loan.business.LoanScheduleEntity; import org.mifos.accounts.persistence.LegacyAccountDao; import org.mifos.accounts.productdefinition.business.LoanOfferingBO; import org.mifos.accounts.savings.business.SavingsBO; import org.mifos.accounts.util.helpers.AccountActionTypes; import org.mifos.accounts.util.helpers.AccountState; import org.mifos.accounts.util.helpers.AccountStateFlag; import org.mifos.accounts.util.helpers.AccountTypes; import org.mifos.application.meeting.business.MeetingBO; import org.mifos.application.meeting.util.helpers.RecurrenceType; import org.mifos.customers.business.CustomerAccountBO; import org.mifos.customers.business.CustomerBO; import org.mifos.customers.business.CustomerFeeScheduleEntity; import org.mifos.customers.business.CustomerScheduleEntity; import org.mifos.customers.personnel.business.PersonnelBO; import org.mifos.customers.util.helpers.CustomerStatus; import org.mifos.dto.domain.ApplicableCharge; import org.mifos.framework.MifosIntegrationTestCase; import org.mifos.framework.TestUtils; import org.mifos.framework.hibernate.helper.StaticHibernateUtil; import org.mifos.framework.util.helpers.IntegrationTestObjectMother; import org.mifos.framework.util.helpers.Money; import org.mifos.framework.util.helpers.TestObjectFactory; import org.mifos.security.util.UserContext; import org.springframework.beans.factory.annotation.Autowired; public class AccountServiceIntegrationTest extends MifosIntegrationTestCase { protected AccountBO accountBO = null; protected SavingsBO savingsBO = null; protected CustomerBO center = null; protected CustomerBO group = null; @Autowired protected LegacyAccountDao legacyAccountDao; private AccountBusinessService service; @Before public void setUp() throws Exception { service = new AccountBusinessService(); } @After public void tearDown() throws Exception { try { accountBO = null; savingsBO = null; group = null; center = null; // accountBO = null; // savingsBO = null; // group = null; // center = null; legacyAccountDao = null; } catch (Exception e) { // TODO Whoops, cleanup didnt work, reset db } } @Test public void testGetAccountAction() throws Exception { AccountBusinessService service = new AccountBusinessService(); AccountActionEntity accountaction = service.getAccountAction(AccountActionTypes.SAVINGS_DEPOSIT.getValue(), Short.valueOf("1")); Assert.assertNotNull(accountaction); } @Test public void testGetAppllicableFees() throws Exception { AccountBusinessService accountBusinessService = new AccountBusinessService(); accountBO = getLoanAccount(); StaticHibernateUtil.flushSession(); center = TestObjectFactory.getCustomer(center.getCustomerId()); group = TestObjectFactory.getCustomer(group.getCustomerId()); accountBO = TestObjectFactory.getObject(AccountBO.class, accountBO.getAccountId()); UserContext uc = TestUtils.makeUser(); List<ApplicableCharge> applicableChargeList = accountBusinessService.getAppllicableFees(accountBO .getAccountId(), uc); Assert.assertEquals(2, applicableChargeList.size()); } @Test @Ignore public void testGetAppllicableFeesForInstallmentStartingOnCurrentDate() throws Exception { AccountBusinessService accountBusinessService = new AccountBusinessService(); accountBO = getLoanAccountWithAllTypesOfFees(); StaticHibernateUtil.flushSession(); center = TestObjectFactory.getCustomer(center.getCustomerId()); group = TestObjectFactory.getCustomer(group.getCustomerId()); accountBO = TestObjectFactory.getObject(AccountBO.class, accountBO.getAccountId()); StaticHibernateUtil.flushAndClearSession(); UserContext uc = TestUtils.makeUser(); List<ApplicableCharge> applicableChargeList = accountBusinessService.getAppllicableFees(accountBO .getAccountId(), uc); Assert.assertEquals(4, applicableChargeList.size()); for (ApplicableCharge applicableCharge : applicableChargeList) { if (applicableCharge.getFeeName().equalsIgnoreCase("Upfront Fee")) { Assert.assertEquals(new Money(getCurrency(), "20.0"), new Money(getCurrency(), applicableCharge .getAmountOrRate())); Assert.assertNotNull(applicableCharge.getFormula()); Assert.assertNull(applicableCharge.getPeriodicity()); } else if (applicableCharge.getFeeName().equalsIgnoreCase("Periodic Fee")) { Assert.assertEquals(new Money(getCurrency(), "200.0"), new Money(getCurrency(), applicableCharge .getAmountOrRate())); Assert.assertNull(applicableCharge.getFormula()); Assert.assertNotNull(applicableCharge.getPeriodicity()); } else if (applicableCharge.getFeeName().equalsIgnoreCase("Misc Fee")) { Assert.assertNull(applicableCharge.getAmountOrRate()); Assert.assertNull(applicableCharge.getFormula()); Assert.assertNull(applicableCharge.getPeriodicity()); } } } @Test public void testGetAppllicableFeesForInstallmentStartingAfterCurrentDate() throws Exception { AccountBusinessService accountBusinessService = new AccountBusinessService(); accountBO = getLoanAccountWithAllTypesOfFees(); incrementInstallmentDate(accountBO, 1, Short.valueOf("1")); accountBO.setUserContext(TestObjectFactory.getContext()); PersonnelBO loggedInUser = IntegrationTestObjectMother.testUser(); accountBO.changeStatus(AccountState.LOAN_DISBURSED_TO_LOAN_OFFICER, null, "", loggedInUser); TestObjectFactory.updateObject(accountBO); StaticHibernateUtil.flushSession(); center = TestObjectFactory.getCustomer(center.getCustomerId()); group = TestObjectFactory.getCustomer(group.getCustomerId()); StaticHibernateUtil.flushAndClearSession(); accountBO = TestObjectFactory.getObject(AccountBO.class, accountBO.getAccountId()); UserContext uc = TestUtils.makeUser(); List<ApplicableCharge> applicableChargeList = accountBusinessService.getAppllicableFees(accountBO .getAccountId(), uc); Assert.assertEquals(3, applicableChargeList.size()); for (ApplicableCharge applicableCharge : applicableChargeList) { if (applicableCharge.getFeeName().equalsIgnoreCase("Periodic Fee")) { Assert.assertEquals(new Money(getCurrency(), "200.0"), new Money(getCurrency(), applicableCharge .getAmountOrRate())); Assert.assertNull(applicableCharge.getFormula()); Assert.assertNotNull(applicableCharge.getPeriodicity()); } else if (applicableCharge.getFeeName().equalsIgnoreCase("Misc Fee")) { Assert.assertNull(applicableCharge.getAmountOrRate()); Assert.assertNull(applicableCharge.getFormula()); Assert.assertNull(applicableCharge.getPeriodicity()); } } } @Test public void testGetAppllicableFeesForMeetingStartingOnCurrentDate() throws Exception { // FIXME some test leaves database table (apart from CUSTOMER and // PRD_OFFERING) in dirty state Failures are noticed on windows xp // system, the execution order differs for surefire from OS to OS. AccountBusinessService accountBusinessService = new AccountBusinessService(); CustomerAccountBO customerAccountBO = getCustomerAccountWithAllTypesOfFees(); StaticHibernateUtil.flushSession(); center = TestObjectFactory.getCustomer(center.getCustomerId()); StaticHibernateUtil.flushAndClearSession(); UserContext uc = TestUtils.makeUser(); List<ApplicableCharge> applicableChargeList = accountBusinessService.getAppllicableFees(customerAccountBO .getAccountId(), uc); Assert.assertEquals(4, applicableChargeList.size()); for (ApplicableCharge applicableCharge : applicableChargeList) { if (applicableCharge.getFeeName().equalsIgnoreCase("Upfront Fee")) { // this is a rate, so we shouldn't have a trailing ".0" Assert.assertEquals("20", applicableCharge.getAmountOrRate()); Assert.assertNotNull(applicableCharge.getFormula()); Assert.assertNull(applicableCharge.getPeriodicity()); } else if (applicableCharge.getFeeName().equalsIgnoreCase("Misc Fee")) { Assert.assertNull(applicableCharge.getAmountOrRate()); Assert.assertNull(applicableCharge.getFormula()); Assert.assertNull(applicableCharge.getPeriodicity()); } else if (applicableCharge.getFeeName().equalsIgnoreCase("Periodic Fee")) { Assert.assertEquals(new Money(getCurrency(), "200.0"), new Money(getCurrency(), applicableCharge .getAmountOrRate())); Assert.assertNull(applicableCharge.getFormula()); Assert.assertNotNull(applicableCharge.getPeriodicity()); } else if (applicableCharge.getFeeName().equalsIgnoreCase("Mainatnence Fee")) { Assert.assertFalse(true); } } } @Test public void testGetStatusName() throws Exception { AccountStateMachines.getInstance().initialize(AccountTypes.SAVINGS_ACCOUNT, null); String statusNameForSavings = service.getStatusName(AccountState.SAVINGS_PARTIAL_APPLICATION, AccountTypes.SAVINGS_ACCOUNT); Assert.assertNotNull(statusNameForSavings); AccountStateMachines.getInstance().initialize(AccountTypes.LOAN_ACCOUNT, null); String statusNameForLoan = service.getStatusName(AccountState.LOAN_PARTIAL_APPLICATION,AccountTypes.LOAN_ACCOUNT); Assert.assertNotNull(statusNameForLoan); } @Test public void testGetFlagName() throws Exception { AccountStateMachines.getInstance().initialize(AccountTypes.SAVINGS_ACCOUNT, null); String flagNameForSavings = service.getFlagName(AccountStateFlag.SAVINGS_REJECTED, AccountTypes.SAVINGS_ACCOUNT); Assert.assertNotNull(flagNameForSavings); AccountStateMachines.getInstance().initialize(AccountTypes.LOAN_ACCOUNT, null); String flagNameForLoan = service.getFlagName(AccountStateFlag.LOAN_REJECTED, AccountTypes.LOAN_ACCOUNT); Assert.assertNotNull(flagNameForLoan); } @Test public void testGetStatusList() throws Exception { AccountStateMachines.getInstance().initialize(AccountTypes.SAVINGS_ACCOUNT, null); List<AccountStateEntity> statusListForSavings = service.getStatusList(new AccountStateEntity( AccountState.SAVINGS_PARTIAL_APPLICATION), AccountTypes.SAVINGS_ACCOUNT, TestUtils.makeUser() .getLocaleId()); Assert.assertEquals(2, statusListForSavings.size()); AccountStateMachines.getInstance().initialize(AccountTypes.LOAN_ACCOUNT, null); List<AccountStateEntity> statusListForLoan = service.getStatusList(new AccountStateEntity( AccountState.LOAN_PARTIAL_APPLICATION), AccountTypes.LOAN_ACCOUNT, Short.valueOf("1")); Assert.assertEquals(2, statusListForLoan.size()); } private AccountBO getLoanAccount() { Date startDate = new Date(System.currentTimeMillis()); MeetingBO meeting = TestObjectFactory.createMeeting(TestObjectFactory.getNewMeetingForToday(WEEKLY, EVERY_WEEK, CUSTOMER_MEETING)); center = TestObjectFactory.createWeeklyFeeCenter("Center", meeting); group = TestObjectFactory.createWeeklyFeeGroupUnderCenter("Group", CustomerStatus.GROUP_ACTIVE, center); LoanOfferingBO loanOffering = TestObjectFactory.createLoanOffering(startDate, meeting); return TestObjectFactory.createLoanAccount("42423142341", group, AccountState.LOAN_ACTIVE_IN_GOOD_STANDING, startDate, loanOffering); } private AccountBO getLoanAccountWithAllTypesOfFees() { accountBO = getLoanAccount(); LoanScheduleEntity loanScheduleEntity = (LoanScheduleEntity) accountBO.getAccountActionDate(Short.valueOf("1")); FeeBO upfrontFee = TestObjectFactory.createOneTimeRateFee("Upfront Fee", FeeCategory.LOAN, Double.valueOf("20"), FeeFormula.AMOUNT, FeePayment.UPFRONT, null); AccountFeesEntity accountUpfrontFee = new AccountFeesEntity(accountBO, upfrontFee, new Double("20.0"), FeeStatus.ACTIVE.getValue(), null, loanScheduleEntity.getActionDate()); AccountTestUtils.addAccountFees(accountUpfrontFee, accountBO); AccountFeesActionDetailEntity accountUpfrontFeesaction = new LoanFeeScheduleEntity(loanScheduleEntity, upfrontFee, accountUpfrontFee, new Money(getCurrency(), "20.0")); loanScheduleEntity.addAccountFeesAction(accountUpfrontFeesaction); TestObjectFactory.updateObject(accountBO); accountBO = TestObjectFactory.getObject(AccountBO.class, accountBO.getAccountId()); loanScheduleEntity = (LoanScheduleEntity) accountBO.getAccountActionDate(Short.valueOf("1")); FeeBO timeOfDisbursementFees = TestObjectFactory.createOneTimeAmountFee("Disbursement Fee", FeeCategory.LOAN, "30", FeePayment.TIME_OF_DISBURSEMENT); AccountFeesEntity accountDisbursementFee = new AccountFeesEntity(accountBO, timeOfDisbursementFees, new Double( "30.0"), FeeStatus.ACTIVE.getValue(), null, loanScheduleEntity.getActionDate()); AccountTestUtils.addAccountFees(accountDisbursementFee, accountBO); AccountFeesActionDetailEntity accountDisbursementFeesaction = new LoanFeeScheduleEntity(loanScheduleEntity, timeOfDisbursementFees, accountDisbursementFee, new Money(getCurrency(), "30.0")); loanScheduleEntity.addAccountFeesAction(accountDisbursementFeesaction); TestObjectFactory.updateObject(accountBO); accountBO = TestObjectFactory.getObject(AccountBO.class, accountBO.getAccountId()); loanScheduleEntity = (LoanScheduleEntity) accountBO.getAccountActionDate(Short.valueOf("1")); FeeBO firstLoanRepaymentFee = TestObjectFactory.createOneTimeAmountFee("First Loan Repayment Fee", FeeCategory.LOAN, "40", FeePayment.TIME_OF_FIRSTLOANREPAYMENT); AccountFeesEntity accountFirstLoanRepaymentFee = new AccountFeesEntity(accountBO, firstLoanRepaymentFee, new Double("40.0"), FeeStatus.ACTIVE.getValue(), null, loanScheduleEntity.getActionDate()); AccountTestUtils.addAccountFees(accountFirstLoanRepaymentFee, accountBO); AccountFeesActionDetailEntity accountTimeOfFirstLoanRepaymentFeesaction = new LoanFeeScheduleEntity( loanScheduleEntity, firstLoanRepaymentFee, accountFirstLoanRepaymentFee, new Money(getCurrency(), "40.0")); loanScheduleEntity.addAccountFeesAction(accountTimeOfFirstLoanRepaymentFeesaction); TestObjectFactory.updateObject(accountBO); accountBO = TestObjectFactory.getObject(AccountBO.class, accountBO.getAccountId()); FeeBO periodicFee = TestObjectFactory.createPeriodicAmountFee("Periodic Fee", FeeCategory.LOAN, "200", RecurrenceType.WEEKLY, Short.valueOf("1")); AccountFeesEntity accountPeriodicFee = new AccountFeesEntity(accountBO, periodicFee, new Double("200.0"), FeeStatus.INACTIVE.getValue(), null, null); AccountTestUtils.addAccountFees(accountPeriodicFee, accountBO); TestObjectFactory.updateObject(accountBO); return accountBO; } private CustomerAccountBO getCustomerAccountWithAllTypesOfFees() { MeetingBO meeting = TestObjectFactory.createMeeting(TestObjectFactory.getNewMeetingForToday(WEEKLY, EVERY_WEEK, CUSTOMER_MEETING)); center = TestObjectFactory.createWeeklyFeeCenter("Center", meeting); CustomerAccountBO customerAccountBO = center.getCustomerAccount(); CustomerScheduleEntity customerScheduleEntity = (CustomerScheduleEntity) customerAccountBO .getAccountActionDate(Short.valueOf("1")); FeeBO upfrontFee = TestObjectFactory.createOneTimeRateFee("Upfront Fee", FeeCategory.CENTER, Double .valueOf("20"), FeeFormula.AMOUNT, FeePayment.UPFRONT, null); AccountFeesEntity accountUpfrontFee = new AccountFeesEntity(customerAccountBO, upfrontFee, new Double("20.0"), FeeStatus.ACTIVE.getValue(), null, customerScheduleEntity.getActionDate()); AccountTestUtils.addAccountFees(accountUpfrontFee, customerAccountBO); AccountFeesActionDetailEntity accountUpfrontFeesaction = new CustomerFeeScheduleEntity(customerScheduleEntity, upfrontFee, accountUpfrontFee, new Money(getCurrency(), "20.0")); customerScheduleEntity.addAccountFeesAction(accountUpfrontFeesaction); TestObjectFactory.updateObject(center); customerAccountBO = center.getCustomerAccount(); FeeBO periodicFee = TestObjectFactory.createPeriodicAmountFee("Periodic Fee", FeeCategory.ALLCUSTOMERS, "200", RecurrenceType.WEEKLY, Short.valueOf("1")); AccountFeesEntity accountPeriodicFee = new AccountFeesEntity(customerAccountBO, periodicFee, new Double("200.0"), FeeStatus.INACTIVE.getValue(), null, null); AccountTestUtils.addAccountFees(accountPeriodicFee, customerAccountBO); TestObjectFactory.updateObject(center); return customerAccountBO; } private void incrementInstallmentDate(AccountBO accountBO, int numberOfDays, Short installmentId) { for (AccountActionDateEntity accountActionDateEntity : accountBO.getAccountActionDates()) { if (accountActionDateEntity.getInstallmentId().equals(installmentId)) { Calendar dateCalendar = new GregorianCalendar(); dateCalendar.setTimeInMillis(accountActionDateEntity.getActionDate().getTime()); int year = dateCalendar.get(Calendar.YEAR); int month = dateCalendar.get(Calendar.MONTH); int day = dateCalendar.get(Calendar.DAY_OF_MONTH); dateCalendar = new GregorianCalendar(year, month, day + numberOfDays); LoanBOTestUtils.setActionDate(accountActionDateEntity, new java.sql.Date(dateCalendar.getTimeInMillis())); break; } } } }