/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.gl.batch.service.impl; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.kuali.kfs.coa.businessobject.ObjectCode; import org.kuali.kfs.gl.businessobject.Balance; import org.kuali.kfs.gl.businessobject.BalanceHistory; import org.kuali.kfs.gl.businessobject.Entry; import org.kuali.kfs.gl.businessobject.EntryHistory; import org.kuali.kfs.gl.businessobject.OriginEntryInformation; import org.kuali.kfs.gl.dataaccess.LedgerBalanceBalancingDao; import org.kuali.kfs.gl.dataaccess.LedgerBalancingDao; import org.kuali.kfs.gl.dataaccess.LedgerEntryBalancingDao; import org.kuali.kfs.gl.dataaccess.LedgerEntryHistoryBalancingDao; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.context.KualiTestBase; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.context.TestUtils; import org.kuali.kfs.sys.service.UniversityDateService; import org.kuali.kfs.sys.service.impl.ReportWriterTextServiceImpl; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.krad.bo.PersistableBusinessObjectBase; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.util.ObjectUtils; /** * Is a Base class for GL and LD BalancingService test cases */ public abstract class BalancingServiceImplTestBase extends KualiTestBase { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BalancingServiceImplTestBase.class); protected static final String CHART_OF_ACCOUNTS_CODE = "BL"; protected static final String FINANCIAL_OBJECT_CODE = "5772"; protected BalancingServiceBaseImpl<Entry, Balance> balancingService; protected LedgerBalancingDao ledgerBalancingDao; protected LedgerEntryHistoryBalancingDao ledgerEntryHistoryBalancingDao; protected BusinessObjectService businessObjectService; protected DateTimeService dateTimeService; protected UniversityDateService universityDateService; protected Integer startUniversityFiscalYear; protected Integer obsoleteUniversityFiscalYear; protected String[] INPUT_TRANSACTIONS = this.getInputTransactions(); @Override protected void setUp() throws Exception { super.setUp(); dateTimeService = SpringContext.getBean(DateTimeService.class); universityDateService = SpringContext.getBean(UniversityDateService.class); // Due to how WrappingBatchService works we need to manually initialize report writing ((ReportWriterTextServiceImpl) balancingService.reportWriterService).initialize(); // Make the last two of INPUT_TRANSACTIONS out of date range Integer currentFiscalYear = universityDateService.getCurrentFiscalYear(); startUniversityFiscalYear = currentFiscalYear - balancingService.getPastFiscalYearsToConsider(); obsoleteUniversityFiscalYear = startUniversityFiscalYear - 1; for (int i = 0; i < INPUT_TRANSACTIONS.length; i++) { if (i < INPUT_TRANSACTIONS.length - 2) { INPUT_TRANSACTIONS[i] = currentFiscalYear + INPUT_TRANSACTIONS[i]; } else { // Want the last two to be out of range INPUT_TRANSACTIONS[i] = obsoleteUniversityFiscalYear + INPUT_TRANSACTIONS[i]; } } // And to make sure that the posters don't complain we need to generate data in the obsolete fiscal year this.generateObsoleteYearData(obsoleteUniversityFiscalYear); } @Override protected void tearDown() throws Exception { // KualiTestBase cleans added files up. Hence we need to make sure BalancingService doesn't use cache when looking for files balancingService.clearPosterFileCache(); // Due to how WrappingBatchService works we need to manually destroy report writing ((ReportWriterTextServiceImpl) balancingService.reportWriterService).destroy(); super.tearDown(); } public void testBasicGetters() { // Here we test a set of basic getters. There really isn't much that should be done here because they vary between GL and Labor plus // these are pretty simple methods. Just checking that they return values should be enough. assertNotNull(balancingService.getPastFiscalYearsToConsider()); assertNotNull(balancingService.getComparisonFailuresToPrintPerReport()); // These should at minimum return Entry and Balance plus Histories for each GL and Labor assertNotNull(balancingService.getShortTableLabel((Entry.class).getSimpleName())); assertNotNull(balancingService.getShortTableLabel((EntryHistory.class).getSimpleName())); assertNotNull(balancingService.getShortTableLabel((Balance.class).getSimpleName())); assertNotNull(balancingService.getShortTableLabel((BalanceHistory.class).getSimpleName())); // Whether files are ready or not depends on if the poster ran before this. We are just executing the code here and not checking return value. balancingService.getPosterInputFile(); balancingService.getPosterErrorOutputFile(); } public void testGetOriginEntry() { LOG.debug("Basic test that getting GL or Labor OriginEntryInformation works. Since the parsing method isn't part of Balancing we don't run a full test."); OriginEntryInformation originEntry = balancingService.getOriginEntry(INPUT_TRANSACTIONS[0], 0); assertNotNull(originEntry); assertEquals(TestUtils.getFiscalYearForTesting().intValue(), originEntry.getUniversityFiscalYear().intValue()); } public void testIsFilesReady() { // Delete the files since we don't know whether the poster run before this test case or not TestUtils.deleteFilesInDirectory(this.getBatchFileDirectoryName()); LOG.debug("No file data present scenario"); assertFalse(balancingService.isFilesReady()); LOG.debug("Files ready scenario"); this.postTestCaseEntries(INPUT_TRANSACTIONS); assertTrue(balancingService.isFilesReady()); } public abstract void testRunBalancingPopulateData(); public abstract void testRunBalancingDeleteObsoleteUniversityFiscalYearData(); public abstract void testRunBalancingHistoryUpdate(); /** * Fix Test */ public void PATCHFIX_testRunBalancingComparisionFailure() { // Execute exactly the same as testRunBalancingPopulateData. This serves to populate the tables this.testRunBalancingPopulateData(); // Now run balancing again, in the same accounting cycle assertTrue(balancingService.runBalancing()); // This caused comparison failures because the update was run twice for the same accounting cycle, verify that was the case this.assertCompareHistoryFailure(); } /** * Test helper since PosterService and LaborPosterService are exclusive interfaces. */ protected abstract void postTestCaseEntries(String[] inputTransactions); /** * Test helper to get GL or Labor sample transactions. This isn't in fixtures because these are written to a file, not used as objects */ protected abstract String[] getInputTransactions(); /** * Test helper to compare history data to live data, expecting comparison success */ protected void assertCompareHistorySuccess() { assertEquals(0, balancingService.compareEntryHistory().intValue()); assertEquals(0, balancingService.compareBalanceHistory().intValue()); Map<String, Integer> countCustomComparisionFailures = balancingService.customCompareHistory(); if (ObjectUtils.isNotNull(countCustomComparisionFailures)) { for (Iterator<String> names = countCustomComparisionFailures.keySet().iterator(); names.hasNext();) { String name = names.next(); assertEquals(0, countCustomComparisionFailures.get(name).intValue()); } } } /** * Test helper to compare history data to live data, expecting comparison failure */ protected void assertCompareHistoryFailure() { assertNotSame(0, balancingService.compareEntryHistory().intValue()); assertNotSame(0, balancingService.compareBalanceHistory().intValue()); Map<String, Integer> countCustomComparisionFailures = balancingService.customCompareHistory(); if (ObjectUtils.isNotNull(countCustomComparisionFailures)) { for (Iterator<String> names = countCustomComparisionFailures.keySet().iterator(); names.hasNext();) { String name = names.next(); assertNotSame(0, countCustomComparisionFailures.get(name).intValue()); } } } /** * Test helper to generate obsolete fiscal year data if it does not exist. This method is messy. What it is doing is to check if the entries exist in * case there was an FY rollover but data wasn't updated yet. If not, it makes copies of the current. This corresponds to the entries getInputTransactions * @param obsoleteYear */ protected void generateObsoleteYearData(Integer obsoleteYear) { Map<String, Object> obsoleteChartOfAccountFieldValues = new HashMap<String, Object>(); obsoleteChartOfAccountFieldValues.put(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, obsoleteYear); obsoleteChartOfAccountFieldValues.put(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, CHART_OF_ACCOUNTS_CODE); obsoleteChartOfAccountFieldValues.put(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, FINANCIAL_OBJECT_CODE); ObjectCode obsoleteYearObjectCode = (ObjectCode) businessObjectService.findByPrimaryKey(ObjectCode.class, obsoleteChartOfAccountFieldValues); if (ObjectUtils.isNull(obsoleteYearObjectCode)) { Map<String, Object> fieldValues = new HashMap<String, Object>(); fieldValues.put(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, TestUtils.getFiscalYearForTesting()); fieldValues.put(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, CHART_OF_ACCOUNTS_CODE); fieldValues.put(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, FINANCIAL_OBJECT_CODE); ObjectCode objectCode = (ObjectCode) businessObjectService.findByPrimaryKey(ObjectCode.class, fieldValues); objectCode.setUniversityFiscalYear(obsoleteYear); objectCode.setVersionNumber(null); objectCode.setObjectId(null); businessObjectService.save(objectCode); } } /** * Test helper to expose protected method on BalancingService. Quick and dirty way to make the test case easy to write and avoid exposing (making public) production code unnecessarily. */ protected int getHistoryCount(Integer fiscalYear, Class<? extends PersistableBusinessObjectBase> persistentClass) { return balancingService.getHistoryCount(fiscalYear, persistentClass); } /** * Test helper to expose protected method on BalancingService. Quick and dirty way to make the test case easy to write and avoid exposing (making public) production code unnecessarily. */ protected LedgerEntryBalancingDao getLedgerEntryBalancingDao() { return balancingService.ledgerEntryBalancingDao; } /** * Test helper to expose protected method on BalancingService. Quick and dirty way to make the test case easy to write and avoid exposing (making public) production code unnecessarily. */ protected LedgerBalanceBalancingDao getLedgerBalanceBalancingDao() { return balancingService.ledgerBalanceBalancingDao; } /** * Test helper to expose protected method on BalancingService. Quick and dirty way to make the test case easy to write and avoid exposing (making public) production code unnecessarily. */ protected String getBatchFileDirectoryName() { return balancingService.batchFileDirectoryName; } }