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.sql.Date;
019    import java.util.Collection;
020    import java.util.Iterator;
021    import java.util.List;
022    import java.util.Map;
023    
024    import org.apache.commons.lang.StringUtils;
025    import org.kuali.kfs.gl.Constant;
026    import org.kuali.kfs.gl.businessobject.Entry;
027    import org.kuali.kfs.gl.businessobject.inquiry.EntryInquirableImpl;
028    import org.kuali.kfs.gl.businessobject.inquiry.InquirableFinancialDocument;
029    import org.kuali.kfs.gl.service.EntryService;
030    import org.kuali.kfs.gl.service.ScrubberValidator;
031    import org.kuali.kfs.sys.KFSConstants;
032    import org.kuali.kfs.sys.KFSKeyConstants;
033    import org.kuali.kfs.sys.KFSPropertyConstants;
034    import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
035    import org.kuali.kfs.sys.businessobject.UniversityDate;
036    import org.kuali.kfs.sys.context.SpringContext;
037    import org.kuali.kfs.sys.service.UniversityDateService;
038    import org.kuali.rice.kns.bo.BusinessObject;
039    import org.kuali.rice.kns.exception.ValidationException;
040    import org.kuali.rice.kns.lookup.HtmlData;
041    import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
042    import org.kuali.rice.kns.service.DateTimeService;
043    import org.kuali.rice.kns.util.GlobalVariables;
044    import org.kuali.rice.kns.util.KNSConstants;
045    
046    /**
047     * An extension of KualiLookupableImpl to support entry lookups
048     */
049    public class EntryLookupableHelperServiceImpl extends AbstractGeneralLedgerLookupableHelperServiceImpl {
050        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EntryLookupableHelperServiceImpl.class);
051    
052        private ScrubberValidator scrubberValidator;
053        private EntryService entryService;
054    
055        /**
056         * Validate the university fiscal year that has been queried on
057         * 
058         * @param fieldValues the queried fields
059         * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
060         */
061        @Override
062        public void validateSearchParameters(Map fieldValues) {
063            super.validateSearchParameters(fieldValues);
064    
065            String valueFiscalYear = (String) fieldValues.get("universityFiscalYear");
066            if (!StringUtils.isEmpty(valueFiscalYear)) {
067                try {
068                    int year = Integer.parseInt(valueFiscalYear);
069                }
070                catch (NumberFormatException e) {
071                    GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_CUSTOM, new String[] { "Fiscal Year must be a four-digit number" });
072                    throw new ValidationException("errors in search criteria");
073                }
074            }
075            
076            if (!allRequiredsForAccountSearch(fieldValues) && !allRequiredsForDocumentSearch(fieldValues)) {
077                GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_GL_LOOKUP_ENTRY_NON_MATCHING_REQUIRED_FIELDS, new String[] {});
078                throw new ValidationException("errors in search criteria");
079            }
080        }
081    
082        /**
083         * Determines if all the required values for an account based search are present - fiscal year, chart, account number, and fiscal period code
084         * @param fieldValues field values to check
085         * @return true if all the account-based required search fields are present; false otherwise
086         */
087        protected boolean allRequiredsForAccountSearch(Map fieldValues) {
088            final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
089            final String chartOfAccountsCode = (String)fieldValues.get("chartOfAccountsCode");
090            final String accountNumber = (String)fieldValues.get("accountNumber");
091            final String fiscalPeriodCode = (String)fieldValues.get("universityFiscalPeriodCode");
092            return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(chartOfAccountsCode) && !StringUtils.isBlank(accountNumber) && !StringUtils.isBlank(fiscalPeriodCode);
093        }
094        
095        /**
096         * Determines if all the required values for an document based search are present - fiscal year and document number
097         * @param fieldValues field values to check
098         * @return true if all the document-based required search fields are present; false otherwise
099         */
100        protected boolean allRequiredsForDocumentSearch(Map fieldValues) {
101            final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
102            final String documentNumber = (String)fieldValues.get("documentNumber");
103            return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(documentNumber);
104        }
105    
106        /**
107         * Returns the url for any drill down links within the lookup
108         * @param bo the business object with a property being drilled down on
109         * @param propertyName the name of the property being drilled down on
110         * @return a String with the URL of the property
111         * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
112         */
113        @Override
114        public HtmlData getInquiryUrl(BusinessObject businessObject, String propertyName) {
115            if (KFSPropertyConstants.DOCUMENT_NUMBER.equals(propertyName)) {
116                if (businessObject instanceof Entry) {
117                    Entry entry = (Entry) businessObject;
118                    return new AnchorHtmlData(new InquirableFinancialDocument().getInquirableDocumentUrl(entry), KNSConstants.EMPTY_STRING, "view entry "+entry.toString());
119                }
120            }
121            return (new EntryInquirableImpl()).getInquiryUrl(businessObject, propertyName);
122        }
123    
124        /**
125         * Generates the list of search results for this inquiry
126         * @param fieldValues the field values of the query to carry out
127         * @return List the search results returned by the lookup
128         * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map)
129         */
130        @Override
131        public List getSearchResults(Map fieldValues) {
132            setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION));
133            setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY));
134    
135            // get the pending entry option. This method must be prior to the get search results
136            String pendingEntryOption = this.getSelectedPendingEntryOption(fieldValues);
137    
138            // get the search result collection
139            Collection searchResultsCollection = getLookupService().findCollectionBySearch(getBusinessObjectClass(), fieldValues);
140    
141            // update search results according to the selected pending entry option
142            updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, false, false);
143    
144            // get the actual size of all qualified search results
145            Long actualSize = new Long(entryService.getEntryRecordCount(fieldValues));
146    
147            return this.buildSearchResultList(searchResultsCollection, actualSize);
148        }
149    
150        /**
151         * Updates pending entries before their results are included in the lookup results
152         * 
153         * @param entryCollection a collection of balance entries
154         * @param fieldValues the map containing the search fields and values
155         * @param isApproved flag whether the approved entries or all entries will be processed
156         * @param isConsolidated flag whether the results are consolidated or not
157         * @param isCostShareExcluded flag whether the user selects to see the results with cost share subaccount
158         * @see org.kuali.module.gl.web.lookupable.AbstractGLLookupableImpl#updateEntryCollection(java.util.Collection, java.util.Map,
159         *      boolean, boolean, boolean)
160         */
161        @Override
162        protected void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive) {
163            LOG.debug("updateEntryCollection started");
164    
165            // convert the field names of balance object into corresponding ones of pending entry object
166            Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues);
167    
168            // go through the pending entries to update the balance collection
169            Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForEntry(pendingEntryFieldValues, isApproved);
170    
171            String pendingOption = isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY;
172            UniversityDate today = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
173            String currentFiscalPeriodCode = today.getUniversityFiscalAccountingPeriod();
174            Integer currentFiscalYear = today.getUniversityFiscalYear();
175            Date postDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
176    
177            while (pendingEntryIterator.hasNext()) {
178                GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next();
179    
180                // Gotta circumvent date checks in the scrubberValidator. They totally kill performance.
181                if (pendingEntry.getUniversityFiscalYear() == null) {
182                    pendingEntry.setUniversityFiscalYear(currentFiscalYear);
183                }
184    
185                if (pendingEntry.getUniversityFiscalPeriodCode() == null) {
186                    pendingEntry.setUniversityFiscalPeriodCode(currentFiscalPeriodCode);
187                }
188    
189                scrubberValidator.validateForInquiry(pendingEntry);
190                
191                Entry entry = new Entry(pendingEntry, postDate);
192                
193                String approvedCode = pendingEntry.getFinancialDocumentApprovedCode();
194                String description = Constant.DocumentApprovedCode.getDescription(approvedCode);
195                entry.getDummyBusinessObject().setPendingEntryOption(description);
196                
197                entryCollection.add(entry);
198            }
199        }
200    
201        /**
202         * Sets the scrubberValidator attribute value.
203         * 
204         * @param scrubberValidator The scrubberValidator to set.
205         */
206        public void setScrubberValidator(ScrubberValidator scrubberValidator) {
207            this.scrubberValidator = scrubberValidator;
208        }
209    
210        /**
211         * Sets the entryService attribute value.
212         * 
213         * @param entryService The entryService to set.
214         */
215        public void setEntryService(EntryService entryService) {
216            this.entryService = entryService;
217        }
218    }