/*
* 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.ld.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ojb.broker.query.ReportQueryByCriteria;
import org.kuali.kfs.module.ld.businessobject.LedgerBalance;
import org.kuali.kfs.sys.KFSPropertyConstants;
import org.kuali.kfs.sys.ObjectUtil;
/**
* Utility class for helping DAOs deal with building queries for the consolidation option
*/
public class ConsolidationUtil {
private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory.getLog(ConsolidationUtil.class);
/**
* wrap the given field name with SQL function "sum"
*
* @param fieldName the given field name
* @return the wrapped field name with SQL function "sum"
*/
public static final String sum(String fieldName) {
return "sum(" + fieldName + ")";
}
/**
* This method builds the atrribute list used by balance searching
*
* @param extendedFields extra fields
* @return List an attribute list
*/
public static Collection<String> buildAttributeCollection(String... extendedFields) {
return buildAttributeCollection(Arrays.asList(extendedFields));
}
/**
* This method builds the atrribute list used by balance searching
*
* @param extendedFields extra fields
* @return Collection an attribute list
*/
public static Collection<String> buildAttributeCollection(Collection<String> extendedFields) {
Collection<String> attributeList = buildGroupByCollection();
attributeList.add(sum(KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT));
attributeList.add(sum(KFSPropertyConstants.FINANCIAL_BEGINNING_BALANCE_LINE_AMOUNT));
attributeList.add(sum(KFSPropertyConstants.CONTRACTS_GRANTS_BEGINNING_BALANCE_AMOUNT));
// add the entended elements into the list
attributeList.addAll(extendedFields);
return attributeList;
}
/**
* Utility class for helping DAOs deal with building queries for the consolidation option
*
* @param query Query to make consolidated
* @param extraFields fields included in the query
* @param ignoredFields to omit from the query
*/
public static void buildConsolidatedQuery(ReportQueryByCriteria query, String... extraFields) {
Collection<String> attributeList = buildAttributeCollection(extraFields);
Collection<String> groupByList = buildGroupByCollection();
attributeList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
groupByList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
attributeList.remove(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE);
groupByList.remove(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE);
attributeList.remove(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE);
groupByList.remove(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE);
// set the selection attributes
String[] attributes = (String[]) attributeList.toArray(new String[attributeList.size()]);
query.setAttributes(attributes);
if (LOG.isDebugEnabled()) {
LOG.debug("Built Attributes for Query: " + attributeList.toString());
}
// add the group criteria into the selection statement
String[] groupBy = (String[]) groupByList.toArray(new String[attributeList.size()]);
query.addGroupBy(groupBy);
if (LOG.isDebugEnabled()) {
LOG.debug("Built GroupBy for Query: " + groupByList.toString());
}
}
/**
* This method builds group by attribute list used by balance searching
*
* @return extraFields
* @return Collection an group by attribute list
*/
public static Collection<String> buildGroupByCollection(Collection<String> extraFields) {
Collection<String> retval = new ArrayList();
retval.add(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
retval.add(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
retval.add(KFSPropertyConstants.ACCOUNT_NUMBER);
retval.add(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
retval.add(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE);
retval.add(KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
retval.add(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE);
retval.add(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE);
retval.add(KFSPropertyConstants.EMPLID);
retval.add(KFSPropertyConstants.POSITION_NUMBER);
retval.addAll(extraFields);
return retval;
}
/**
* This method builds group by attribute list used by balance searching
*
* @return extraFields
* @return Collection an group by attribute list
*/
public static Collection<String> buildGroupByCollection(String... extraFields) {
return buildGroupByCollection(Arrays.asList(extraFields));
}
/**
* Consolidates a collection of actual balances with a collection of A2 balances. The A2 balances are changed to AC, then
* matched by balance key with balances from the actual collection.
*
* @param actualBalances - collection of actual balances (consolidatedBalanceTypeCode)
* @param effortBalances - collection of effort balances ('A2')
* @param consolidatedBalanceTypeCode - balance type to change A2 records to
* @return Collection<LedgerBalance> - collection with consolidated balance records
*/
public static Collection<LedgerBalance> consolidateA2Balances(Collection<LedgerBalance> actualBalances, Collection<LedgerBalance> effortBalances, String consolidatedBalanceTypeCode, List<String> consolidationKeyList) {
Map<String, LedgerBalance> consolidatedBalanceMap = new HashMap<String, LedgerBalance>();
for (LedgerBalance effortBalance : effortBalances) {
effortBalance.setBalanceTypeCode(consolidatedBalanceTypeCode);
String consolidationKey = ObjectUtil.buildPropertyMap(effortBalance, consolidationKeyList).toString();
if(consolidatedBalanceMap.containsKey(consolidationKey)) {
LedgerBalance ledgerBalance = consolidatedBalanceMap.get(consolidationKey);
sumLedgerBalances(ledgerBalance, effortBalance);
}
else {
consolidatedBalanceMap.put(consolidationKey, effortBalance);
}
}
for (LedgerBalance actualBalance : actualBalances) {
actualBalance.setBalanceTypeCode(consolidatedBalanceTypeCode);
String consolidationKey = ObjectUtil.buildPropertyMap(actualBalance, consolidationKeyList).toString();
if(consolidatedBalanceMap.containsKey(consolidationKey)) {
LedgerBalance ledgerBalance = consolidatedBalanceMap.get(consolidationKey);
sumLedgerBalances(ledgerBalance, actualBalance);
}
else {
consolidatedBalanceMap.put(consolidationKey, actualBalance);
}
}
return consolidatedBalanceMap.values();
}
/**
* Adds the amounts fields of the second balance record to the first.
*
* @param balance1 - LedgerBalance
* @param balance2 - LedgerBalance
*/
public static void sumLedgerBalances(LedgerBalance balance1, LedgerBalance balance2) {
balance1.setAccountLineAnnualBalanceAmount(balance1.getAccountLineAnnualBalanceAmount().add(balance2.getAccountLineAnnualBalanceAmount()));
balance1.setBeginningBalanceLineAmount(balance1.getBeginningBalanceLineAmount().add(balance2.getBeginningBalanceLineAmount()));
balance1.setContractsGrantsBeginningBalanceAmount(balance1.getContractsGrantsBeginningBalanceAmount().add(balance2.getContractsGrantsBeginningBalanceAmount()));
balance1.setMonth1Amount(balance1.getMonth1Amount().add(balance2.getMonth1Amount()));
balance1.setMonth2Amount(balance1.getMonth2Amount().add(balance2.getMonth2Amount()));
balance1.setMonth3Amount(balance1.getMonth3Amount().add(balance2.getMonth3Amount()));
balance1.setMonth4Amount(balance1.getMonth4Amount().add(balance2.getMonth4Amount()));
balance1.setMonth5Amount(balance1.getMonth5Amount().add(balance2.getMonth5Amount()));
balance1.setMonth6Amount(balance1.getMonth6Amount().add(balance2.getMonth6Amount()));
balance1.setMonth7Amount(balance1.getMonth7Amount().add(balance2.getMonth7Amount()));
balance1.setMonth8Amount(balance1.getMonth8Amount().add(balance2.getMonth8Amount()));
balance1.setMonth9Amount(balance1.getMonth9Amount().add(balance2.getMonth9Amount()));
balance1.setMonth10Amount(balance1.getMonth10Amount().add(balance2.getMonth10Amount()));
balance1.setMonth11Amount(balance1.getMonth11Amount().add(balance2.getMonth11Amount()));
balance1.setMonth12Amount(balance1.getMonth12Amount().add(balance2.getMonth12Amount()));
balance1.setMonth13Amount(balance1.getMonth13Amount().add(balance2.getMonth13Amount()));
}
/**
* wrap the attribute name based on the given flag: isAttributeNameNeeded
*
* @param attributeName the given attribute name
* @param isAttributeNameNeeded the flag that indicates if the attribute name needs to be wrapped with consolidation
* @return the attribute name as it is if isAttributeNameNeeded is true; otherwise, the attribute name wrapped with
* consolidation string
*/
public static String wrapAttributeName(String attributeName, boolean isAttributeNameNeeded) {
return isAttributeNameNeeded ? attributeName : ConsolidationUtil.sum(attributeName);
}
}