/*
* 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.service;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.kuali.kfs.gl.GeneralLedgerConstants;
import org.kuali.kfs.sys.ConfigureContext;
import org.kuali.kfs.sys.context.KualiTestBase;
import org.kuali.kfs.sys.context.SpringContext;
import org.kuali.kfs.sys.dataaccess.UnitTestSqlDao;
import org.kuali.rice.core.api.config.property.ConfigurationService;
import org.kuali.rice.core.api.datetime.DateTimeService;
/**
* Tests the NighlyOutService
*/
@ConfigureContext
public class NightlyOutServiceTest extends KualiTestBase {
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(NightlyOutServiceTest.class);
private NightlyOutService nightlyOutService;
private UnitTestSqlDao unitTestSqlDao;
private DateTimeService dateTimeService;
protected Date date;
protected String batchDirectory;
protected String nightlyOutFileName;
/**
* Initializes the services needed for this test
* @see junit.framework.TestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
nightlyOutService = SpringContext.getBean(NightlyOutService.class);
unitTestSqlDao = SpringContext.getBean(UnitTestSqlDao.class);
dateTimeService = SpringContext.getBean(DateTimeService.class);
date = dateTimeService.getCurrentDate();
batchDirectory = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString("staging.directory")+"/gl/test_directory/originEntry";
File batchDirectoryFile = new File(SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString("staging.directory")+"/gl/test_directory");
batchDirectoryFile.mkdir();
batchDirectoryFile = new File(batchDirectory);
batchDirectoryFile.mkdir();
nightlyOutFileName = batchDirectory + File.separator + GeneralLedgerConstants.BatchFileSystem.NIGHTLY_OUT_FILE + GeneralLedgerConstants.BatchFileSystem.EXTENSION;
}
/**
* Removes the directory for the batch files to go in
* @see junit.framework.TestCase#tearDown()
*/
@Override
public void tearDown() throws Exception {
File batchDirectoryFile = new File(batchDirectory);
for (File f : batchDirectoryFile.listFiles()) {
f.delete();
}
batchDirectoryFile.delete();
batchDirectoryFile = new File(SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString("staging.directory")+"/gl/test_directory");
batchDirectoryFile.delete();
}
/**
* An inner class to filter only the files for this batch run
*/
final class BatchFilenameFilter implements FilenameFilter {
/**
* @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
*/
@Override
public boolean accept(File dir, String name) {
return name.equals(GeneralLedgerConstants.BatchFileSystem.NIGHTLY_OUT_FILE);
}
}
/**
* This test validates that the correct data is copied into origin_entry
*
* @throws Exception thrown if any exception is encountered for any reason
*/
@ConfigureContext(shouldCommitTransactions=true)
public void testCopyPendingLedgerEntry() throws Exception {
// Empty out the origin entry group & origin entry tables
assertTrue("batch directory does not exist", new File(batchDirectory).isDirectory());
for (File file : new File(batchDirectory).listFiles()) {
file.delete();
}
// Empty out the pending entry table & doc header table
LOG.info( "deleting from KRNS_DOC_HDR_T" );
unitTestSqlDao.sqlCommand("delete from KRNS_DOC_HDR_T where doc_hdr_id in ('1','2','3')");
LOG.info( "deleting from FS_DOC_HEADER_T" );
unitTestSqlDao.sqlCommand("delete from FS_DOC_HEADER_T where fdoc_nbr in ('1','2','3')");
LOG.info( "deleting from GL_PENDING_ENTRY" );
unitTestSqlDao.sqlCommand("delete from GL_PENDING_ENTRY_T");
// Add a few documents
LOG.info( "Inserting new documents" );
unitTestSqlDao.sqlCommand("insert into KRNS_DOC_HDR_T (doc_hdr_id,obj_id,ver_nbr,fdoc_desc,org_doc_hdr_id,tmpl_doc_hdr_id) values ('1','" + UUID.randomUUID().toString() + "',1,'a','OA',null)");
unitTestSqlDao.sqlCommand("insert into FS_DOC_HEADER_T (fdoc_nbr,fdoc_status_cd,fdoc_total_amt,fdoc_in_err_nbr) values ('1','A',100,null)");
unitTestSqlDao.sqlCommand("insert into KRNS_DOC_HDR_T (doc_hdr_id,obj_id,ver_nbr,fdoc_desc,org_doc_hdr_id,tmpl_doc_hdr_id) values ('2','" + UUID.randomUUID().toString() + "',1,'b','OB',null)");
unitTestSqlDao.sqlCommand("insert into FS_DOC_HEADER_T (fdoc_nbr,fdoc_status_cd,fdoc_total_amt,fdoc_in_err_nbr) values ('2','D',100,null)");
unitTestSqlDao.sqlCommand("insert into KRNS_DOC_HDR_T (doc_hdr_id,obj_id,ver_nbr,fdoc_desc,org_doc_hdr_id,tmpl_doc_hdr_id) values ('3','" + UUID.randomUUID().toString() + "',1,'c','OC',null)");
unitTestSqlDao.sqlCommand("insert into FS_DOC_HEADER_T (fdoc_nbr,fdoc_status_cd,fdoc_total_amt,fdoc_in_err_nbr) values ('3','A',100,null)");
LOG.info( "Inserting new GL Pending entries" );
unitTestSqlDao.sqlCommand("insert into GL_PENDING_ENTRY_T (fs_origin_cd,fdoc_nbr,trn_entr_seq_nbr,obj_id,ver_nbr,fin_coa_cd,account_nbr," + "sub_acct_nbr,fin_object_cd,fin_sub_obj_cd,fin_balance_typ_cd,fin_obj_typ_cd,univ_fiscal_yr,univ_fiscal_prd_cd," + "trn_ldgr_entr_desc,trn_ldgr_entr_amt,trn_debit_crdt_cd,transaction_dt,fdoc_typ_cd,org_doc_nbr,project_cd," + "org_reference_id,fdoc_ref_typ_cd,fs_ref_origin_cd,fdoc_ref_nbr,fdoc_reversal_dt,trn_encum_updt_cd,fdoc_approved_cd," + "acct_sf_finobj_cd,trn_entr_ofst_cd,trnentr_process_tm) values ('01','1',1,'" + UUID.randomUUID().toString() + "',1,'BA','1234567'," + "null,'4166',null,'AC','EX',2004,'01'," + "'Description',100,'D'," + unitTestSqlDao.getDbPlatform().getCurTimeFunction() + ",'JV',null,null," + "null,null,null,null,null,' ','A'," + "'4166',null,null)");
unitTestSqlDao.sqlCommand("insert into GL_PENDING_ENTRY_T (fs_origin_cd,fdoc_nbr,trn_entr_seq_nbr,obj_id,ver_nbr,fin_coa_cd,account_nbr," + "sub_acct_nbr,fin_object_cd,fin_sub_obj_cd,fin_balance_typ_cd,fin_obj_typ_cd,univ_fiscal_yr,univ_fiscal_prd_cd," + "trn_ldgr_entr_desc,trn_ldgr_entr_amt,trn_debit_crdt_cd,transaction_dt,fdoc_typ_cd,org_doc_nbr,project_cd," + "org_reference_id,fdoc_ref_typ_cd,fs_ref_origin_cd,fdoc_ref_nbr,fdoc_reversal_dt,trn_encum_updt_cd,fdoc_approved_cd," + "acct_sf_finobj_cd,trn_entr_ofst_cd,trnentr_process_tm) values ('01','1',2,'" + UUID.randomUUID().toString() + "',1,'BA','1234567'," + "null,'4166',null,'AC','EX',2004,'01'," + "'Description',100,'C'," + unitTestSqlDao.getDbPlatform().getCurTimeFunction() + ",'JV',null,null," + "null,null,null,null,null,' ',null," + "'4166',null,null)");
unitTestSqlDao.sqlCommand("insert into GL_PENDING_ENTRY_T (fs_origin_cd,fdoc_nbr,trn_entr_seq_nbr,obj_id,ver_nbr,fin_coa_cd,account_nbr," + "sub_acct_nbr,fin_object_cd,fin_sub_obj_cd,fin_balance_typ_cd,fin_obj_typ_cd,univ_fiscal_yr,univ_fiscal_prd_cd," + "trn_ldgr_entr_desc,trn_ldgr_entr_amt,trn_debit_crdt_cd,transaction_dt,fdoc_typ_cd,org_doc_nbr,project_cd," + "org_reference_id,fdoc_ref_typ_cd,fs_ref_origin_cd,fdoc_ref_nbr,fdoc_reversal_dt,trn_encum_updt_cd,fdoc_approved_cd," + "acct_sf_finobj_cd,trn_entr_ofst_cd,trnentr_process_tm) values ('01','2',3,'" + UUID.randomUUID().toString() + "',1,'BA','1234567'," + "null,'4166',null,'AC','EX',2004,'01'," + "'Description',100,'D'," + unitTestSqlDao.getDbPlatform().getCurTimeFunction() + ",'JV',null,null," + "null,null,null,null,null,' ','A'," + "'4166',null,null)");
unitTestSqlDao.sqlCommand("insert into GL_PENDING_ENTRY_T (fs_origin_cd,fdoc_nbr,trn_entr_seq_nbr,obj_id,ver_nbr,fin_coa_cd,account_nbr," + "sub_acct_nbr,fin_object_cd,fin_sub_obj_cd,fin_balance_typ_cd,fin_obj_typ_cd,univ_fiscal_yr,univ_fiscal_prd_cd," + "trn_ldgr_entr_desc,trn_ldgr_entr_amt,trn_debit_crdt_cd,transaction_dt,fdoc_typ_cd,org_doc_nbr,project_cd," + "org_reference_id,fdoc_ref_typ_cd,fs_ref_origin_cd,fdoc_ref_nbr,fdoc_reversal_dt,trn_encum_updt_cd,fdoc_approved_cd," + "acct_sf_finobj_cd,trn_entr_ofst_cd,trnentr_process_tm) values ('01','2',4,'" + UUID.randomUUID().toString() + "',1,'BA','1234567'," + "null,'4166',null,'AC','EX',2004,'01'," + "'Description',100,'C'," + unitTestSqlDao.getDbPlatform().getCurTimeFunction() + ",'JV',null,null," + "null,null,null,null,null,' ',null," + "'4166',null,null)");
unitTestSqlDao.sqlCommand("insert into GL_PENDING_ENTRY_T (fs_origin_cd,fdoc_nbr,trn_entr_seq_nbr,obj_id,ver_nbr,fin_coa_cd,account_nbr," + "sub_acct_nbr,fin_object_cd,fin_sub_obj_cd,fin_balance_typ_cd,fin_obj_typ_cd,univ_fiscal_yr,univ_fiscal_prd_cd," + "trn_ldgr_entr_desc,trn_ldgr_entr_amt,trn_debit_crdt_cd,transaction_dt,fdoc_typ_cd,org_doc_nbr,project_cd," + "org_reference_id,fdoc_ref_typ_cd,fs_ref_origin_cd,fdoc_ref_nbr,fdoc_reversal_dt,trn_encum_updt_cd,fdoc_approved_cd," + "acct_sf_finobj_cd,trn_entr_ofst_cd,trnentr_process_tm) values ('01','3',5,'" + UUID.randomUUID().toString() + "',1,'BA','1234567'," + "null,'4166',null,'AC','EX',2004,'01'," + "'Description',100,'D'," + unitTestSqlDao.getDbPlatform().getCurTimeFunction() + ",'JV',null,null," + "null,null,null,null,null,' ','X'," + "'4166',null,null)");
unitTestSqlDao.sqlCommand("insert into GL_PENDING_ENTRY_T (fs_origin_cd,fdoc_nbr,trn_entr_seq_nbr,obj_id,ver_nbr,fin_coa_cd,account_nbr," + "sub_acct_nbr,fin_object_cd,fin_sub_obj_cd,fin_balance_typ_cd,fin_obj_typ_cd,univ_fiscal_yr,univ_fiscal_prd_cd," + "trn_ldgr_entr_desc,trn_ldgr_entr_amt,trn_debit_crdt_cd,transaction_dt,fdoc_typ_cd,org_doc_nbr,project_cd," + "org_reference_id,fdoc_ref_typ_cd,fs_ref_origin_cd,fdoc_ref_nbr,fdoc_reversal_dt,trn_encum_updt_cd,fdoc_approved_cd," + "acct_sf_finobj_cd,trn_entr_ofst_cd,trnentr_process_tm) values ('01','3',6,'" + UUID.randomUUID().toString() + "',1,'BA','1234567'," + "null,'4166',null,'AC','EX',2004,'01'," + "'Description',100,'C'," + unitTestSqlDao.getDbPlatform().getCurTimeFunction() + ",'JV',null,null," + "null,null,null,null,null,' ','X'," + "'4166',null,null)");
LOG.info( "Calling NightlyOutService to copy the pending entries" );
nightlyOutService.copyApprovedPendingLedgerEntries();
LOG.info( "Completed Call to NightlyOutService" );
assertEquals("Should have 2 group and one done file", 2, new File(batchDirectory).list().length);
assertEquals("Should have 2 entries", 2, countOriginEntriesInFile());
LOG.info( "Checking for processed GL Pending Entries" );
// 2 transactions were set to X to start with, 2 were marked as X when copyApprovedPendingLedgerEntries was run
List pendingEntries = unitTestSqlDao.sqlSelect("select * from GL_PENDING_ENTRY_T where fdoc_approved_cd = 'X'");
assertEquals("Should have 4 copied entries", 4, pendingEntries.size());
LOG.info( "Deleting processed GL Pending Entries" );
nightlyOutService.deleteCopiedPendingLedgerEntries();
LOG.info( "Confirming that GL Pending Entry is again empty" );
List remainderEntries = unitTestSqlDao.sqlSelect("select * from GL_PENDING_ENTRY_T");
assertEquals("Should have 2 remaining entries", 2, remainderEntries.size());
}
/**
* @return the number of entries in the nightly out origin entry file
*/
protected int countOriginEntriesInFile() {
int count = 0;
try {
File nightlyOutFile = new File(this.nightlyOutFileName);
BufferedReader nightlyOutFileIn = new BufferedReader(new InputStreamReader(new FileInputStream(nightlyOutFile)));
while (nightlyOutFileIn.readLine() != null) {
count += 1;
}
}
catch (FileNotFoundException fnfe) {
//let's not sweat this one - if the file didn't exist, we'd hit errors before this
throw new RuntimeException(fnfe);
}
catch (IOException ioe) {
throw new RuntimeException(ioe);
}
return count;
}
}