/*
* 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.module.bc.batch.dataaccess.impl;
import java.lang.reflect.InvocationTargetException;
import java.sql.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.log4j.Logger;
import org.apache.ojb.broker.query.Criteria;
import org.apache.ojb.broker.query.QueryByCriteria;
import org.apache.ojb.broker.query.ReportQueryByCriteria;
import org.kuali.kfs.coa.businessobject.Account;
import org.kuali.kfs.coa.businessobject.AccountingPeriod;
import org.kuali.kfs.coa.businessobject.SubFundGroup;
import org.kuali.kfs.module.bc.BCConstants;
import org.kuali.kfs.module.bc.batch.dataaccess.GeneralLedgerBudgetLoadDao;
import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader;
import org.kuali.kfs.module.bc.businessobject.BudgetConstructionMonthly;
import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionGeneralLedger;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
import org.kuali.rice.core.api.util.type.KualiInteger;
public class GeneralLedgerBudgetLoadDaoOjb extends BudgetConstructionBatchHelperDaoOjb implements GeneralLedgerBudgetLoadDao {
/* turn on the logger for the persistence broker */
private static Logger LOG = org.apache.log4j.Logger.getLogger(GeneralLedgerBudgetLoadDaoOjb.class);
/*
* see GeneralLedgerBudgetLoadDao.LoadGeneralLedgerFromBudget
*/
public void loadGeneralLedgerFromBudget(Integer fiscalYear, Date currentSqlDate, String financialSystemOriginationCode) {
/**
* this method calls a series of steps that load the general ledger from the budget into the general ledger pending entry
* table. this method takes a fiscal year as input, but all that is required is that this object be a key labeling the
* bduget construction general ledger rows for the budget period to be loaded. it need not be an actual fiscal year.
*/
//
// set up the global variables
// this is a single object that can be passed to all methods that need it, to make the code "thread safe"
// (1) the fiscal year to load
// (2) the initial sequence numbers for each document to be loaded
// (3) the run date (which will be the transaction date)
// (4) the "origination code", which comes from the database
DaoGlobalVariables daoGlobalVariables = new DaoGlobalVariables(fiscalYear, currentSqlDate, financialSystemOriginationCode);
/**
* initiliaze the counter variables
*/
DiagnosticCounters diagnosticCounters = new DiagnosticCounters();
/**
* make sure all the accounting periods for the load year are open, so the entry lines we create can be posted
*/
openAllAccountingPeriods(fiscalYear);
/**
* process pending budget construction general ledger rows
*/
loadPendingBudgetConstructionGeneralLedger(daoGlobalVariables, diagnosticCounters);
/**
* process budget construction monthly budget rows
*/
loadBudgetConstructionMonthlyBudget(daoGlobalVariables, diagnosticCounters);
// write out the counts for verification
diagnosticCounters.writeDiagnosticCounters();
}
/*******************************************************************************************************************************
* methods to do the actual load *
******************************************************************************************************************************/
/**
* build a hashmap containing the next entry sequence number to use for each document (document number) to be loaded from budget
* construction to the general ledger
*
* @param target fiscal year for the budget load
* @return HashMapap keyed on document number containing the next entry sequence number to use for the key
*/
protected HashMap<String, Integer> entrySequenceNumber(Integer requestYear) {
HashMap<String, Integer> nextEntrySequenceNumber;
// set up the query: each distinct document number in the source load table
Criteria criteriaID = new Criteria();
criteriaID.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, requestYear);
ReportQueryByCriteria queryID = new ReportQueryByCriteria(BudgetConstructionHeader.class, criteriaID);
queryID.setAttributes(new String[] { KFSPropertyConstants.DOCUMENT_NUMBER });
nextEntrySequenceNumber = new HashMap<String, Integer>(hashCapacity(queryID));
// OK. build the hash map
// there are NO entries for these documents yet, so we initialize the entry sequence number to 0
Iterator documentNumbersToLoad = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(queryID);
while (documentNumbersToLoad.hasNext()) {
Object[] resultRow = (Object[]) documentNumbersToLoad.next();
nextEntrySequenceNumber.put((String) resultRow[0], new Integer(0));
}
return nextEntrySequenceNumber;
}
/**
* This method creates a new generalLedgerPendingEntry object and initializes it with the default settings for the budget
* construction general ledger load.
*
* @param requestYear
* @param financialSystemOriginationCode
* @return intiliazed GeneralLedgerPendingEntry business object
*/
protected GeneralLedgerPendingEntry getNewPendingEntryWithDefaults(DaoGlobalVariables daoGlobalVariables) {
GeneralLedgerPendingEntry newRow = new GeneralLedgerPendingEntry();
newRow.setUniversityFiscalYear(daoGlobalVariables.getRequestYear());
newRow.setTransactionLedgerEntryDescription(BCConstants.BC_TRN_LDGR_ENTR_DESC);
newRow.setFinancialDocumentTypeCode(BCConstants.BUDGET_CONSTRUCTION_BEGINNING_BALANCE_DOCUMENT_TYPE);
newRow.setFinancialDocumentApprovedCode(KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
newRow.setTransactionDate(daoGlobalVariables.getTransactionDate());
newRow.setTransactionEntryOffsetIndicator(false);
newRow.setFinancialSystemOriginationCode(daoGlobalVariables.getFinancialSystemOriginationcode());
// the fields below are set to null
newRow.setOrganizationDocumentNumber(null);
newRow.setProjectCode(null);
newRow.setOrganizationReferenceId(null);
newRow.setReferenceFinancialDocumentTypeCode(null);
newRow.setReferenceOriginationCode(null);
newRow.setReferenceFinancialDocumentNumber(null);
newRow.setFinancialDocumentReversalDate(null);
newRow.setTransactionEncumbranceUpdateCode(null);
newRow.setAcctSufficientFundsFinObjCd(null);
newRow.setTransactionDebitCreditCode(null);
newRow.setTransactionEntryProcessedTs(null);
return newRow;
}
protected void loadBudgetConstructionMonthlyBudget(DaoGlobalVariables daoGlobalVariables, DiagnosticCounters diagnosticCounters) {
QueryByCriteria queryID = queryForBudgetConstructionMonthly(daoGlobalVariables.getRequestYear());
Iterator<BudgetConstructionMonthly> monthlyBudgetRows = getPersistenceBrokerTemplate().getIteratorByQuery(queryID);
while (monthlyBudgetRows.hasNext()) {
BudgetConstructionMonthly monthlyBudgetIn = monthlyBudgetRows.next();
diagnosticCounters.increaseBudgetConstructionMonthlyBudgetRead();
if (daoGlobalVariables.shouldThisAccountLoad(monthlyBudgetIn.getAccountNumber() + monthlyBudgetIn.getChartOfAccountsCode())) {
GeneralLedgerPendingEntry newRow = getNewPendingEntryWithDefaults(daoGlobalVariables);
writeGeneralLedgerPendingEntryFromMonthly(newRow, monthlyBudgetIn, daoGlobalVariables, diagnosticCounters);
}
else {
diagnosticCounters.increaseBudgetConstructionMonthlyBudgetSkipped();
}
}
}
/**
* This method loads all the eligible pending budget construction general ledger rows
*
* @param daoGlobalVariables
* @param diagnosticCounters
*/
protected void loadPendingBudgetConstructionGeneralLedger(DaoGlobalVariables daoGlobalVariables, DiagnosticCounters diagnosticCounters) {
QueryByCriteria queryID = queryForPendingBudgetConstructionGeneralLedger(daoGlobalVariables.getRequestYear());
Iterator<PendingBudgetConstructionGeneralLedger> pbglRows = getPersistenceBrokerTemplate().getIteratorByQuery(queryID);
while (pbglRows.hasNext()) {
PendingBudgetConstructionGeneralLedger pbglIn = pbglRows.next();
diagnosticCounters.increaseBudgetConstructionPendingGeneralLedgerRead();
if (daoGlobalVariables.shouldThisAccountLoad(pbglIn.getAccountNumber() + pbglIn.getChartOfAccountsCode())) {
GeneralLedgerPendingEntry newRow = getNewPendingEntryWithDefaults(daoGlobalVariables);
writeGeneralLedgerPendingEntryFromAnnual(newRow, pbglIn, daoGlobalVariables, diagnosticCounters);
}
else {
diagnosticCounters.increaseBudgetConstructionPendingGeneralLedgerSkipped();
}
}
}
/**
* This method builds the query to fetch the monthly budget general ledger lines to be loaded
*
* @param fiscalYear : the year to be loaded
* @return query for fetching monthly budget rows
*/
protected QueryByCriteria queryForBudgetConstructionMonthly(Integer fiscalYear) {
// we only select rows which have non-zero budget amounts
// on this object, proxy=true, so we can do a regular query for a business object instead of a report query
Criteria criteriaID = new Criteria();
criteriaID.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, fiscalYear);
// we want to test for at least one non-zero monthly amount
Criteria orCriteriaID = new Criteria();
Iterator<String[]> monthlyPeriods = BCConstants.BC_MONTHLY_AMOUNTS.iterator();
while (monthlyPeriods.hasNext()) {
// the first array element is the amount field name (the second is the corresponding accounting period)
String monthlyAmountName = monthlyPeriods.next()[0];
Criteria amountCriteria = new Criteria();
amountCriteria.addNotEqualTo(monthlyAmountName, new KualiInteger(0));
orCriteriaID.addOrCriteria(amountCriteria);
}
criteriaID.addAndCriteria(orCriteriaID);
QueryByCriteria queryID = new QueryByCriteria(BudgetConstructionMonthly.class, criteriaID);
return queryID;
}
/**
* This method builds the query to fetch the pending budget construction general ledger rows to be loaded
*
* @param fiscalYear: the year to be loaded
* @return query for fetching pending budget construction GL rows
*/
protected QueryByCriteria queryForPendingBudgetConstructionGeneralLedger(Integer fiscalYear) {
// we only select rows which have non-zero budget amounts
// on this object, proxy=true, so we can do a regular query for a business object instead of a report query
Criteria criteriaID = new Criteria();
criteriaID.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, fiscalYear);
criteriaID.addNotEqualTo(KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT, new KualiInteger(0));
QueryByCriteria queryID = new QueryByCriteria(PendingBudgetConstructionGeneralLedger.class, criteriaID);
return queryID;
}
/**
* complete the pending entry row based on the data returned from the DB store it to the DB
*
* @param newRow
* @param source annual budget construction GL row
* @param object containing global constants
*/
protected void writeGeneralLedgerPendingEntryFromAnnual(GeneralLedgerPendingEntry newRow, PendingBudgetConstructionGeneralLedger pbgl, DaoGlobalVariables daoGlobalVariables, DiagnosticCounters diagnosticCounters) {
/**
* first get the document number
*/
String incomingDocumentNumber = pbgl.getDocumentNumber();
/**
* write a base budget row
*/
newRow.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_BASE_BUDGET);
newRow.setUniversityFiscalPeriodCode(KFSConstants.PERIOD_CODE_BEGINNING_BALANCE);
/**
* set the variable fields
*/
newRow.setTransactionLedgerEntrySequenceNumber(daoGlobalVariables.getNextSequenceNumber(incomingDocumentNumber));
newRow.setDocumentNumber(incomingDocumentNumber); // document number
newRow.setChartOfAccountsCode(pbgl.getChartOfAccountsCode()); // chart of accounts
newRow.setAccountNumber(pbgl.getAccountNumber()); // account number
newRow.setSubAccountNumber(pbgl.getSubAccountNumber()); // sub account number
newRow.setFinancialObjectCode(pbgl.getFinancialObjectCode()); // object code
newRow.setFinancialSubObjectCode(pbgl.getFinancialSubObjectCode()); // sub object code
newRow.setFinancialObjectTypeCode(pbgl.getFinancialObjectTypeCode()); // object type code
/**
* the budget works with whole numbers--we must convert to decimal for the general ledger
*/
newRow.setTransactionLedgerEntryAmount(pbgl.getAccountLineAnnualBalanceAmount().kualiDecimalValue());
/**
* now we store the base budget value
*/
getPersistenceBrokerTemplate().store(newRow);
diagnosticCounters.increaseGeneralLedgerBaseBudgetWritten();
/**
* the same row needs to be written as a current budget item we change only the balance type and the sequence number
*/
newRow.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_CURRENT_BUDGET);
newRow.setTransactionLedgerEntrySequenceNumber(daoGlobalVariables.getNextSequenceNumber(incomingDocumentNumber));
/**
* store the current budget value
*/
getPersistenceBrokerTemplate().store(newRow);
diagnosticCounters.increasGenneralLedgerCurrentBudgetWritten();
}
protected void writeGeneralLedgerPendingEntryFromMonthly(GeneralLedgerPendingEntry newRow, BudgetConstructionMonthly pbglMonthly, DaoGlobalVariables daoGlobalVariables, DiagnosticCounters diagnosticCounters) {
/**
* first get the document number
*/
String incomingDocumentNumber = pbglMonthly.getDocumentNumber();
/**
* write a base budget row
*/
newRow.setFinancialBalanceTypeCode(KFSConstants.BALANCE_TYPE_MONTHLY_BUDGET);
/**
* set the variable fields
*/
newRow.setDocumentNumber(incomingDocumentNumber); // document number
newRow.setChartOfAccountsCode(pbglMonthly.getChartOfAccountsCode()); // chart of accounts
newRow.setAccountNumber(pbglMonthly.getAccountNumber()); // account number
newRow.setSubAccountNumber(pbglMonthly.getSubAccountNumber()); // sub account number
newRow.setFinancialObjectCode(pbglMonthly.getFinancialObjectCode()); // object code
newRow.setFinancialSubObjectCode(pbglMonthly.getFinancialSubObjectCode()); // sub object code
newRow.setFinancialObjectTypeCode(pbglMonthly.getFinancialObjectTypeCode()); // object type code
/**
* we have to loop through the monthly array, and write an MB row for each monthly row with a non-zero amount (we do this to
* write less code. we hope that the extra hit from reflection won't be too bad)
*/
Iterator<String[]> monthlyPeriodAmounts = BCConstants.BC_MONTHLY_AMOUNTS.iterator();
while (monthlyPeriodAmounts.hasNext()) {
String[] monthlyPeriodProperties = monthlyPeriodAmounts.next();
KualiInteger monthlyAmount;
try {
monthlyAmount = (KualiInteger) PropertyUtils.getSimpleProperty(pbglMonthly, monthlyPeriodProperties[0]);
}
catch (IllegalAccessException ex) {
LOG.error(String.format("\nunable to use get method to access value of %s in %s\n", monthlyPeriodProperties[0], BudgetConstructionMonthly.class.getName()), ex);
diagnosticCounters.writeDiagnosticCounters();
throw new RuntimeException(ex);
}
catch (InvocationTargetException ex) {
LOG.error(String.format("\nunable to invoke get method for %s in %s\n", monthlyPeriodProperties[0], BudgetConstructionMonthly.class.getName()), ex);
diagnosticCounters.writeDiagnosticCounters();
throw new RuntimeException(ex);
}
catch (NoSuchMethodException ex) {
LOG.error(String.format("\nNO get method found for %s in %s ???\n", monthlyPeriodProperties[0], BudgetConstructionMonthly.class.getName()), ex);
diagnosticCounters.writeDiagnosticCounters();
throw new RuntimeException(ex);
}
if (!(monthlyAmount.isZero())) {
newRow.setTransactionLedgerEntrySequenceNumber(daoGlobalVariables.getNextSequenceNumber(incomingDocumentNumber));
newRow.setUniversityFiscalPeriodCode(monthlyPeriodProperties[1]); // accounting period
newRow.setTransactionLedgerEntryAmount(monthlyAmount.kualiDecimalValue()); // amount
getPersistenceBrokerTemplate().store(newRow);
diagnosticCounters.increaseBudgetConstructionMonthlyBudgetWritten();
}
}
}
/*******************************************************************************************************************************
* * This section build the list of accounts that SHOULD NOT be loaded to the general ledger * (This may seem strange--why build
* a budget if you aren't going to load it--but in the FIS the budget * loaded to payroll as well. For grant accounts, the FIS
* allowed people to set salaries for the new year * so those would load to payroll. But, the actual budget for a grant account
* was not necessarily done on a * fiscal year basis, and was not part of the university's operating budget, so there was no
* "base budget" * for a grant account to load to the general ledger.) * (1) We will inhibit the load to the general ledger of
* all accounts in given sub fund groups * (2) (We WILL allow closed accounts to load. There should not be any--they should have
* been filtered * out in the budget application, but if there are, they will be caught by the GL scrubber. We want * people to
* have a record of this kind of load failure, so it can be corrected. * * *
******************************************************************************************************************************/
/**
* get a list of accounts that should not be loaded from the budget to the General Ledger
*
* @return hashset of accounts NOT to be loaded
*/
protected HashSet<String> getAccountsNotToBeLoaded() {
HashSet<String> bannedAccounts;
/**
* list of subfunds which should not be loaded
*/
HashSet<String> bannedSubFunds = getSubFundsNotToBeLoaded();
/**
* query for the subfund property for each account in the DB
*/
ReportQueryByCriteria queryID = new ReportQueryByCriteria(Account.class, org.apache.ojb.broker.query.ReportQueryByCriteria.CRITERIA_SELECT_ALL);
queryID.setAttributes(new String[] { KFSPropertyConstants.ACCOUNT_NUMBER, KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, KFSPropertyConstants.SUB_FUND_GROUP_CODE });
bannedAccounts = new HashSet<String>(hashCapacity(queryID));
/**
* use the results to build a hash set of accounts which should NOT be loaded (that is, their subfunds are in the list of
* subfunds we do not want
*/
Iterator accountProperties = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(queryID);
while (accountProperties.hasNext()) {
Object[] selectListValues = (Object[]) accountProperties.next();
/**
* we will add an account/chart to the list if it has a no-load subfundgroup
*/
if (bannedSubFunds.contains((String) selectListValues[2])) {
/**
* hash content is account number concatenated with chart (the key of the chart of accounts table)
*/
bannedAccounts.add(((String) selectListValues[0]) + ((String) selectListValues[1]));
}
}
return bannedAccounts;
}
/**
* build a hash set of subfunds whose accounts should NOT be loaded this can be done by either a list of FUND groups and/or a
* list of subfund groups
*
* @see org.kuali.kfs.module.bc.BCConstants to initialize the String[] array(s) as desired
* @return list of subfunds whose accounts will NOT be loaded
*/
protected HashSet<String> getSubFundsNotToBeLoaded() {
HashSet<String> bannedSubFunds;
if (BCConstants.NO_BC_GL_LOAD_FUND_GROUPS.size() != 0) {
/**
* look for subfunds in the banned fund groups
*/
Criteria criteriaID = new Criteria();
criteriaID.addIn(KFSPropertyConstants.FUND_GROUP_CODE, BCConstants.NO_BC_GL_LOAD_FUND_GROUPS);
ReportQueryByCriteria queryID = new ReportQueryByCriteria(SubFundGroup.class, criteriaID);
queryID.setAttributes(new String[] { KFSPropertyConstants.SUB_FUND_GROUP_CODE });
/**
* set the size of the hashset based on the number of rows the query will return
*/
bannedSubFunds = new HashSet<String>(hashCapacity(queryID) + BCConstants.NO_BC_GL_LOAD_SUBFUND_GROUPS.size());
Iterator subfundsForBannedFunds = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(queryID);
/**
* add the subfunds for the fund groups to be skipped to the hash set
*/
while (subfundsForBannedFunds.hasNext()) {
bannedSubFunds.add((String) ((Object[]) subfundsForBannedFunds.next())[0]);
}
}
else {
bannedSubFunds = new HashSet<String>(BCConstants.NO_BC_GL_LOAD_SUBFUND_GROUPS.size() + 1);
}
/**
* now add the specific sub funds we don't want from the hard-coded array in BCConstants to the hash set
*/
Iterator<String> additionalBannedSubFunds = BCConstants.NO_BC_GL_LOAD_SUBFUND_GROUPS.iterator();
while (additionalBannedSubFunds.hasNext()) {
bannedSubFunds.add(additionalBannedSubFunds.next());
}
return bannedSubFunds;
}
/*******************************************************************************************************************************
* This section sets all the accounting periods for the coming year to open. * The monthly budget will load by accounting
* period. If some are not open, some monthly rows will error * out in the scrubber. Current FIS procedure is to prevent this
* from happening, by opening all the * accounting periods and letting the university chart manager close them after the budget
* is loaded if that * is desirable for some reason. If an institution prefers another policy, just don't call these methods. *
* But, even if we let the scrubber fail, there will be no way to load the monthly rows from the error tables* unless the
* corresponding accounting periods are open. *
******************************************************************************************************************************/
/**
* this method makes sure all accounting periods inn the target fiscal year are open
*
* @param request fiscal year (or other fiscal period) which is the TARGET of the load
*/
protected void openAllAccountingPeriods(Integer requestYear) {
Criteria criteriaID = new Criteria();
criteriaID.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, requestYear);
criteriaID.addNotEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_PERIOD_STATUS_CODE, "Y");
QueryByCriteria queryID = new QueryByCriteria(AccountingPeriod.class, criteriaID);
Iterator<AccountingPeriod> unopenPeriods = getPersistenceBrokerTemplate().getIteratorByQuery(queryID);
int periodsOpened = 0;
while (unopenPeriods.hasNext()) {
AccountingPeriod periodToOpen = unopenPeriods.next();
periodToOpen.setActive(true);
getPersistenceBrokerTemplate().store(periodToOpen);
periodsOpened = periodsOpened + 1;
}
LOG.warn(String.format("\n\naccounting periods for %d changed to open status: %d", requestYear, new Integer(periodsOpened)));
}
/*******************************************************************************************************************************
* These two classes are containers so we can make certain variables accessible to all methods without making them global to the
* * outer class and without cluttering up the method signatures. *
******************************************************************************************************************************/
/**
* This class keeps a set of counters and provides a method to print them out This allows us to set up thread-local counters in
* the unlikely event this code is run by more than one thread
*/
protected class DiagnosticCounters {
long budgetConstructionPendingGeneralLedgerRead = 0;
long budgetConstructionPendingGeneralLedgerSkipped = 0;
long generalLedgerBaseBudgetWritten = 0;
long generalLedgerCurrentBudgetWritten = 0;
long budgetConstructionMonthlyBudgetRead = 0;
long budgetConstructionMonthlyBudgetSkipped = 0;
long budgetConstructionMonthlyBudgetWritten = 0;
public void increaseBudgetConstructionPendingGeneralLedgerRead() {
budgetConstructionPendingGeneralLedgerRead++;
}
public void increaseBudgetConstructionPendingGeneralLedgerSkipped() {
budgetConstructionPendingGeneralLedgerSkipped++;
}
public void increaseGeneralLedgerBaseBudgetWritten() {
generalLedgerBaseBudgetWritten++;
}
public void increasGenneralLedgerCurrentBudgetWritten() {
generalLedgerCurrentBudgetWritten++;
}
public void increaseBudgetConstructionMonthlyBudgetRead() {
budgetConstructionMonthlyBudgetRead++;
}
public void increaseBudgetConstructionMonthlyBudgetSkipped() {
budgetConstructionMonthlyBudgetSkipped++;
}
public void increaseBudgetConstructionMonthlyBudgetWritten() {
budgetConstructionMonthlyBudgetWritten++;
}
public void writeDiagnosticCounters() {
LOG.warn(String.format("\n\nPending Budget Construction General Ledger Load\n"));
LOG.warn(String.format("\n pending budget construction GL rows read: %,d", budgetConstructionPendingGeneralLedgerRead));
LOG.warn(String.format("\n pending budget construction GL rows skipped: %,d", budgetConstructionPendingGeneralLedgerSkipped));
LOG.warn(String.format("\n\n base budget rows written: %,d", generalLedgerBaseBudgetWritten));
LOG.warn(String.format("\n current budget rows written: %,d", generalLedgerCurrentBudgetWritten));
LOG.warn(String.format("\n\n pending budget construction monthly rows read: %,d", budgetConstructionMonthlyBudgetRead));
LOG.warn(String.format("\n pending budget construction monthly rows skipped: %,d", budgetConstructionMonthlyBudgetSkipped));
LOG.warn(String.format("\n pending budget construction monthly rows written: %,d", budgetConstructionMonthlyBudgetWritten));
}
}
/**
* This class allows us to create global variables and pass them around. This should make the code thread safe, in the unlikely
* event it is called by more than one thread. it also allows us to fetch constants and build datas stuctures from the DB once
* upon instantiation of this class, and make them available for the duration of the run
*
* @param requestYear
* @param <documentNumber, ledger sequence number> HashMap
* @param current SQL Date (which will be the transaction date in the general ledger entry rows we create)
* @param the "financial system Origination Code" for this database
*/
protected class DaoGlobalVariables {
private Integer requestYear;
private HashMap<String, Integer> entrySequenceNumber;
private Date transactionDate;
private String financialSystemOriginationCode;
private HashSet<String> accountsNotToBeLoaded;
public DaoGlobalVariables(Integer requestYear, Date currentSqlDate, String financialSystemOriginationCode) {
this.requestYear = requestYear;
this.entrySequenceNumber = entrySequenceNumber(requestYear);
this.transactionDate = currentSqlDate;
this.financialSystemOriginationCode = financialSystemOriginationCode;
this.accountsNotToBeLoaded = getAccountsNotToBeLoaded();
}
public Integer getRequestYear() {
return this.requestYear;
}
/**
* return the next available sequence number for the input key and update "next available"
*/
public Integer getNextSequenceNumber(String seqKey) {
Integer newSeqNumber = entrySequenceNumber.get(seqKey);
entrySequenceNumber.put(seqKey, new Integer(newSeqNumber.intValue() + 1));
return newSeqNumber;
}
public Date getTransactionDate() {
return this.transactionDate;
}
public String getFinancialSystemOriginationcode() {
return this.financialSystemOriginationCode;
}
public boolean shouldThisAccountLoad(String accountAndChart) {
return (!accountsNotToBeLoaded.contains(accountAndChart));
}
}
}