001/*
002 * Copyright 2006 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 */
016package org.kuali.ole.gl.businessobject.lookup;
017
018import java.sql.Date;
019import java.util.Collection;
020import java.util.Iterator;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.commons.lang.StringUtils;
025import org.kuali.ole.gl.Constant;
026import org.kuali.ole.gl.businessobject.Entry;
027import org.kuali.ole.gl.businessobject.inquiry.EntryInquirableImpl;
028import org.kuali.ole.gl.businessobject.inquiry.InquirableFinancialDocument;
029import org.kuali.ole.gl.service.EntryService;
030import org.kuali.ole.gl.service.ScrubberValidator;
031import org.kuali.ole.sys.OLEConstants;
032import org.kuali.ole.sys.OLEKeyConstants;
033import org.kuali.ole.sys.OLEPropertyConstants;
034import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
035import org.kuali.ole.sys.businessobject.UniversityDate;
036import org.kuali.ole.sys.context.SpringContext;
037import org.kuali.ole.sys.service.UniversityDateService;
038import org.kuali.rice.core.api.datetime.DateTimeService;
039import org.kuali.rice.kns.lookup.HtmlData;
040import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
041import org.kuali.rice.krad.bo.BusinessObject;
042import org.kuali.rice.krad.exception.ValidationException;
043import org.kuali.rice.krad.util.GlobalVariables;
044import org.kuali.rice.krad.util.KRADConstants;
045
046/**
047 * An extension of KualiLookupableImpl to support entry lookups
048 */
049public 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", OLEKeyConstants.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", OLEKeyConstants.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 (OLEPropertyConstants.DOCUMENT_NUMBER.equals(propertyName)) {
116            if (businessObject instanceof Entry) {
117                Entry entry = (Entry) businessObject;
118                return new AnchorHtmlData(new InquirableFinancialDocument().getInquirableDocumentUrl(entry), KRADConstants.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(OLEConstants.BACK_LOCATION));
133        setDocFormKey((String) fieldValues.get(OLEConstants.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        String debitCreditOption  = this.getDebitCreditOption(fieldValues);
139
140        // get the search result collection
141        Collection searchResultsCollection = getLookupService().findCollectionBySearch(getBusinessObjectClass(), fieldValues);
142
143        // update search results according to the selected pending entry option
144        updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, false, false);
145
146        // get the actual size of all qualified search results
147        Long actualSize = new Long(entryService.getEntryRecordCount(fieldValues));
148
149        return this.buildSearchResultList(searchResultsCollection, actualSize);
150    }
151
152    /**
153     * Updates pending entries before their results are included in the lookup results
154     *
155     * @param entryCollection a collection of balance entries
156     * @param fieldValues the map containing the search fields and values
157     * @param isApproved flag whether the approved entries or all entries will be processed
158     * @param isConsolidated flag whether the results are consolidated or not
159     * @param isCostShareExcluded flag whether the user selects to see the results with cost share subaccount
160     * @see org.kuali.module.gl.web.lookupable.AbstractGLLookupableImpl#updateEntryCollection(java.util.Collection, java.util.Map,
161     *      boolean, boolean, boolean)
162     */
163    @Override
164    protected void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive) {
165        LOG.debug("updateEntryCollection started");
166
167        // convert the field names of balance object into corresponding ones of pending entry object
168        Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues);
169
170        // go through the pending entries to update the balance collection
171        Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForEntry(pendingEntryFieldValues, isApproved);
172
173        String pendingOption = isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY;
174        UniversityDate today = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
175        String currentFiscalPeriodCode = today.getUniversityFiscalAccountingPeriod();
176        Integer currentFiscalYear = today.getUniversityFiscalYear();
177        Date postDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
178
179        while (pendingEntryIterator.hasNext()) {
180            GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next();
181
182            // Gotta circumvent date checks in the scrubberValidator. They totally kill performance.
183            if (pendingEntry.getUniversityFiscalYear() == null) {
184                pendingEntry.setUniversityFiscalYear(currentFiscalYear);
185            }
186
187            if (pendingEntry.getUniversityFiscalPeriodCode() == null) {
188                pendingEntry.setUniversityFiscalPeriodCode(currentFiscalPeriodCode);
189            }
190
191            scrubberValidator.validateForInquiry(pendingEntry);
192
193            Entry entry = new Entry(pendingEntry, postDate);
194
195            String approvedCode = pendingEntry.getFinancialDocumentApprovedCode();
196            String description = Constant.DocumentApprovedCode.getDescription(approvedCode);
197            entry.getDummyBusinessObject().setPendingEntryOption(description);
198
199            entryCollection.add(entry);
200        }
201    }
202
203    /**
204     * Sets the scrubberValidator attribute value.
205     *
206     * @param scrubberValidator The scrubberValidator to set.
207     */
208    public void setScrubberValidator(ScrubberValidator scrubberValidator) {
209        this.scrubberValidator = scrubberValidator;
210    }
211
212    /**
213     * Sets the entryService attribute value.
214     *
215     * @param entryService The entryService to set.
216     */
217    public void setEntryService(EntryService entryService) {
218        this.entryService = entryService;
219    }
220}