/* * 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.framework.components.batchjobs.helpers; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mifos.framework.util.helpers.IntegrationTestObjectMother.sampleBranchOffice; import static org.mifos.framework.util.helpers.IntegrationTestObjectMother.testUser; import java.util.Date; import java.util.Set; import org.joda.time.DateTime; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.mifos.accounts.business.AccountActionDateEntity; import org.mifos.accounts.fees.business.AmountFeeBO; import org.mifos.accounts.fees.persistence.FeeDao; import org.mifos.accounts.fees.util.helpers.FeeChangeType; import org.mifos.accounts.fees.util.helpers.FeeStatus; import org.mifos.application.master.business.MifosCurrency; import org.mifos.application.meeting.business.MeetingBO; import org.mifos.customers.business.CustomerScheduleEntity; import org.mifos.customers.center.business.CenterBO; import org.mifos.customers.persistence.CustomerDao; import org.mifos.domain.builders.CenterBuilder; import org.mifos.domain.builders.FeeBuilder; import org.mifos.domain.builders.MeetingBuilder; import org.mifos.framework.MifosIntegrationTestCase; import org.mifos.framework.TestUtils; import org.mifos.framework.util.StandardTestingService; import org.mifos.framework.util.helpers.IntegrationTestObjectMother; import org.mifos.framework.util.helpers.Money; import org.mifos.service.test.TestMode; import org.mifos.test.framework.util.DatabaseCleaner; import org.springframework.beans.factory.annotation.Autowired; public class ApplyCustomerFeeChangesBatchJobIntegrationTest extends MifosIntegrationTestCase { // class under test private ApplyCustomerFeeChangesHelper applyCustomerFeeChanges; // collaborators private CenterBO center; private AmountFeeBO weeklyPeriodicFeeForCenterOnly; @Autowired private CustomerDao customerDao; @Autowired private FeeDao feeDao; @Autowired private DatabaseCleaner databaseCleaner; private static MifosCurrency oldDefaultCurrency; @BeforeClass public static void initialiseHibernateUtil() { oldDefaultCurrency = Money.getDefaultCurrency(); Money.setDefaultCurrency(TestUtils.RUPEE); new StandardTestingService().setTestMode(TestMode.INTEGRATION); } @AfterClass public static void resetCurrency() { Money.setDefaultCurrency(oldDefaultCurrency); } @After public void cleanDatabaseTablesAfterTest() { // NOTE: - only added to stop older integration tests failing due to brittleness databaseCleaner.clean(); } @Before public void cleanDatabaseTables() { databaseCleaner.clean(); DateTime eightWeeksInPast = new DateTime().minusWeeks(8); MeetingBO weeklyMeeting = new MeetingBuilder().customerMeeting().weekly().every(1).withStartDate(eightWeeksInPast).build(); IntegrationTestObjectMother.saveMeeting(weeklyMeeting); weeklyPeriodicFeeForCenterOnly = new FeeBuilder().appliesToCenterOnly() .withFeeAmount("100.0") .withName("Center Weekly Periodic Fee") .withSameRecurrenceAs(weeklyMeeting) .with(sampleBranchOffice()) .build(); IntegrationTestObjectMother.saveFee(weeklyPeriodicFeeForCenterOnly); center = new CenterBuilder().withName("Center1") .with(weeklyMeeting) .with(sampleBranchOffice()) .withLoanOfficer(testUser()) .build(); IntegrationTestObjectMother.createCenter(center, weeklyMeeting, weeklyPeriodicFeeForCenterOnly); applyCustomerFeeChanges = new ApplyCustomerFeeChangesHelper(); } @Test public void givenFeeAmountIsChangedShouldApplyFeeChangesToUpcomingAndFutureAccountFees() throws Exception { weeklyPeriodicFeeForCenterOnly.setFeeAmount(TestUtils.createMoney("52")); weeklyPeriodicFeeForCenterOnly.updateFeeChangeType(FeeChangeType.AMOUNT_UPDATED); IntegrationTestObjectMother.saveFee(weeklyPeriodicFeeForCenterOnly); long timeInMillis = new Date().getTime(); // pre-verification center = customerDao.findCenterBySystemId(center.getGlobalCustNum()); assertThatEachScheduleHasFeesDueOf(center.getCustomerAccount().getAccountActionDates(), 100.0); // exercise test applyCustomerFeeChanges.execute(timeInMillis); // verification center = customerDao.findCenterBySystemId(center.getGlobalCustNum()); assertThatFutureScheduleHasFeesDueOf(center.getCustomerAccount().getAccountActionDates(), 52.0); } @Test public void givenFeeStatusIsChangedToInactiveShouldRemoveAnyFeesAssociatedWithUpcomingAndFutureInstallments() throws Exception { weeklyPeriodicFeeForCenterOnly.updateDetails(TestUtils.makeUser()); weeklyPeriodicFeeForCenterOnly.updateFeeChangeType(FeeChangeType.STATUS_UPDATED); weeklyPeriodicFeeForCenterOnly.updateStatus(FeeStatus.INACTIVE); IntegrationTestObjectMother.saveFee(weeklyPeriodicFeeForCenterOnly); long timeInMillis = new Date().getTime(); // pre-verification center = customerDao.findCenterBySystemId(center.getGlobalCustNum()); assertThatEachScheduleHasFeesDueOf(center.getCustomerAccount().getAccountActionDates(), 100.0); // exercise test applyCustomerFeeChanges.execute(timeInMillis); // verification center = customerDao.findCenterBySystemId(center.getGlobalCustNum()); assertThatFutureScheduleHasFeesDueOf(center.getCustomerAccount().getAccountActionDates(), 0.0); } @Test @Ignore public void givenFeeStatusIsChangedFromInactiveToActiveShouldAssociateFeesWithAllKnownFutureInstallments() throws Exception { long timeInMillis = new Date().getTime(); weeklyPeriodicFeeForCenterOnly.updateDetails(TestUtils.makeUser()); weeklyPeriodicFeeForCenterOnly.updateFeeChangeType(FeeChangeType.STATUS_UPDATED); weeklyPeriodicFeeForCenterOnly.updateStatus(FeeStatus.INACTIVE); IntegrationTestObjectMother.saveFee(weeklyPeriodicFeeForCenterOnly); // setup fee and customer_fee_schedule state when fee is inactive applyCustomerFeeChanges.execute(timeInMillis); weeklyPeriodicFeeForCenterOnly = (AmountFeeBO) feeDao.findById(weeklyPeriodicFeeForCenterOnly.getFeeId()); weeklyPeriodicFeeForCenterOnly.updateDetails(TestUtils.makeUser()); weeklyPeriodicFeeForCenterOnly.updateFeeChangeType(FeeChangeType.STATUS_UPDATED); weeklyPeriodicFeeForCenterOnly.updateStatus(FeeStatus.ACTIVE); IntegrationTestObjectMother.saveFee(weeklyPeriodicFeeForCenterOnly); // pre-verification center = customerDao.findCenterBySystemId(center.getGlobalCustNum()); assertThatFutureScheduleHasFeesDueOf(center.getCustomerAccount().getAccountActionDates(), 0.0); // exercise test applyCustomerFeeChanges.execute(timeInMillis); // verification center = customerDao.findCenterBySystemId(center.getGlobalCustNum()); assertThatFutureScheduleHasFeesDueOf(center.getCustomerAccount().getAccountActionDates(), 100.0); } private void assertThatEachScheduleHasFeesDueOf(Set<AccountActionDateEntity> customerSchedules, double feesDue) { for (AccountActionDateEntity accountActionDateEntity : customerSchedules) { CustomerScheduleEntity customerSchedule = (CustomerScheduleEntity) center.getCustomerAccount().getAccountActionDate(accountActionDateEntity.getInstallmentId()); assertThat(customerSchedule.getTotalFees().getAmountDoubleValue(), is(feesDue)); } } private void assertThatFutureScheduleHasFeesDueOf(Set<AccountActionDateEntity> customerSchedules, double feesDue) { for (AccountActionDateEntity accountActionDateEntity : customerSchedules) { CustomerScheduleEntity customerSchedule = (CustomerScheduleEntity) center.getCustomerAccount().getAccountActionDate(accountActionDateEntity.getInstallmentId()); DateTime scheduledDate = new DateTime(customerSchedule.getActionDate()); if (scheduledDate.isAfter(new DateTime().minusDays(1))) { assertThat(customerSchedule.getTotalFees().getAmountDoubleValue(), is(feesDue)); } } } }