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.gl.businessobject.lookup;
017    
018    import java.util.ArrayList;
019    import java.util.Collection;
020    import java.util.Collections;
021    import java.util.Iterator;
022    import java.util.List;
023    import java.util.Map;
024    
025    import org.apache.commons.lang.StringUtils;
026    import org.kuali.kfs.gl.Constant;
027    import org.kuali.kfs.gl.businessobject.inquiry.EntryInquirableImpl;
028    import org.kuali.kfs.gl.businessobject.inquiry.InquirableFinancialDocument;
029    import org.kuali.kfs.sys.KFSConstants;
030    import org.kuali.kfs.sys.KFSKeyConstants;
031    import org.kuali.kfs.sys.KFSPropertyConstants;
032    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
033    import org.kuali.kfs.sys.businessobject.UniversityDate;
034    import org.kuali.kfs.sys.context.SpringContext;
035    import org.kuali.kfs.sys.service.GeneralLedgerPendingEntryService;
036    import org.kuali.kfs.sys.service.UniversityDateService;
037    import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
038    import org.kuali.rice.kns.bo.BusinessObject;
039    import org.kuali.rice.kns.exception.ValidationException;
040    import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl;
041    import org.kuali.rice.kns.lookup.CollectionIncomplete;
042    import org.kuali.rice.kns.lookup.HtmlData;
043    import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
044    import org.kuali.rice.kns.service.ParameterService;
045    import org.kuali.rice.kns.util.BeanPropertyComparator;
046    import org.kuali.rice.kns.util.GlobalVariables;
047    import org.kuali.rice.kns.util.KNSConstants;
048    
049    /**
050     * An extension of KualiLookupableImpl to support balance lookups
051     */
052    public class PendingEntryLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl {
053        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PendingEntryLookupableHelperServiceImpl.class);
054    
055        private GeneralLedgerPendingEntryService generalLedgerPendingEntryService;
056        private ParameterService parameterService;
057    
058        private final static String UNIVERSITY_FISCAL_YEAR = "universityFiscalYear";
059        private final static String UNIVERSITY_FISCAL_PERIOD_CODE = "universityFiscalPeriodCode";
060    
061        /**
062         * Returns the url for any drill down links within the lookup (defers to its superclass unless it needs
063         * to get the url of the document that created this result pending entry)
064         * @param bo the business object with a property being drilled down on
065         * @param propertyName the name of the property being drilled down on
066         * @return a String with the URL of the property
067         * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
068         */
069        @Override
070        public HtmlData getInquiryUrl(BusinessObject businessObject, String propertyName) {
071            if (KFSPropertyConstants.DOCUMENT_NUMBER.equals(propertyName) && businessObject instanceof GeneralLedgerPendingEntry) {
072                GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) businessObject;
073                return new AnchorHtmlData(new InquirableFinancialDocument().getInquirableDocumentUrl(pendingEntry), KNSConstants.EMPTY_STRING, "view pending entry "+pendingEntry.toString());
074            }
075            return (new EntryInquirableImpl()).getInquiryUrl(businessObject, propertyName);
076            //return super.getInquiryUrl(businessObject, propertyName);
077        }
078    
079    
080        /**
081         * Validates the fiscal year searched for in the inquiry
082         * @param fieldValues the values of the query
083         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
084         */
085        @Override
086        public void validateSearchParameters(Map fieldValues) {
087            super.validateSearchParameters(fieldValues);
088    
089            String valueFiscalYear = (String) fieldValues.get(UNIVERSITY_FISCAL_YEAR);
090            if (!StringUtils.isEmpty(valueFiscalYear)) {
091                try {
092                    int year = Integer.parseInt(valueFiscalYear);
093                }
094                catch (NumberFormatException e) {
095                    GlobalVariables.getMessageMap().putError(UNIVERSITY_FISCAL_YEAR, KFSKeyConstants.ERROR_CUSTOM, new String[] { KFSKeyConstants.PendingEntryLookupableImpl.FISCAL_YEAR_FOUR_DIGIT });
096                    throw new ValidationException("errors in search criteria");
097                }
098            }
099            
100            if (!allRequiredsForAccountSearch(fieldValues) && !allRequiredsForDocumentSearch(fieldValues)) {
101                GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_GL_LOOKUP_PENDING_ENTRY_NON_MATCHING_REQUIRED_FIELDS, new String[] {});
102                throw new ValidationException("errors in search criteria");
103            }
104        }
105        
106        /**
107         * Determines if all the required values for an account based search are present - fiscal year, chart, account number, and fiscal period code
108         * @param fieldValues field values to check
109         * @return true if all the account-based required search fields are present; false otherwise
110         */
111        protected boolean allRequiredsForAccountSearch(Map fieldValues) {
112            final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
113            final String chartOfAccountsCode = (String)fieldValues.get("chartOfAccountsCode");
114            final String accountNumber = (String)fieldValues.get("accountNumber");
115            final String fiscalPeriodCode = (String)fieldValues.get("universityFiscalPeriodCode");
116            return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(chartOfAccountsCode) && !StringUtils.isBlank(accountNumber) && !StringUtils.isBlank(fiscalPeriodCode);
117        }
118        
119        /**
120         * Determines if all the required values for an document based search are present - fiscal year and document number
121         * @param fieldValues field values to check
122         * @return true if all the document-based required search fields are present; false otherwise
123         */
124        protected boolean allRequiredsForDocumentSearch(Map fieldValues) {
125            final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
126            final String documentNumber = (String)fieldValues.get("documentNumber");
127            return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(documentNumber);
128        }
129    
130    
131        /**
132         * Generates the list of search results for this inquiry
133         * @param fieldValues the field values of the query to carry out
134         * @return List the search results returned by the lookup
135         * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map)
136         */
137        public List getSearchResults(Map fieldValues) {
138            setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION));
139            setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY));
140    
141            boolean isApproved = fieldValues.containsKey(Constant.PENDING_ENTRY_OPTION) && Constant.APPROVED_PENDING_ENTRY.equals(fieldValues.get(Constant.PENDING_ENTRY_OPTION));
142            Collection searchResultsCollection = generalLedgerPendingEntryService.findPendingEntries(fieldValues, isApproved);
143    
144            // sort list if default sort column given
145            List searchResults = (List) searchResultsCollection;
146            List defaultSortColumns = getDefaultSortColumns();
147            if (defaultSortColumns.size() > 0) {
148                Collections.sort(searchResults, new BeanPropertyComparator(defaultSortColumns, true));
149            }
150    
151            // get the result limit number from configuration
152            String limitConfig = parameterService.getParameterValue(KfsParameterConstants.NERVOUS_SYSTEM_LOOKUP.class, KFSConstants.LOOKUP_RESULTS_LIMIT_URL_KEY);
153            Integer limit = null;
154            if (limitConfig != null) {
155                limit = Integer.valueOf(limitConfig);
156            }
157    
158            Long collectionCount = new Long(searchResults.size());
159            Long actualCountIfTruncated = new Long(0);
160    
161            // If more than limit number of records were returned, removed
162            if (limit != null) {
163                if (collectionCount >= limit.intValue()) {
164                    actualCountIfTruncated = collectionCount;
165                    for (int i = collectionCount.intValue() - 1; i >= limit; i--) {
166                        searchResults.remove(i);
167                    }
168                }
169            }
170    
171            UniversityDate currentUniversityDate = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
172            String currentFiscalPeriodCode = currentUniversityDate.getUniversityFiscalAccountingPeriod();
173            Integer currentFiscalYear = currentUniversityDate.getUniversityFiscalYear();
174    
175            String fiscalPeriodFromForm = null;
176            if (fieldValues.containsKey(UNIVERSITY_FISCAL_PERIOD_CODE)) {
177                fiscalPeriodFromForm = (String) fieldValues.get(UNIVERSITY_FISCAL_PERIOD_CODE);
178            }
179    
180            String fiscalYearFromForm = null;
181            if (fieldValues.containsKey(UNIVERSITY_FISCAL_YEAR)) {
182                fiscalYearFromForm = (String) fieldValues.get(UNIVERSITY_FISCAL_YEAR);
183            }
184            // Set null fy and ap to current values.
185            for (Iterator i = searchResults.iterator(); i.hasNext();) {
186                GeneralLedgerPendingEntry glpe = (GeneralLedgerPendingEntry) i.next();
187    
188                if (currentFiscalPeriodCode.equals(fiscalPeriodFromForm) && null == glpe.getUniversityFiscalPeriodCode()) {
189                    glpe.setUniversityFiscalPeriodCode(currentFiscalPeriodCode);
190                }
191    
192                if (currentFiscalYear.toString().equals(fiscalYearFromForm) && null == glpe.getUniversityFiscalYear()) {
193                    glpe.setUniversityFiscalYear(currentFiscalYear);
194                }
195            }
196    
197            return new CollectionIncomplete(searchResults, actualCountIfTruncated);
198        }
199    
200        /**
201         * This method builds the collection of search results without period codes and updates the results with current period code
202         * 
203         * @param iterator the iterator of search results
204         * @param periodCode the current period code
205         * @return the collection of search results with updated period codes
206         */
207        private Collection buildSearchResults(Iterator iterator, String periodCode) {
208            Collection collection = new ArrayList();
209    
210            while (iterator.hasNext()) {
211                GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) iterator.next();
212                pendingEntry.setUniversityFiscalPeriodCode(periodCode);
213                collection.add(pendingEntry);
214            }
215    
216            return new CollectionIncomplete(collection, new Long(collection.size()));
217        }
218    
219        /**
220         * Sets the generalLedgerPendingEntryService attribute value.
221         * 
222         * @param generalLedgerPendingEntryService The generalLedgerPendingEntryService to set.
223         */
224        public void setGeneralLedgerPendingEntryService(GeneralLedgerPendingEntryService generalLedgerPendingEntryService) {
225            this.generalLedgerPendingEntryService = generalLedgerPendingEntryService;
226        }
227    
228        public void setParameterService(ParameterService parameterService) {
229            this.parameterService = parameterService;
230        }
231    
232    }