View Javadoc
1   /*
2    * The Kuali Financial System, a comprehensive financial management system for higher education.
3    * 
4    * Copyright 2005-2014 The Kuali Foundation
5    * 
6    * This program is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU Affero General Public License as
8    * published by the Free Software Foundation, either version 3 of the
9    * License, or (at your option) any later version.
10   * 
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU Affero General Public License for more details.
15   * 
16   * You should have received a copy of the GNU Affero General Public License
17   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  package org.kuali.kfs.gl.dataaccess.impl;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.commons.lang.StringUtils;
30  import org.apache.ojb.broker.query.Criteria;
31  import org.apache.ojb.broker.query.Query;
32  import org.apache.ojb.broker.query.QueryByCriteria;
33  import org.apache.ojb.broker.query.QueryFactory;
34  import org.apache.ojb.broker.query.ReportQueryByCriteria;
35  import org.kuali.kfs.coa.businessobject.Account;
36  import org.kuali.kfs.gl.GeneralLedgerConstants;
37  import org.kuali.kfs.gl.OJBUtility;
38  import org.kuali.kfs.gl.batch.service.FilteringBalanceIterator;
39  import org.kuali.kfs.gl.businessobject.Balance;
40  import org.kuali.kfs.gl.businessobject.CashBalance;
41  import org.kuali.kfs.gl.businessobject.Transaction;
42  import org.kuali.kfs.gl.dataaccess.BalanceDao;
43  import org.kuali.kfs.gl.dataaccess.LedgerBalanceBalancingDao;
44  import org.kuali.kfs.sys.KFSConstants;
45  import org.kuali.kfs.sys.KFSPropertyConstants;
46  import org.kuali.kfs.sys.businessobject.SystemOptions;
47  import org.kuali.kfs.sys.context.SpringContext;
48  import org.kuali.rice.core.api.parameter.ParameterEvaluator;
49  import org.kuali.rice.core.api.util.type.KualiDecimal;
50  import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb;
51  
52  /**
53   * An OJB implementation of BalanceDao
54   */
55  public class BalanceDaoOjb extends PlatformAwareDaoBaseOjb implements BalanceDao, LedgerBalanceBalancingDao {
56      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(BalanceDaoOjb.class);
57  
58      /**
59       * Does a ReportQuery to summarize GL balance data
60       *
61       * @param universityFiscalYear the fiscal year of balances to search for
62       * @param balanceTypeCodes a list of balance type codes of balances to search for
63       * @return iterator of reported on java.lang.Object arrays with the report data
64       * @see org.kuali.kfs.gl.dataaccess.BalanceDao#getGlSummary(int, java.util.List)
65       */
66      @Override
67      public Iterator<Object[]> getGlSummary(int universityFiscalYear, Collection<String> balanceTypeCodes) {
68          LOG.debug("getGlSummary() started");
69  
70          Criteria c = new Criteria();
71          c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, universityFiscalYear);
72          c.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, balanceTypeCodes);
73  
74          String[] attributes = new String[] { "account.subFundGroup.fundGroupCode", "sum(accountLineAnnualBalanceAmount)", "sum(beginningBalanceLineAmount)", "sum(contractsGrantsBeginningBalanceAmount)", "sum(month1Amount)", "sum(month2Amount)", "sum(month3Amount)", "sum(month4Amount)", "sum(month5Amount)", "sum(month6Amount)", "sum(month7Amount)", "sum(month8Amount)", "sum(month9Amount)", "sum(month10Amount)", "sum(month11Amount)", "sum(month12Amount)", "sum(month13Amount)" };
75  
76          String[] groupby = new String[] { "account.subFundGroup.fundGroupCode" };
77  
78          ReportQueryByCriteria query = new ReportQueryByCriteria(Balance.class, c);
79  
80          query.setAttributes(attributes);
81          query.addGroupBy(groupby);
82          query.addOrderByAscending("account.subFundGroup.fundGroupCode");
83  
84          return getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
85      }
86  
87      /**
88       * Queries the database for all the balances for a given fiscal year
89       *
90       * @param year the university fiscal year of balances to return
91       * @return an iterator over all balances for a given fiscal year
92       * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findBalancesForFiscalYear(java.lang.Integer)
93       */
94      @Override
95      public Iterator<Balance> findBalancesForFiscalYear(Integer year) {
96          LOG.debug("findBalancesForFiscalYear() started");
97  
98          Criteria c = new Criteria();
99          c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
100 
101         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
102         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
103         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
104         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
105         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
106         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
107         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
108         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
109 
110         return getPersistenceBrokerTemplate().getIteratorByQuery(query);
111     }
112 
113     /**
114      * Using values from the transaction as keys, lookup the balance the transaction would affect were it posted
115      *
116      * @t a transaction to look up the related balance for
117      * @return a Balance that the given transaction would affect
118      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#getBalanceByTransaction(org.kuali.kfs.gl.businessobject.Transaction)
119      */
120     @Override
121     public Balance getBalanceByTransaction(Transaction t) {
122         LOG.debug("getBalanceByTransaction() started");
123 
124         Criteria crit = new Criteria();
125         crit.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, t.getUniversityFiscalYear());
126         crit.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, t.getChartOfAccountsCode());
127         crit.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, t.getAccountNumber());
128         crit.addEqualTo(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, t.getSubAccountNumber());
129         crit.addEqualTo(KFSPropertyConstants.OBJECT_CODE, t.getFinancialObjectCode());
130         crit.addEqualTo(KFSPropertyConstants.SUB_OBJECT_CODE, t.getFinancialSubObjectCode());
131         crit.addEqualTo(KFSPropertyConstants.BALANCE_TYPE_CODE, t.getFinancialBalanceTypeCode());
132         crit.addEqualTo(KFSPropertyConstants.OBJECT_TYPE_CODE, t.getFinancialObjectTypeCode());
133 
134         QueryByCriteria qbc = QueryFactory.newQuery(Balance.class, crit);
135         return (Balance) getPersistenceBrokerTemplate().getObjectByQuery(qbc);
136     }
137 
138     /**
139      * This method adds to the given criteria if the given collection is non-empty. It uses an EQUALS if there is exactly one
140      * element in the collection; otherwise, its uses an IN
141      *
142      * @param criteria - the criteria that might have a criterion appended
143      * @param name - name of the attribute
144      * @param collection - the collection to inspect
145      */
146     protected void criteriaBuilder(Criteria criteria, String name, Collection collection) {
147         criteriaBuilderHelper(criteria, name, collection, false);
148     }
149 
150     /**
151      * Similar to criteriaBuilder, this adds a negative criterion (NOT EQUALS, NOT IN)
152      *
153      * @param criteria - the criteria that might have a criterion appended
154      * @param name - name of the attribute
155      * @param collection - the collection to inspect
156      */
157     protected void negatedCriteriaBuilder(Criteria criteria, String name, Collection collection) {
158         criteriaBuilderHelper(criteria, name, collection, true);
159     }
160 
161 
162     /**
163      * This method provides the implementation for the conveniences methods criteriaBuilder & negatedCriteriaBuilder
164      *
165      * @param criteria - the criteria that might have a criterion appended
166      * @param name - name of the attribute
167      * @param collection - the collection to inspect
168      * @param negate - the criterion will be negated (NOT EQUALS, NOT IN) when this is true
169      */
170     protected void criteriaBuilderHelper(Criteria criteria, String name, Collection collection, boolean negate) {
171         if (collection != null) {
172             int size = collection.size();
173             if (size == 1) {
174                 if (negate) {
175                     criteria.addNotEqualTo(name, collection.iterator().next());
176                 }
177                 else {
178                     criteria.addEqualTo(name, collection.iterator().next());
179                 }
180             }
181             if (size > 1) {
182                 if (negate) {
183                     criteria.addNotIn(name, collection);
184                 }
185                 else {
186                     criteria.addIn(name, collection);
187 
188                 }
189             }
190         }
191 
192     }
193 
194     /**
195      * Build a query based on all the parameters, and return an Iterator of all Balances from the database that qualify
196      *
197      * @param account the account of balances to find
198      * @param fiscalYear the fiscal year of balances to find
199      * @param includedObjectCodes a Collection of object codes found balances should have one of
200      * @param excludedObjectCodes a Collection of object codes found balances should not have one of
201      * @param objectTypeCodes a Collection of object type codes found balances should have one of
202      * @param balanceTypeCodes a Collection of balance type codes found balances should have one of
203      * @return an Iterator of Balances
204      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findBalances(org.kuali.kfs.coa.businessobject.Account, java.lang.Integer,
205      *      java.util.Collection, java.util.Collection, java.util.Collection, java.util.Collection)
206      */
207     @Override
208     public Iterator<Balance> findBalances(Account account, Integer fiscalYear, Collection includedObjectCodes, Collection excludedObjectCodes, Collection objectTypeCodes, Collection balanceTypeCodes) {
209         LOG.debug("findBalances() started");
210 
211         Criteria criteria = new Criteria();
212 
213         criteria.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, account.getAccountNumber());
214         criteria.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, account.getChartOfAccountsCode());
215 
216         criteria.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, fiscalYear);
217 
218         criteriaBuilder(criteria, GeneralLedgerConstants.ColumnNames.OBJECT_TYPE_CODE, objectTypeCodes);
219         criteriaBuilder(criteria, GeneralLedgerConstants.ColumnNames.BALANCE_TYPE_CODE, balanceTypeCodes);
220         criteriaBuilder(criteria, GeneralLedgerConstants.ColumnNames.OBJECT_CODE, includedObjectCodes);
221         negatedCriteriaBuilder(criteria, GeneralLedgerConstants.ColumnNames.OBJECT_CODE, excludedObjectCodes);
222 
223         ReportQueryByCriteria query = new ReportQueryByCriteria(Balance.class, criteria);
224 
225         // returns an iterator of all matching balances
226         Iterator balances = getPersistenceBrokerTemplate().getIteratorByQuery(query);
227         return balances;
228     }
229 
230     /**
231      * Using the given fieldValues as keys, return all cash balance records. The results will be limited to the system lookup
232      * results limit.
233      *
234      * @param fieldValues the input fields and values
235      * @param isConsolidated consolidation option is applied or not
236      * @return the records of cash balance entries
237      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#lookupCashBalance(Map, boolean, List)
238      */
239     @Override
240     public Iterator<Balance> lookupCashBalance(Map fieldValues, boolean isConsolidated, Collection<String> encumbranceBalanceTypes) {
241         LOG.debug("findCashBalance() started");
242 
243         Query query = this.getCashBalanceQuery(fieldValues, isConsolidated, encumbranceBalanceTypes);
244         OJBUtility.limitResultSize(query);
245         return getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
246     }
247 
248     /**
249      * Get the number of detailed cash balance records that would be returned, were we to do a query based on the given fieldValues
250      *
251      * @param fieldValues the input fields and values
252      * @param isConsolidated consolidation option is applied or not
253      * @return the size collection of cash balance entry groups
254      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#getDetailedCashBalanceRecordCount(Map, List)
255      */
256     @Override
257     public Integer getDetailedCashBalanceRecordCount(Map fieldValues, Collection<String> encumbranceBalanceTypes) {
258         LOG.debug("getDetailedCashBalanceRecordCount() started");
259 
260         Query query = this.getCashBalanceQuery(fieldValues, false, encumbranceBalanceTypes);
261         return getPersistenceBrokerTemplate().getCount(query);
262     }
263 
264     /**
265      * Given a map of keys, return all of the report data about qualifying cash balances
266      *
267      * @param fieldValues the input fields and values
268      * @return the size collection of cash balance entry groups
269      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#getConsolidatedCashBalanceRecordCount(Map, List)
270      */
271     @Override
272     public int getConsolidatedCashBalanceRecordCount(Map fieldValues, Collection<String> encumbranceBalanceTypes) {
273         LOG.debug("getCashBalanceRecordCount() started");
274 
275         ReportQueryByCriteria query = this.getCashBalanceCountQuery(fieldValues, encumbranceBalanceTypes);
276         return getPersistenceBrokerTemplate().getCount(query);
277     }
278 
279     /**
280      * Given a map of values, build a query out of those and find all the balances that qualify
281      *
282      * @param fieldValues a Map of fieldValues to use as keys in the query
283      * @param isConsolidated should the results be consolidated?
284      * @return an Iterator of Balances
285      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findBalance(java.util.Map, boolean)
286      */
287     @Override
288     public Iterator<Balance> findBalance(Map fieldValues, boolean isConsolidated, Collection<String> encumbranceBalanceTypes) {
289         LOG.debug("findBalance() started");
290 
291         Query query = this.getBalanceQuery(fieldValues, isConsolidated, encumbranceBalanceTypes);
292         OJBUtility.limitResultSize(query);
293 
294         if (isConsolidated) {
295             return getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
296         }
297         return getPersistenceBrokerTemplate().getIteratorByQuery(query);
298     }
299 
300     /**
301      * Given a Map of keys to use as a query, if we performed that query as a consolidated query... how many records would we get
302      * back?
303      *
304      * @param fieldValues a Map of values to use as keys to build the query
305      * @return an Iterator of counts...
306      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#getConsolidatedBalanceRecordCount(Map, List)
307      */
308     @Override
309     public Iterator getConsolidatedBalanceRecordCount(Map fieldValues, Collection<String> encumbranceBalanceTypes) {
310         LOG.debug("getBalanceRecordCount() started");
311 
312         ReportQueryByCriteria query = this.getBalanceCountQuery(fieldValues, encumbranceBalanceTypes);
313         return getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
314     }
315 
316     /**
317      * Builds a query for cash balances, based on the given field values
318      *
319      * @param fieldValues a map of keys to use when building the query
320      * @return an OJB ReportQuery to use as the query
321      */
322     protected ReportQueryByCriteria getCashBalanceCountQuery(Map fieldValues, Collection<String> encumbranceBalanceTypes) {
323         Criteria criteria = buildCriteriaFromMap(fieldValues, new CashBalance(), encumbranceBalanceTypes);
324         criteria.addEqualTo(KFSPropertyConstants.BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_ACTUAL);
325         criteria.addEqualToField("chart.financialCashObjectCode", KFSPropertyConstants.OBJECT_CODE);
326 
327         ReportQueryByCriteria query = QueryFactory.newReportQuery(CashBalance.class, criteria);
328 
329         List groupByList = buildGroupByList();
330         groupByList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
331         groupByList.remove(KFSPropertyConstants.SUB_OBJECT_CODE);
332         groupByList.remove(KFSPropertyConstants.OBJECT_TYPE_CODE);
333 
334         // add the group criteria into the selection statement
335         String[] groupBy = (String[]) groupByList.toArray(new String[groupByList.size()]);
336         query.addGroupBy(groupBy);
337 
338         return query;
339     }
340 
341     /**
342      * build the query for cash balance search
343      *
344      * @param fieldValues Map of keys to use for the query
345      * @param isConsolidated should the results be consolidated?
346      * @return the OJB query to perform
347      */
348     protected Query getCashBalanceQuery(Map fieldValues, boolean isConsolidated, Collection<String> encumbranceBalanceTypes) {
349         Criteria criteria = buildCriteriaFromMap(fieldValues, new CashBalance(), encumbranceBalanceTypes);
350         criteria.addEqualTo(KFSPropertyConstants.BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_ACTUAL);
351         criteria.addEqualToField("chart.financialCashObjectCode", KFSPropertyConstants.OBJECT_CODE);
352 
353         ReportQueryByCriteria query = QueryFactory.newReportQuery(CashBalance.class, criteria);
354         List attributeList = buildAttributeList(false);
355         List groupByList = buildGroupByList();
356 
357         // if consolidated, then ignore the following fields
358         if (isConsolidated) {
359             attributeList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
360             groupByList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
361             attributeList.remove(KFSPropertyConstants.SUB_OBJECT_CODE);
362             groupByList.remove(KFSPropertyConstants.SUB_OBJECT_CODE);
363             attributeList.remove(KFSPropertyConstants.OBJECT_TYPE_CODE);
364             groupByList.remove(KFSPropertyConstants.OBJECT_TYPE_CODE);
365         }
366 
367         // add the group criteria into the selection statement
368         String[] groupBy = (String[]) groupByList.toArray(new String[groupByList.size()]);
369         query.addGroupBy(groupBy);
370 
371         // set the selection attributes
372         String[] attributes = (String[]) attributeList.toArray(new String[attributeList.size()]);
373         query.setAttributes(attributes);
374 
375         return query;
376     }
377 
378     /**
379      * build the query for balance search
380      *
381      * @param fieldValues Map of keys to use for the query
382      * @param isConsolidated should the results be consolidated?
383      * @return an OJB query to perform
384      */
385     protected Query getBalanceQuery(Map fieldValues, boolean isConsolidated, Collection<String> encumbranceBalanceTypes) {
386         LOG.debug("getBalanceQuery(Map, boolean) started");
387 
388         Criteria criteria = buildCriteriaFromMap(fieldValues, new Balance(), encumbranceBalanceTypes);
389         ReportQueryByCriteria query = QueryFactory.newReportQuery(Balance.class, criteria);
390 
391         // if consolidated, then ignore subaccount number and balance type code
392         if (isConsolidated) {
393             List attributeList = buildAttributeList(true);
394             List groupByList = buildGroupByList();
395 
396             // ignore subaccount number, sub object code and object type code
397             attributeList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
398             groupByList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
399             attributeList.remove(KFSPropertyConstants.SUB_OBJECT_CODE);
400             groupByList.remove(KFSPropertyConstants.SUB_OBJECT_CODE);
401             attributeList.remove(KFSPropertyConstants.OBJECT_TYPE_CODE);
402             groupByList.remove(KFSPropertyConstants.OBJECT_TYPE_CODE);
403 
404             // set the selection attributes
405             String[] attributes = (String[]) attributeList.toArray(new String[attributeList.size()]);
406             query.setAttributes(attributes);
407 
408             // add the group criteria into the selection statement
409             String[] groupBy = (String[]) groupByList.toArray(new String[groupByList.size()]);
410             query.addGroupBy(groupBy);
411         }
412 
413         return query;
414     }
415 
416     /**
417      * build the query for balance search
418      *
419      * @param fieldValues Map of keys to use for the query
420      * @return an OJB ReportQuery to perform
421      */
422     protected ReportQueryByCriteria getBalanceCountQuery(Map fieldValues, Collection<String> encumbranceBalanceTypes) {
423         Criteria criteria = buildCriteriaFromMap(fieldValues, new Balance(), encumbranceBalanceTypes);
424         ReportQueryByCriteria query = QueryFactory.newReportQuery(Balance.class, criteria);
425 
426         // set the selection attributes
427         query.setAttributes(new String[] { "count(*)" });
428 
429         List groupByList = buildGroupByList();
430         groupByList.remove(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
431         groupByList.remove(KFSPropertyConstants.SUB_OBJECT_CODE);
432         groupByList.remove(KFSPropertyConstants.OBJECT_TYPE_CODE);
433 
434         // add the group criteria into the selection statement
435         String[] groupBy = (String[]) groupByList.toArray(new String[groupByList.size()]);
436         query.addGroupBy(groupBy);
437         return query;
438     }
439 
440     /**
441      * This method builds the query criteria based on the input field map
442      *
443      * @param fieldValues Map of keys to use for the query
444      * @param balance this really usen't used in the method
445      * @return a query criteria
446      */
447     protected Criteria buildCriteriaFromMap(Map fieldValues, Balance balance, Collection<String> encumbranceBalanceTypes) {
448         Map localFieldValues = new HashMap();
449         localFieldValues.putAll(fieldValues);
450 
451         Criteria criteria = new Criteria();
452 
453         // handle encumbrance balance type
454         String propertyName = KFSPropertyConstants.BALANCE_TYPE_CODE;
455         if (localFieldValues.containsKey(propertyName)) {
456             String propertyValue = (String) localFieldValues.get(propertyName);
457             if (KFSConstants.AGGREGATE_ENCUMBRANCE_BALANCE_TYPE_CODE.equals(propertyValue)) {
458                 localFieldValues.remove(KFSPropertyConstants.BALANCE_TYPE_CODE);
459 
460                 criteria.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, encumbranceBalanceTypes);
461             }
462         }
463 
464         criteria.addAndCriteria(OJBUtility.buildCriteriaFromMap(localFieldValues, balance));
465         return criteria;
466     }
467 
468     /**
469      * This method builds the atrribute list used by balance searching
470      *
471      * @param isExtended should we add the attributes to sum each of the monthly totals?
472      * @return List an attribute list
473      */
474     protected List<String> buildAttributeList(boolean isExtended) {
475         List attributeList = this.buildGroupByList();
476 
477         attributeList.add("sum(accountLineAnnualBalanceAmount)");
478         attributeList.add("sum(beginningBalanceLineAmount)");
479         attributeList.add("sum(contractsGrantsBeginningBalanceAmount)");
480 
481         // add the entended elements into the list
482         if (isExtended) {
483             attributeList.add("sum(month1Amount)");
484             attributeList.add("sum(month2Amount)");
485             attributeList.add("sum(month3Amount)");
486             attributeList.add("sum(month4Amount)");
487             attributeList.add("sum(month5Amount)");
488             attributeList.add("sum(month6Amount)");
489             attributeList.add("sum(month7Amount)");
490             attributeList.add("sum(month8Amount)");
491             attributeList.add("sum(month9Amount)");
492             attributeList.add("sum(month10Amount)");
493             attributeList.add("sum(month11Amount)");
494             attributeList.add("sum(month12Amount)");
495             attributeList.add("sum(month13Amount)");
496         }
497         return attributeList;
498     }
499 
500     /**
501      * This method builds group by attribute list used by balance searching
502      *
503      * @return List an group by attribute list
504      */
505     protected List<String> buildGroupByList() {
506         List attributeList = new ArrayList();
507 
508         attributeList.add(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
509         attributeList.add(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
510         attributeList.add(KFSPropertyConstants.ACCOUNT_NUMBER);
511         attributeList.add(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
512         attributeList.add(KFSPropertyConstants.BALANCE_TYPE_CODE);
513         attributeList.add(KFSPropertyConstants.OBJECT_CODE);
514         attributeList.add(KFSPropertyConstants.SUB_OBJECT_CODE);
515         attributeList.add(KFSPropertyConstants.OBJECT_TYPE_CODE);
516 
517         return attributeList;
518     }
519 
520     /**
521      * Since SubAccountNumber, SubObjectCode, and ObjectType are all part of the primary key of Balance, you're guaranteed to get
522      * one of those records when you call this method. Let's hope the right one.
523      *
524      * @param universityFiscalYear the fiscal year of the CB balance to return
525      * @param chartOfAccountsCode the chart of the accounts code of the CB balanes to return
526      * @param accountNumber the account number of the CB balance to return
527      * @param objectCode the object code of the CB balance to return
528      * @return the CB Balance record
529      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#getCurrentBudgetForObjectCode(java.lang.Integer, java.lang.String,
530      *      java.lang.String, java.lang.String)
531      */
532     @Override
533     public Balance getCurrentBudgetForObjectCode(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String objectCode) {
534         LOG.debug("getCurrentBudgetForObjectCode() started");
535 
536         Criteria crit = new Criteria();
537         crit.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, universityFiscalYear);
538         crit.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartOfAccountsCode);
539         crit.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, accountNumber);
540         crit.addEqualTo(KFSPropertyConstants.OBJECT_CODE, objectCode);
541         crit.addEqualTo(KFSPropertyConstants.BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_CURRENT_BUDGET);
542 
543         QueryByCriteria qbc = QueryFactory.newQuery(Balance.class, crit);
544         return (Balance) getPersistenceBrokerTemplate().getObjectByQuery(qbc);
545     }
546 
547     /**
548      * Find all matching account balances.
549      *
550      * @param universityFiscalYear the university fiscal year of balances to return
551      * @param chartOfAccountsCode the chart of accounts code of balances to return
552      * @param accountNumber the account number of balances to return
553      * @return balances sorted by object code
554      */
555     @Override
556     public Iterator<Balance> findAccountBalances(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber) {
557         LOG.debug("findAccountBalances() started");
558         return this.findAccountBalances(universityFiscalYear, chartOfAccountsCode, accountNumber, KFSConstants.SF_TYPE_OBJECT);
559     }
560 
561     /**
562      * Find all matching account balances. The Sufficient funds code is used to determine the sort of the results.
563      *
564      * @param universityFiscalYear the university fiscal year of balances to return
565      * @param chartOfAccountsCode the chart of accounts code of balances to return
566      * @param accountNumber the account number of balances to return
567      * @param sfCode the sufficient funds code, used to sort on
568      * @return an Iterator of balances
569      */
570     @Override
571     public Iterator<Balance> findAccountBalances(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, String sfCode) {
572         LOG.debug("findAccountBalances() started");
573 
574         Criteria crit = new Criteria();
575         crit.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, universityFiscalYear);
576         crit.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartOfAccountsCode);
577         crit.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, accountNumber);
578 
579         QueryByCriteria qbc = QueryFactory.newQuery(Balance.class, crit);
580         if (KFSConstants.SF_TYPE_OBJECT.equals(sfCode)) {
581             qbc.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
582         }
583         else if (KFSConstants.SF_TYPE_LEVEL.equals(sfCode)) {
584             qbc.addOrderByAscending(GeneralLedgerConstants.BalanceInquiryDrillDowns.OBJECT_LEVEL_CODE);
585         }
586         else if (KFSConstants.SF_TYPE_CONSOLIDATION.equals(sfCode)) {
587             qbc.addOrderByAscending(GeneralLedgerConstants.BalanceInquiryDrillDowns.CONSOLIDATION_OBJECT_CODE);
588         }
589         return getPersistenceBrokerTemplate().getIteratorByQuery(qbc);
590     }
591 
592     /**
593      * Purge the sufficient funds balance table by year/chart
594      *
595      * @param chart the chart of balances to purge
596      * @param year the university fiscal year of balances to purge
597      */
598     @Override
599     public void purgeYearByChart(String chartOfAccountsCode, int year) {
600         LOG.debug("purgeYearByChart() started");
601 
602         Criteria criteria = new Criteria();
603         criteria.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, chartOfAccountsCode);
604         criteria.addLessThan(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, new Integer(year));
605 
606         getPersistenceBrokerTemplate().deleteByQuery(new QueryByCriteria(Balance.class, criteria));
607 
608         // This is required because if any deleted account balances are in the cache, deleteByQuery doesn't
609         // remove them from the cache so a future select will retrieve these deleted account balances from
610         // the cache and return them. Clearing the cache forces OJB to go to the database again.
611         getPersistenceBrokerTemplate().clearCache();
612     }
613 
614     /**
615      * Returns the count of balances for a given fiscal year; this method is used for year end job reporting
616      *
617      * @param year the university fiscal year to count balances for
618      * @return an int with the count of balances for that fiscal year
619      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#countBalancesForFiscalYear(java.lang.Integer)
620      */
621     @Override
622     public int countBalancesForFiscalYear(Integer year) {
623         LOG.debug("countBalancesForFiscalYear() started");
624 
625         Criteria c = new Criteria();
626         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
627         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
628 
629         return getPersistenceBrokerTemplate().getCount(query);
630     }
631 
632     /**
633      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#countBalancesForFiscalYear(java.lang.Integer, java.util.List)
634      */
635     @Override
636     public int countBalancesForFiscalYear(Integer year, List<String> charts) {
637         LOG.debug("countBalancesForFiscalYear(year, charts) started");
638 
639         Criteria c = new Criteria();
640         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
641         c.addIn(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, charts);
642         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
643 
644         return getPersistenceBrokerTemplate().getCount(query);
645     }
646 
647     /**
648      * Finds all of the balances for the fiscal year that should be processed by nominal activity closing
649      *
650      * @param year the university fiscal year of balances to find
651      * @return an Iterator of Balances to process
652      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findNominalActivityBalancesForFiscalYear(Integer, List, SystemOptions)
653      */
654     @Override
655     public Iterator<Balance> findNominalActivityBalancesForFiscalYear(Integer year, Collection<String> nominalActivityObjectTypeCodes, SystemOptions currentYearOptions) {
656         LOG.debug("findNominalActivityBalancesForFiscalYear() started");
657 
658         Criteria c = new Criteria();
659         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
660         c.addEqualTo(KFSPropertyConstants.BALANCE_TYPE_CODE, currentYearOptions.getActualFinancialBalanceTypeCd());
661         c.addIn(KFSPropertyConstants.OBJECT_TYPE_CODE, nominalActivityObjectTypeCodes);
662         c.addNotEqualTo("accountLineAnnualBalanceAmount", KualiDecimal.ZERO);
663 
664         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
665         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
666         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
667         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
668         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
669         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
670         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
671         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
672 
673         return getPersistenceBrokerTemplate().getIteratorByQuery(query);
674     }
675 
676      /**
677      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findNominalActivityBalancesForFiscalYear(java.lang.Integer, java.util.Collection, org.kuali.kfs.sys.businessobject.SystemOptions, java.util.List)
678      */
679     @Override
680     public Iterator<Balance> findNominalActivityBalancesForFiscalYear(Integer year, Collection<String> nominalActivityObjectTypeCodes, SystemOptions currentYearOptions, List<String> charts) {
681         LOG.debug("findNominalActivityBalancesForFiscalYear(year, charts) started");
682 
683         Criteria c = new Criteria();
684         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
685         c.addEqualTo(KFSPropertyConstants.BALANCE_TYPE_CODE, currentYearOptions.getActualFinancialBalanceTypeCd());
686         c.addIn(KFSPropertyConstants.OBJECT_TYPE_CODE, nominalActivityObjectTypeCodes);
687         c.addIn(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, charts);
688         c.addNotEqualTo(KFSPropertyConstants.ACCOUNT_LINE_ANNUAL_BALANCE_AMOUNT, KualiDecimal.ZERO);
689 
690         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
691         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
692         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
693         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
694         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
695         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
696         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
697         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
698 
699         return getPersistenceBrokerTemplate().getIteratorByQuery(query);
700     }
701 
702     /**
703      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findGeneralBalancesToForwardForFiscalYear(java.lang.Integer, java.util.List,
704      *      java.lang.String[])
705      */
706     @Override
707     public Iterator<Balance> findGeneralBalancesToForwardForFiscalYear(Integer year, Collection<String> generalForwardBalanceObjectTypes, Collection<String> generalBalanceForwardBalanceTypes) {
708 
709         Criteria c = new Criteria();
710         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
711         c.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, generalBalanceForwardBalanceTypes);
712         c.addIn(KFSPropertyConstants.OBJECT_TYPE_CODE, generalForwardBalanceObjectTypes);
713 
714         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
715         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
716         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
717         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
718         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
719         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
720         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
721         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
722 
723         Iterator<Balance> balances = getPersistenceBrokerTemplate().getIteratorByQuery(query);
724 
725         return balances;
726     }
727 
728     /**
729      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findGeneralBalancesToForwardForFiscalYear(java.lang.Integer, java.util.Collection, java.util.Collection, java.util.List)
730      */
731     @Override
732     public Iterator<Balance> findGeneralBalancesToForwardForFiscalYear(Integer year, Collection<String> generalForwardBalanceObjectTypes, Collection<String> generalBalanceForwardBalanceTypes, List<String> charts) {
733 
734         Criteria c = new Criteria();
735         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
736         c.addIn(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, charts);
737         c.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, generalBalanceForwardBalanceTypes);
738         c.addIn(KFSPropertyConstants.OBJECT_TYPE_CODE, generalForwardBalanceObjectTypes);
739 
740         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
741         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
742         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
743         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
744         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
745         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
746         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
747         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
748 
749         Iterator<Balance> balances = getPersistenceBrokerTemplate().getIteratorByQuery(query);
750 
751         FilteringBalanceIterator filteredBalances = SpringContext.getBean(FilteringBalanceIterator.class, GeneralLedgerConstants.GL_BALANCE_TOTAL_NOT_ZERO_ITERATOR);
752         filteredBalances.setBalancesSource(balances);
753 
754         return filteredBalances;
755     }
756 
757     /**
758      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findCumulativeBalancesToForwardForFiscalYear(java.lang.Integer, java.util.List,
759      *      java.util.List, java.lang.String[], java.lang.String[])
760      */
761     @Override
762     public Iterator<Balance> findCumulativeBalancesToForwardForFiscalYear(Integer year, Collection<String> cumulativeForwardBalanceObjectTypes, Collection<String> contractsAndGrantsDenotingValues, Collection<String> subFundGroupsForCumulativeBalanceForwarding, Collection<String> cumulativeBalanceForwardBalanceTypes, boolean fundGroupDenotesCGInd) {
763         Criteria c = new Criteria();
764         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
765         c.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, cumulativeBalanceForwardBalanceTypes);
766         c.addIn(KFSPropertyConstants.OBJECT_TYPE_CODE, cumulativeForwardBalanceObjectTypes);
767 
768         Criteria forCGCrit = new Criteria();
769         if (fundGroupDenotesCGInd) {
770             for (String value : contractsAndGrantsDenotingValues) {
771                 forCGCrit.addEqualTo(KFSPropertyConstants.PRIOR_YEAR_ACCOUNT + "." + KFSPropertyConstants.SUB_FUND_GROUP + "." + KFSPropertyConstants.FUND_GROUP_CODE, value);
772             }
773         }
774         else {
775             for (String value : contractsAndGrantsDenotingValues) {
776                 forCGCrit.addEqualTo(KFSPropertyConstants.PRIOR_YEAR_ACCOUNT + "." + KFSPropertyConstants.SUB_FUND_GROUP_CODE, value);
777             }
778         }
779 
780         Criteria subFundGroupCrit = new Criteria();
781         subFundGroupCrit.addIn(KFSPropertyConstants.PRIOR_YEAR_ACCOUNT + "." + KFSPropertyConstants.SUB_FUND_GROUP_CODE, subFundGroupsForCumulativeBalanceForwarding);
782         forCGCrit.addOrCriteria(subFundGroupCrit);
783         c.addAndCriteria(forCGCrit);
784 
785         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
786         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
787         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
788         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
789         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
790         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
791         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
792         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
793 
794         Iterator<Balance> balances = getPersistenceBrokerTemplate().getIteratorByQuery(query);
795 
796         return balances;
797     }
798 
799     /**
800      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findCumulativeBalancesToForwardForFiscalYear(java.lang.Integer, java.util.Collection, java.util.Collection, java.util.Collection, java.util.Collection, boolean, java.util.List)
801      */
802     @Override
803     public Iterator<Balance> findCumulativeBalancesToForwardForFiscalYear(Integer year, Collection<String> cumulativeForwardBalanceObjectTypes, Collection<String> contractsAndGrantsDenotingValues, Collection<String> subFundGroupsForCumulativeBalanceForwarding, Collection<String> cumulativeBalanceForwardBalanceTypes, boolean fundGroupDenotesCGInd, List<String> charts) {
804 
805         Criteria c = new Criteria();
806         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
807         c.addIn(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, charts);
808         c.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, cumulativeBalanceForwardBalanceTypes);
809         c.addIn(KFSPropertyConstants.OBJECT_TYPE_CODE, cumulativeForwardBalanceObjectTypes);
810 
811         Criteria forCGCrit = new Criteria();
812         if (fundGroupDenotesCGInd) {
813            for (String value : contractsAndGrantsDenotingValues) {
814                forCGCrit.addEqualTo(KFSPropertyConstants.PRIOR_YEAR_ACCOUNT + "." + KFSPropertyConstants.SUB_FUND_GROUP + "." + KFSPropertyConstants.FUND_GROUP_CODE, value);
815            }
816         } else {
817             for (String value : contractsAndGrantsDenotingValues) {
818                 forCGCrit.addEqualTo(KFSPropertyConstants.PRIOR_YEAR_ACCOUNT + "." + KFSPropertyConstants.SUB_FUND_GROUP_CODE, value);
819             }
820         }
821 
822         Criteria subFundGroupCrit = new Criteria();
823         subFundGroupCrit.addIn(KFSPropertyConstants.PRIOR_YEAR_ACCOUNT + "." + KFSPropertyConstants.SUB_FUND_GROUP_CODE, subFundGroupsForCumulativeBalanceForwarding);
824         forCGCrit.addOrCriteria(subFundGroupCrit);
825         c.addAndCriteria(forCGCrit);
826 
827         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
828         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
829         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
830         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
831         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
832         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
833         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
834         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
835 
836         Iterator<Balance> balances = getPersistenceBrokerTemplate().getIteratorByQuery(query);
837 
838         FilteringBalanceIterator filteredBalances = SpringContext.getBean(FilteringBalanceIterator.class, GeneralLedgerConstants.GL_BALANCE_ANNUAL_AND_CG_TOTAL_NOT_ZERO_ITERATOR);
839         filteredBalances.setBalancesSource(balances);
840 
841         return filteredBalances;
842     }
843 
844     /**
845      * Returns a list of balances to return for the Organization Reversion year end job to process
846      *
847      * @param the university fiscal year to find balances for
848      * @param endOfYear if true, use current year accounts, otherwise use prior year accounts
849      * @return an Iterator of Balances to process
850      * @see org.kuali.kfs.gl.dataaccess.BalanceDao#findOrganizationReversionBalancesForFiscalYear(Integer, boolean, SystemOptions)
851      */
852     @Override
853     public Iterator<Balance> findOrganizationReversionBalancesForFiscalYear(Integer year, boolean endOfYear, SystemOptions options, List<ParameterEvaluator> parameterEvaluators) {
854         LOG.debug("findOrganizationReversionBalancesForFiscalYear() started");
855         Criteria c = new Criteria();
856         c.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
857 
858         for (ParameterEvaluator parameterEvaluator : parameterEvaluators) {
859 
860             String currentRule = parameterEvaluator.getValue();
861             if (endOfYear) {
862                 currentRule = currentRule.replaceAll("account\\.", "priorYearAccount.");
863             }
864             if (StringUtils.isNotBlank(currentRule)) {
865                 String propertyName = StringUtils.substringBefore(currentRule, "=");
866                 List<String> ruleValues = Arrays.asList(StringUtils.substringAfter(currentRule, "=").split(";"));
867                 if (propertyName != null && propertyName.length() > 0 && ruleValues.size() > 0 && !StringUtils.isBlank(ruleValues.get(0))) {
868                     if (parameterEvaluator.constraintIsAllow()) {
869                         c.addIn(propertyName, ruleValues);
870                     }
871                     else {
872                         c.addNotIn(propertyName, ruleValues);
873                     }
874                 }
875             }
876         }
877         // we only ever calculate on CB, AC, and encumbrance types, so let's only select those
878         List organizationReversionBalancesToSelect = new ArrayList();
879         organizationReversionBalancesToSelect.add(options.getActualFinancialBalanceTypeCd());
880         organizationReversionBalancesToSelect.add(options.getFinObjTypeExpenditureexpCd());
881         organizationReversionBalancesToSelect.add(options.getCostShareEncumbranceBalanceTypeCd());
882         organizationReversionBalancesToSelect.add(options.getIntrnlEncumFinBalanceTypCd());
883         organizationReversionBalancesToSelect.add(KFSConstants.BALANCE_TYPE_CURRENT_BUDGET);
884         c.addIn(KFSPropertyConstants.BALANCE_TYPE_CODE, organizationReversionBalancesToSelect);
885         QueryByCriteria query = QueryFactory.newQuery(Balance.class, c);
886         query.addOrderByAscending(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
887         query.addOrderByAscending(KFSPropertyConstants.ACCOUNT_NUMBER);
888         query.addOrderByAscending(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
889         query.addOrderByAscending(KFSPropertyConstants.OBJECT_CODE);
890         query.addOrderByAscending(KFSPropertyConstants.SUB_OBJECT_CODE);
891         query.addOrderByAscending(KFSPropertyConstants.BALANCE_TYPE_CODE);
892         query.addOrderByAscending(KFSPropertyConstants.OBJECT_TYPE_CODE);
893 
894         return getPersistenceBrokerTemplate().getIteratorByQuery(query);
895     }
896 
897     /**
898      * @see org.kuali.kfs.gl.dataaccess.BalancingDao#findCountGreaterOrEqualThan(java.lang.Integer)
899      */
900     @Override
901     public Integer findCountGreaterOrEqualThan(Integer year) {
902         Criteria criteria = new Criteria();
903         criteria.addGreaterOrEqualThan(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, year);
904 
905         ReportQueryByCriteria query = QueryFactory.newReportQuery(Balance.class, criteria);
906 
907         return getPersistenceBrokerTemplate().getCount(query);
908     }
909 
910 }