001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.sys.dataaccess.impl;
017    
018    import java.math.BigDecimal;
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.Collection;
022    import java.util.HashMap;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Map;
026    
027    import org.apache.commons.lang.StringUtils;
028    import org.apache.ojb.broker.query.Criteria;
029    import org.apache.ojb.broker.query.QueryByCriteria;
030    import org.apache.ojb.broker.query.QueryFactory;
031    import org.apache.ojb.broker.query.ReportQueryByCriteria;
032    import org.kuali.kfs.coa.businessobject.Account;
033    import org.kuali.kfs.coa.service.BalanceTypeService;
034    import org.kuali.kfs.gl.OJBUtility;
035    import org.kuali.kfs.gl.businessobject.Balance;
036    import org.kuali.kfs.gl.businessobject.Encumbrance;
037    import org.kuali.kfs.sys.KFSConstants;
038    import org.kuali.kfs.sys.KFSPropertyConstants;
039    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
040    import org.kuali.kfs.sys.businessobject.SystemOptions;
041    import org.kuali.kfs.sys.businessobject.UniversityDate;
042    import org.kuali.kfs.sys.context.SpringContext;
043    import org.kuali.kfs.sys.dataaccess.GeneralLedgerPendingEntryDao;
044    import org.kuali.kfs.sys.service.OptionsService;
045    import org.kuali.kfs.sys.service.UniversityDateService;
046    import org.kuali.rice.kns.dao.impl.PlatformAwareDaoBaseOjb;
047    import org.kuali.rice.kns.lookup.LookupUtils;
048    import org.kuali.rice.kns.service.ParameterService;
049    import org.kuali.rice.kns.util.KualiDecimal;
050    import org.kuali.rice.kns.util.TransactionalServiceUtils;
051    
052    /**
053     * 
054     * 
055     */
056    public class GeneralLedgerPendingEntryDaoOjb extends PlatformAwareDaoBaseOjb implements GeneralLedgerPendingEntryDao {
057        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(GeneralLedgerPendingEntryDaoOjb.class);
058    
059        protected final static String TRANSACTION_LEDGER_ENTRY_SEQUENCE_NUMBER = "transactionLedgerEntrySequenceNumber";
060        protected final static String FINANCIAL_DOCUMENT_APPROVED_CODE = "financialDocumentApprovedCode";
061        protected final static String ACCOUNT_NUMBER = "accountNumber";
062        protected final static String CHART_OF_ACCOUNTS_CODE = "chartOfAccountsCode";
063        protected final static String CHART_FINANCIAL_CASH_OBJECT_CODE = "chart.financialCashObjectCode";
064        protected final static String OBJECT_TYPE_FIN_OBJECT_TYPE_DEBITCREDIT_CD = "objectType.finObjectTypeDebitcreditCd";
065    
066        private ParameterService parameterService;
067        private BalanceTypeService balanceTypService;
068        private OptionsService optionsService;
069    
070        /**
071         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#getTransactionSummary(java.lang.Integer, java.lang.String,
072         *      java.lang.String, java.util.Collection, java.util.Collection, java.lang.String, boolean)
073         */
074        public KualiDecimal getTransactionSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, Collection objectTypeCodes, Collection balanceTypeCodes, String acctSufficientFundsFinObjCd, boolean isYearEnd) {
075            LOG.debug("getTransactionSummary() started");
076    
077            Criteria criteria = new Criteria();
078            criteria.addEqualTo(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, universityFiscalYear);
079            criteria.addEqualTo(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, chartOfAccountsCode);
080            criteria.addEqualTo(KFSConstants.ACCOUNT_NUMBER_PROPERTY_NAME, accountNumber);
081            criteria.addEqualTo("acctSufficientFundsFinObjCd", acctSufficientFundsFinObjCd);
082            criteria.addIn(KFSConstants.FINANCIAL_BALANCE_TYPE_CODE_PROPERTY_NAME, balanceTypeCodes);
083            criteria.addIn("financialObjectTypeCode", objectTypeCodes);
084    
085            if (isYearEnd) {
086                criteria.addLike("financialDocumentTypeCode", "YE%");
087            }
088            else {
089                criteria.addNotLike("financialDocumentTypeCode", "YE%");
090            }
091    
092            Collection status = new ArrayList();
093            status.add(KFSConstants.DocumentStatusCodes.CANCELLED);
094            status.add(KFSConstants.DocumentStatusCodes.DISAPPROVED);
095    
096            criteria.addNotIn(KFSConstants.DOCUMENT_HEADER_PROPERTY_NAME + "." + KFSConstants.DOCUMENT_HEADER_DOCUMENT_STATUS_CODE_PROPERTY_NAME, status);
097    
098            ReportQueryByCriteria reportQuery = QueryFactory.newReportQuery(this.getEntryClass(), criteria);
099            reportQuery.setAttributes(new String[] { "sum(" + KFSConstants.TRANSACTION_LEDGER_ENTRY_AMOUNT + ")" });
100    
101            KualiDecimal rv = null;
102            Iterator iterator = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(reportQuery);
103            if (iterator.hasNext()) {
104                rv = (KualiDecimal) ((Object[]) TransactionalServiceUtils.retrieveFirstAndExhaustIterator(iterator))[0];
105            }
106            return (rv == null) ? KualiDecimal.ZERO : rv;
107        }
108    
109        /**
110         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#getTransactionSummary(java.lang.Integer, java.lang.String,
111         *      java.lang.String, java.util.Collection, java.util.Collection, boolean, boolean)
112         */
113        public KualiDecimal getTransactionSummary(Integer universityFiscalYear, String chartOfAccountsCode, String accountNumber, Collection objectTypeCodes, Collection balanceTypeCodes, String acctSufficientFundsFinObjCd, boolean isDebit, boolean isYearEnd) {
114            LOG.debug("getTransactionSummary() started");
115    
116            Criteria criteria = new Criteria();
117            criteria.addEqualTo(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, universityFiscalYear);
118            criteria.addEqualTo(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, chartOfAccountsCode);
119            criteria.addEqualTo(KFSConstants.ACCOUNT_NUMBER_PROPERTY_NAME, accountNumber);
120            criteria.addEqualTo("acctSufficientFundsFinObjCd", acctSufficientFundsFinObjCd);
121            criteria.addIn(KFSConstants.FINANCIAL_BALANCE_TYPE_CODE_PROPERTY_NAME, balanceTypeCodes);
122            criteria.addIn("financialObjectTypeCode", objectTypeCodes);
123    
124            if (isYearEnd) {
125                criteria.addLike("financialDocumentTypeCode", "YE%");
126            }
127            else {
128                criteria.addNotLike("financialDocumentTypeCode", "YE%");
129            }
130    
131            if (isDebit) {
132                criteria.addEqualTo(KFSConstants.TRANSACTION_DEBIT_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE);
133            }
134            else {
135                criteria.addNotEqualTo(KFSConstants.TRANSACTION_DEBIT_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE);
136            }
137    
138            Collection status = new ArrayList();
139            status.add(KFSConstants.DocumentStatusCodes.CANCELLED);
140            status.add(KFSConstants.DocumentStatusCodes.DISAPPROVED);
141    
142            criteria.addNotIn(KFSConstants.DOCUMENT_HEADER_PROPERTY_NAME + "." + KFSConstants.DOCUMENT_HEADER_DOCUMENT_STATUS_CODE_PROPERTY_NAME, status);
143    
144            ReportQueryByCriteria reportQuery = QueryFactory.newReportQuery(this.getEntryClass(), criteria);
145            reportQuery.setAttributes(new String[] { "sum(" + KFSConstants.TRANSACTION_LEDGER_ENTRY_AMOUNT + ")" });
146    
147            KualiDecimal rv = null;
148            Iterator iterator = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(reportQuery);
149            if (iterator.hasNext()) {
150                rv = (KualiDecimal) ((Object[]) iterator.next())[0];
151            }
152            return (rv == null) ? KualiDecimal.ZERO : rv;
153        }
154    
155        /**
156         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#getTransactionSummary(java.util.Collection, java.lang.String,
157         *      java.lang.String, java.util.Collection, java.util.Collection, boolean)
158         */
159        public KualiDecimal getTransactionSummary(Collection universityFiscalYears, String chartOfAccountsCode, String accountNumber, Collection objectCodes, Collection balanceTypeCodes, boolean isDebit) {
160            LOG.debug("getTransactionSummary() started");
161    
162            Criteria criteria = new Criteria();
163            criteria.addIn(KFSConstants.UNIVERSITY_FISCAL_YEAR_PROPERTY_NAME, universityFiscalYears);
164            criteria.addEqualTo(KFSConstants.CHART_OF_ACCOUNTS_CODE_PROPERTY_NAME, chartOfAccountsCode);
165            criteria.addEqualTo(KFSConstants.ACCOUNT_NUMBER_PROPERTY_NAME, accountNumber);
166            criteria.addIn(KFSConstants.FINANCIAL_OBJECT_CODE_PROPERTY_NAME, objectCodes);
167            criteria.addIn(KFSConstants.FINANCIAL_BALANCE_TYPE_CODE_PROPERTY_NAME, balanceTypeCodes);
168    
169            if (isDebit) {
170                criteria.addEqualTo(KFSConstants.TRANSACTION_DEBIT_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE);
171            }
172            else {
173                criteria.addNotEqualTo(KFSConstants.TRANSACTION_DEBIT_CREDIT_CODE, KFSConstants.GL_DEBIT_CODE);
174            }
175    
176            Collection status = new ArrayList();
177            status.add(KFSConstants.DocumentStatusCodes.CANCELLED);
178            status.add(KFSConstants.DocumentStatusCodes.DISAPPROVED);
179    
180            criteria.addNotIn(KFSConstants.DOCUMENT_HEADER_PROPERTY_NAME + "." + KFSConstants.DOCUMENT_HEADER_DOCUMENT_STATUS_CODE_PROPERTY_NAME, status);
181    
182            ReportQueryByCriteria reportQuery = QueryFactory.newReportQuery(this.getEntryClass(), criteria);
183            reportQuery.setAttributes(new String[] { "sum(" + KFSConstants.TRANSACTION_LEDGER_ENTRY_AMOUNT + ")" });
184    
185            KualiDecimal rv = null;
186            Iterator iterator = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(reportQuery);
187            if (iterator.hasNext()) {
188                rv = (KualiDecimal) ((Object[]) TransactionalServiceUtils.retrieveFirstAndExhaustIterator(iterator))[0];
189            }
190            return (rv == null) ? KualiDecimal.ZERO : rv;
191        }
192    
193        /*
194         * (non-Javadoc)
195         * 
196         * @see org.kuali.dao.GeneralLedgerPendingEntryDao#getByPrimaryId(java.lang.Long, java.lang.Long)
197         */
198        public GeneralLedgerPendingEntry getByPrimaryId(String documentHeaderId, Integer transactionLedgerEntrySequenceNumber) {
199            LOG.debug("getByPrimaryId() started");
200    
201            Criteria criteria = new Criteria();
202            criteria.addEqualTo(KFSPropertyConstants.DOCUMENT_NUMBER, documentHeaderId);
203            criteria.addEqualTo(TRANSACTION_LEDGER_ENTRY_SEQUENCE_NUMBER, transactionLedgerEntrySequenceNumber);
204    
205            return (GeneralLedgerPendingEntry) getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(this.getEntryClass(), criteria));
206        }
207    
208        /*
209         * (non-Javadoc)
210         * 
211         * @see org.kuali.dao.GeneralLedgerPendingEntryDao#save(org.kuali.bo.GeneralLedgerPendingEntry)
212         */
213        public void save(GeneralLedgerPendingEntry generalLedgerPendingEntry) {
214            LOG.debug("save() started");
215    
216            getPersistenceBrokerTemplate().store(generalLedgerPendingEntry);
217        }
218    
219        /*
220         * (non-Javadoc)
221         * 
222         * @see org.kuali.dao.GeneralLedgerPendingEntryDao#delete(Long)
223         */
224        public void delete(String documentHeaderId) {
225            LOG.debug("delete() started");
226    
227            if (documentHeaderId != null) {
228                Criteria criteria = new Criteria();
229                criteria.addEqualTo(KFSPropertyConstants.DOCUMENT_NUMBER, documentHeaderId);
230    
231                getPersistenceBrokerTemplate().deleteByQuery(QueryFactory.newQuery(this.getEntryClass(), criteria));
232                getPersistenceBrokerTemplate().clearCache();
233            }
234        }
235    
236        public void deleteByFinancialDocumentApprovedCode(String financialDocumentApprovedCode) {
237            LOG.debug("deleteByFinancialDocumentApprovedCode() started");
238    
239            Criteria criteria = new Criteria();
240            criteria.addEqualTo(FINANCIAL_DOCUMENT_APPROVED_CODE, financialDocumentApprovedCode);
241    
242            QueryByCriteria qbc = QueryFactory.newQuery(this.getEntryClass(), criteria);
243            getPersistenceBrokerTemplate().deleteByQuery(qbc);
244            getPersistenceBrokerTemplate().clearCache();
245        }
246    
247        /**
248         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findApprovedPendingLedgerEntries()
249         */
250        public Iterator findApprovedPendingLedgerEntries() {
251            LOG.debug("findApprovedPendingLedgerEntries() started");
252    
253            // only process the document for which document status code is A (approved)
254            Criteria criteria = new Criteria();
255            criteria.addEqualTo("financialDocumentApprovedCode", KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.APPROVED);
256    
257            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
258            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
259        }
260    
261        /**
262         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#countPendingLedgerEntries(org.kuali.kfs.coa.businessobject.Account)
263         */
264        public int countPendingLedgerEntries(Account account) {
265            LOG.debug("findPendingLedgerEntries(Account) started");
266    
267            Criteria criteria = new Criteria();
268            criteria.addEqualTo(ACCOUNT_NUMBER, account.getAccountNumber());
269            criteria.addEqualTo(CHART_OF_ACCOUNTS_CODE, account.getChartOfAccountsCode());
270    
271            ReportQueryByCriteria query = QueryFactory.newReportQuery(this.getEntryClass(), criteria);
272            query.setAttributes(new String[] { "count(*)" });
273            Iterator i = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
274            if (i.hasNext()) {
275                Object[] values = (Object[]) TransactionalServiceUtils.retrieveFirstAndExhaustIterator(i);
276                if (values[0] instanceof BigDecimal) {
277                    return ((BigDecimal) values[0]).intValue();
278                }
279                else {
280                    return ((Long) values[0]).intValue();
281                }
282            }
283            else {
284                return 0;
285            }
286        }
287    
288        /**
289         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntries(org.kuali.kfs.gl.businessobject.Encumbrance,
290         *      boolean)
291         */
292        public Iterator findPendingLedgerEntries(Encumbrance encumbrance, boolean isApproved) {
293            LOG.debug("findPendingLedgerEntries(Encumbrance, boolean) started");
294    
295            // find pending ledger entry by the primary key fields of encumbrance
296            Criteria criteria = new Criteria();
297            criteria.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, encumbrance.getUniversityFiscalYear());
298            criteria.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, encumbrance.getChartOfAccountsCode());
299            criteria.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, encumbrance.getAccountNumber());
300            criteria.addEqualTo(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, encumbrance.getSubAccountNumber());
301            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, encumbrance.getObjectCode());
302            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, encumbrance.getSubObjectCode());
303            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, encumbrance.getBalanceTypeCode());
304            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_DOCUMENT_TYPE_CODE, encumbrance.getDocumentTypeCode());
305            criteria.addEqualTo(KFSPropertyConstants.ORGANIZATION_DOCUMENT_NUMBER, encumbrance.getDocumentNumber());
306    
307            // add the status codes into the criteria
308            this.addStatusCode(criteria, isApproved);
309    
310            // Criteria: (originCode=originationCode OR originCode=originationReferenceCode)
311            Criteria criteria1 = new Criteria();
312            Criteria criteria2 = new Criteria();
313            criteria1.addEqualTo(KFSPropertyConstants.FINANCIAL_SYSTEM_ORIGINATION_CODE, encumbrance.getOriginCode());
314            criteria2.addEqualTo(KFSPropertyConstants.REFERENCE_FINANCIAL_SYSTEM_ORIGINATION_CODE, encumbrance.getOriginCode());
315            criteria1.addOrCriteria(criteria2);
316    
317            // combine all criteria together
318            criteria.addAndCriteria(criteria1);
319    
320            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
321            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
322        }
323    
324        /**
325         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntries(org.kuali.kfs.gl.businessobject.Balance, boolean,
326         *      boolean)
327         */
328        public Iterator findPendingLedgerEntries(Balance balance, boolean isApproved, boolean isConsolidated) {
329            LOG.debug("findPendingLedgerEntries(Balance, boolean, boolean) started");
330    
331            // find pending ledger entry by the primary key fields of balance
332            Criteria criteria = new Criteria();
333            criteria.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, balance.getUniversityFiscalYear());
334            criteria.addEqualTo(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, balance.getChartOfAccountsCode());
335            criteria.addEqualTo(KFSPropertyConstants.ACCOUNT_NUMBER, balance.getAccountNumber());
336            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, balance.getObjectCode());
337            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, balance.getBalanceTypeCode());
338    
339            if (!isConsolidated) {
340                criteria.addEqualTo(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, balance.getSubAccountNumber());
341            }
342    
343            // add the status codes into the criteria
344            this.addStatusCode(criteria, isApproved);
345    
346            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
347            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
348        }
349    
350        /**
351         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntriesForEntry(java.util.Map, boolean)
352         */
353        public Iterator findPendingLedgerEntriesForEntry(Map fieldValues, boolean isApproved) {
354            LOG.debug("findPendingLedgerEntriesForEntry started");
355    
356            Criteria criteria = buildCriteriaFromMap(fieldValues, new GeneralLedgerPendingEntry());
357    
358            // add the status codes into the criteria
359            this.addStatusCode(criteria, isApproved);
360    
361            LookupUtils.applySearchResultsLimit(criteria, getDbPlatform());
362    
363            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
364            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
365        }
366    
367        /**
368         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntriesForBalance(java.util.Map, boolean)
369         */
370        public Iterator findPendingLedgerEntriesForBalance(Map fieldValues, boolean isApproved) {
371            LOG.debug("findPendingLedgerEntriesForBalance started");
372    
373            Criteria criteria = buildCriteriaFromMap(fieldValues, this.getEntryClassInstance());
374    
375            // add the status codes into the criteria
376            this.addStatusCode(criteria, isApproved);
377    
378            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
379            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
380        }
381    
382        /**
383         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntriesForCashBalance(java.util.Map, boolean)
384         */
385        public Iterator findPendingLedgerEntriesForCashBalance(Map fieldValues, boolean isApproved) {
386            LOG.debug("findPendingLedgerEntriesForCashBalance started");
387    
388            Criteria criteria = buildCriteriaFromMap(fieldValues, this.getEntryClassInstance());
389            criteria.addEqualTo(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, "AC");
390            criteria.addEqualToField(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, CHART_FINANCIAL_CASH_OBJECT_CODE);
391    
392            // add the status codes into the criteria
393            this.addStatusCode(criteria, isApproved);
394    
395            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
396            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
397        }
398    
399        /**
400         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntriesForEncumbrance(Map, boolean)
401         */
402        public Iterator findPendingLedgerEntriesForEncumbrance(Map fieldValues, boolean isApproved) {
403            LOG.debug("findPendingLedgerEntriesForEncumbrance started");
404    
405            Criteria criteria = buildCriteriaFromMap(fieldValues, this.getEntryClassInstance());
406            criteria.addIn(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, Arrays.asList(KFSConstants.ENCUMBRANCE_BALANCE_TYPE));
407    
408            List encumbranceUpdateCodeList = new ArrayList();
409            encumbranceUpdateCodeList.add(KFSConstants.ENCUMB_UPDT_REFERENCE_DOCUMENT_CD);
410            encumbranceUpdateCodeList.add(KFSConstants.ENCUMB_UPDT_DOCUMENT_CD);
411            criteria.addIn(KFSPropertyConstants.TRANSACTION_ENCUMBRANCE_UPDT_CD, encumbranceUpdateCodeList);
412    
413            // add the status codes into the criteria
414            this.addStatusCode(criteria, isApproved);
415           
416            // add criteria to exclude fund balance object type code 
417            criteria.addAndCriteria(buildCriteriaToExcludeFundBalance());
418    
419            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
420            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
421        }
422        
423        /**
424         * This method creates Criteria that exclude the fund balance object type from the result.
425         * @return Criteria
426         */
427        protected Criteria buildCriteriaToExcludeFundBalance() {
428    
429            SystemOptions option = optionsService.getCurrentYearOptions();
430            String fundBalanceObjectTypeCode = option.getFinObjectTypeFundBalanceCd();
431    
432            Criteria criteria = new Criteria();
433            criteria.addNotEqualTo(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE, fundBalanceObjectTypeCode);
434            return criteria;
435        }
436    
437        /**
438         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntriesForAccountBalance(java.util.Map, boolean,
439         *      boolean)
440         */
441        public Iterator findPendingLedgerEntriesForAccountBalance(Map fieldValues, boolean isApproved) {
442            LOG.debug("findPendingLedgerEntriesForAccountBalance started");
443    
444            Criteria criteria = buildCriteriaFromMap(fieldValues, this.getEntryClassInstance());
445    
446            // add the status codes into the criteria
447            this.addStatusCode(criteria, isApproved);
448    
449            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
450            return getPersistenceBrokerTemplate().getIteratorByQuery(query);
451        }
452    
453        /**
454         * @see org.kuali.module.gl.dao.GeneralLedgerPendingEntryDao#findPendingLedgerEntrySummaryForAccountBalance(java.util.Map,
455         *      boolean, boolean)
456         */
457        public Iterator findPendingLedgerEntrySummaryForAccountBalance(Map fieldValues, boolean isApproved) {
458            LOG.debug("findPendingLedgerEntrySummaryForAccountBalance started");
459    
460            Criteria criteria = buildCriteriaFromMap(fieldValues, this.getEntryClassInstance());
461    
462            // add the status codes into the criteria
463            this.addStatusCode(criteria, isApproved);
464    
465            ReportQueryByCriteria query = QueryFactory.newReportQuery(this.getEntryClass(), criteria);
466    
467            List attributeList = buildAttributeList();
468            List groupByList = buildGroupList();
469    
470            // set the selection attributes
471            String[] attributes = (String[]) attributeList.toArray(new String[attributeList.size()]);
472            query.setAttributes(attributes);
473    
474            // add the group criteria into the selection statement
475            String[] groupBy = (String[]) groupByList.toArray(new String[groupByList.size()]);
476            query.addGroupBy(groupBy);
477    
478            return getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(query);
479        }
480    
481        /**
482         * This method builds the atrribute list used by balance searching
483         * 
484         * @return List an attribute list
485         */
486        protected List buildAttributeList() {
487            List attributeList = buildGroupList();
488            attributeList.add("sum(" + KFSPropertyConstants.TRANSACTION_LEDGER_ENTRY_AMOUNT + ")");
489            return attributeList;
490        }
491    
492        /**
493         * This method builds group by attribute list used by balance searching
494         * 
495         * @return List an group by attribute list
496         */
497        protected List buildGroupList() {
498            List groupList = new ArrayList();
499    
500            groupList.add(KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
501            groupList.add(KFSPropertyConstants.FINANCIAL_DOCUMENT_APPROVED_CODE);
502            groupList.add(KFSPropertyConstants.TRANSACTION_DEBIT_CREDIT_CODE);
503            groupList.add(OBJECT_TYPE_FIN_OBJECT_TYPE_DEBITCREDIT_CD);
504            return groupList;
505        }
506    
507        /**
508         * add the status code into the given criteria. The status code can be categorized into approved and all.
509         * 
510         * @param criteria the given criteria
511         * @param isApproved the flag that indictates if only approved status code can be added into the given searach criteria
512         */
513        protected void addStatusCode(Criteria criteria, boolean isOnlyApproved) {
514            // add criteria for the approved pending entries
515            if (isOnlyApproved) {
516                criteria.addIn("documentHeader.financialDocumentStatusCode", this.buildApprovalCodeList());
517                criteria.addNotEqualTo(KFSPropertyConstants.FINANCIAL_DOCUMENT_APPROVED_CODE, KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.PROCESSED);
518            }
519            else {
520                Criteria subCriteria1 = new Criteria();
521                subCriteria1.addNotEqualTo(KFSPropertyConstants.FINANCIAL_DOCUMENT_APPROVED_CODE, KFSConstants.PENDING_ENTRY_APPROVED_STATUS_CODE.PROCESSED);
522    
523                Criteria subCriteria2 = new Criteria();
524                subCriteria2.addIsNull(KFSPropertyConstants.FINANCIAL_DOCUMENT_APPROVED_CODE);
525    
526                subCriteria1.addOrCriteria(subCriteria2);
527                criteria.addAndCriteria(subCriteria1);
528            }
529        }
530    
531        /**
532         * build a status code list including the legal approval codes
533         * 
534         * @return an approval code list
535         */
536        protected List buildApprovalCodeList() {
537            List approvalCodeList = new ArrayList();
538    
539            approvalCodeList.add(KFSConstants.DocumentStatusCodes.APPROVED);
540            return approvalCodeList;
541        }
542    
543        /**
544         * This method builds an OJB query criteria based on the input field map
545         * 
546         * @param fieldValues the input field map
547         * @param businessObject the given business object
548         * @return an OJB query criteria
549         */
550        public Criteria buildCriteriaFromMap(Map fieldValues, Object businessObject) {
551            Criteria criteria = new Criteria();
552    
553            UniversityDate currentUniversityDate = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
554            String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod();
555            Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear();
556    
557            // deal with null fiscal year and fiscal period code as current fiscal year and period code respectively
558            String fiscalPeriodFromForm = null;
559            if (fieldValues.containsKey(KFSPropertyConstants.UNIVERSITY_FISCAL_PERIOD_CODE)) {
560                fiscalPeriodFromForm = (String) fieldValues.get(KFSPropertyConstants.UNIVERSITY_FISCAL_PERIOD_CODE);
561            }
562    
563            String fiscalYearFromForm = null;
564            if (fieldValues.containsKey(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR)) {
565                fiscalYearFromForm = (String) fieldValues.get(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
566            }
567    
568            boolean includeNullFiscalPeriodCodeInLookup = null != currentFiscalPeriodCode && currentFiscalPeriodCode.equals(fiscalPeriodFromForm);
569            boolean includeNullFiscalYearInLookup = null != currentFiscalYear && currentFiscalYear.toString().equals(fiscalYearFromForm);
570    
571            if (includeNullFiscalPeriodCodeInLookup) {
572                Criteria apValueCriteria = new Criteria();
573                apValueCriteria.addLike(KFSPropertyConstants.UNIVERSITY_FISCAL_PERIOD_CODE, fiscalPeriodFromForm);
574    
575                Criteria apNullCriteria = new Criteria();
576                apNullCriteria.addIsNull(KFSPropertyConstants.UNIVERSITY_FISCAL_PERIOD_CODE);
577    
578                apValueCriteria.addOrCriteria(apNullCriteria);
579                criteria.addAndCriteria(apValueCriteria);
580    
581            }
582    
583            if (includeNullFiscalYearInLookup) {
584                Criteria fyValueCriteria = new Criteria();
585                fyValueCriteria.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, fiscalYearFromForm);
586    
587                Criteria fyNullCriteria = new Criteria();
588                fyNullCriteria.addIsNull(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
589    
590                fyValueCriteria.addOrCriteria(fyNullCriteria);
591                criteria.addAndCriteria(fyValueCriteria);
592            }
593    
594            // handle encumbrance balance type
595            Map<String, Object> localFieldValues = new HashMap();
596            localFieldValues.putAll(fieldValues);
597            
598            // we've already taken care of these fields...
599            if (includeNullFiscalPeriodCodeInLookup) {
600                localFieldValues.remove(KFSPropertyConstants.UNIVERSITY_FISCAL_PERIOD_CODE);
601            }
602            if (includeNullFiscalYearInLookup) {
603                localFieldValues.remove(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
604            }
605    
606            String propertyName = KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE;
607            if (localFieldValues.containsKey(propertyName)) {
608                String propertyValue = (String) fieldValues.get(propertyName);
609                if (KFSConstants.AGGREGATE_ENCUMBRANCE_BALANCE_TYPE_CODE.equals(propertyValue)) {
610                    localFieldValues.remove(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE);
611    
612                    // parse the fiscal year (it's not a required field on the lookup screens
613                    String universityFiscalYearStr = (String) localFieldValues.get(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
614                    if (StringUtils.isNotBlank(universityFiscalYearStr)) {
615                        Integer universityFiscalYear = new Integer(universityFiscalYearStr);
616                        criteria.addIn(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, balanceTypService.getEncumbranceBalanceTypes(universityFiscalYear));
617                    }
618                    else {
619                        criteria.addIn(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, balanceTypService.getCurrentYearEncumbranceBalanceTypes());
620                    }
621                }
622            }
623    
624            // remove dummyBusinessObject references - no longer needed
625            List<String> keysToRemove = new ArrayList<String>();
626            for (String key : localFieldValues.keySet()) {
627                if (key.startsWith("dummyBusinessObject.")) {
628                    keysToRemove.add(key);
629                }
630            }
631            for (String key : keysToRemove) {
632                localFieldValues.remove(key);
633            }
634    
635            criteria.addAndCriteria(OJBUtility.buildCriteriaFromMap(localFieldValues, businessObject));
636            return criteria;
637        }
638    
639        public Collection findPendingEntries(Map fieldValues, boolean isApproved) {
640            LOG.debug("findPendingEntries(Map, boolean) started");
641    
642            Criteria criteria = buildCriteriaFromMap(fieldValues, this.getEntryClassInstance());
643    
644            // add the status codes into the criteria
645            this.addStatusCode(criteria, isApproved);
646    
647            LookupUtils.applySearchResultsLimit(criteria, getDbPlatform());
648    
649            QueryByCriteria query = QueryFactory.newQuery(this.getEntryClass(), criteria);
650            return getPersistenceBrokerTemplate().getCollectionByQuery(query);
651        }
652    
653    
654        public void setParameterService(ParameterService parameterService) {
655            this.parameterService = parameterService;
656        }
657    
658        /**
659         * Gets the entryClass attribute.
660         * 
661         * @return Returns the entryClass.
662         */
663        public Class getEntryClass() {
664            return GeneralLedgerPendingEntry.class;
665        }
666    
667        protected Object getEntryClassInstance() {
668            Object entryObject = null;
669            try {
670                entryObject = getEntryClass().newInstance();
671            }
672            catch (Exception e) {
673                LOG.debug("Wrong object type" + e);
674            }
675            return entryObject;
676        }
677    
678        public void setBalanceTypService(BalanceTypeService balanceTypService) {
679            this.balanceTypService = balanceTypService;
680        }
681    
682        public OptionsService getOptionsService() {
683            return optionsService;
684        }
685    
686        public void setOptionsService(OptionsService optionsService) {
687            this.optionsService = optionsService;
688        }
689    }