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.businessobject.lookup;
20  
21  import java.sql.Date;
22  import java.util.Collection;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.kuali.kfs.gl.Constant;
29  import org.kuali.kfs.gl.businessobject.Entry;
30  import org.kuali.kfs.gl.businessobject.inquiry.EntryInquirableImpl;
31  import org.kuali.kfs.gl.businessobject.inquiry.InquirableFinancialDocument;
32  import org.kuali.kfs.gl.service.EntryService;
33  import org.kuali.kfs.gl.service.ScrubberValidator;
34  import org.kuali.kfs.integration.ld.LaborModuleService;
35  import org.kuali.kfs.sys.KFSConstants;
36  import org.kuali.kfs.sys.KFSKeyConstants;
37  import org.kuali.kfs.sys.KFSPropertyConstants;
38  import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
39  import org.kuali.kfs.sys.businessobject.UniversityDate;
40  import org.kuali.kfs.sys.context.SpringContext;
41  import org.kuali.kfs.sys.service.UniversityDateService;
42  import org.kuali.rice.core.api.datetime.DateTimeService;
43  import org.kuali.rice.kns.lookup.HtmlData;
44  import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
45  import org.kuali.rice.krad.bo.BusinessObject;
46  import org.kuali.rice.krad.exception.ValidationException;
47  import org.kuali.rice.krad.util.GlobalVariables;
48  import org.kuali.rice.krad.util.KRADConstants;
49  
50  /**
51   * An extension of KualiLookupableImpl to support entry lookups
52   */
53  public class EntryLookupableHelperServiceImpl extends AbstractGeneralLedgerLookupableHelperServiceImpl {
54      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EntryLookupableHelperServiceImpl.class);
55  
56      private ScrubberValidator scrubberValidator;
57      private EntryService entryService;
58      private volatile static LaborModuleService laborModuleService;
59  
60      /**
61       * Validate the university fiscal year that has been queried on
62       * 
63       * @param fieldValues the queried fields
64       * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
65       */
66      @Override
67      public void validateSearchParameters(Map fieldValues) {
68          super.validateSearchParameters(fieldValues);
69  
70          String valueFiscalYear = (String) fieldValues.get("universityFiscalYear");
71          if (!StringUtils.isEmpty(valueFiscalYear)) {
72              try {
73                  int year = Integer.parseInt(valueFiscalYear);
74              }
75              catch (NumberFormatException e) {
76                  GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_CUSTOM, new String[] { "Fiscal Year must be a four-digit number" });
77                  throw new ValidationException("errors in search criteria");
78              }
79          }
80          
81          if (!allRequiredsForAccountSearch(fieldValues) && !allRequiredsForDocumentSearch(fieldValues)) {
82              GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_GL_LOOKUP_ENTRY_NON_MATCHING_REQUIRED_FIELDS, new String[] {});
83              throw new ValidationException("errors in search criteria");
84          }
85      }
86  
87      /**
88       * Determines if all the required values for an account based search are present - fiscal year, chart, account number, and fiscal period code
89       * @param fieldValues field values to check
90       * @return true if all the account-based required search fields are present; false otherwise
91       */
92      protected boolean allRequiredsForAccountSearch(Map fieldValues) {
93          final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
94          final String chartOfAccountsCode = (String)fieldValues.get("chartOfAccountsCode");
95          final String accountNumber = (String)fieldValues.get("accountNumber");
96          final String fiscalPeriodCode = (String)fieldValues.get("universityFiscalPeriodCode");
97          return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(chartOfAccountsCode) && !StringUtils.isBlank(accountNumber) && !StringUtils.isBlank(fiscalPeriodCode);
98      }
99      
100     /**
101      * Determines if all the required values for an document based search are present - fiscal year and document number
102      * @param fieldValues field values to check
103      * @return true if all the document-based required search fields are present; false otherwise
104      */
105     protected boolean allRequiredsForDocumentSearch(Map fieldValues) {
106         final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
107         final String documentNumber = (String)fieldValues.get("documentNumber");
108         return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(documentNumber);
109     }
110 
111     /**
112      * Returns the url for any drill down links within the lookup
113      * @param bo the business object with a property being drilled down on
114      * @param propertyName the name of the property being drilled down on
115      * @return a String with the URL of the property
116      * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
117      */
118     @Override
119     public HtmlData getInquiryUrl(BusinessObject businessObject, String propertyName) {
120         if (KFSPropertyConstants.DOCUMENT_NUMBER.equals(propertyName)) {
121             if (businessObject instanceof Entry) {
122                 Entry entry = (Entry) businessObject;
123                 if (getLaborModuleService().getLaborLedgerGLOriginCodes() != null && !getLaborModuleService().getLaborLedgerGLOriginCodes().isEmpty() && getLaborModuleService().getLaborLedgerGLOriginCodes().contains(entry.getFinancialSystemOriginationCode())) {
124                     return getLaborModuleService().getInquiryUrlForGeneralLedgerEntryDocumentNumber(entry);
125                 }
126                 return new AnchorHtmlData(new InquirableFinancialDocument().getInquirableDocumentUrl(entry), KRADConstants.EMPTY_STRING, "view entry "+entry.toString());
127             }
128         }
129         return (new EntryInquirableImpl()).getInquiryUrl(businessObject, propertyName);
130     }
131 
132     /**
133      * Generates the list of search results for this inquiry
134      * @param fieldValues the field values of the query to carry out
135      * @return List the search results returned by the lookup
136      * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map)
137      */
138     @Override
139     public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
140         setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION));
141         setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY));
142 
143         // get the pending entry option. This method must be prior to the get search results
144         String pendingEntryOption = this.getSelectedPendingEntryOption(fieldValues);
145 
146         String debitCreditOption  = this.getDebitCreditOption(fieldValues);
147 
148         // get the search result collection
149         Collection searchResultsCollection = getLookupService().findCollectionBySearch(getBusinessObjectClass(), fieldValues);
150         int searchResultsCollectionSize = searchResultsCollection.size();
151 
152         // update search results according to the selected pending entry option
153         updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, false, false);
154 
155         // get the actual size of all qualified search results
156         Long actualSize = new Long(entryService.getEntryRecordCount(fieldValues));
157         
158         // calculate how many pending entries were included in the original results
159         int numPendingEntriesAdded = searchResultsCollection.size() - searchResultsCollectionSize;
160         actualSize += numPendingEntriesAdded;
161 
162         return this.buildSearchResultList(searchResultsCollection, actualSize);
163     }
164 
165     /**
166      * Updates pending entries before their results are included in the lookup results
167      * 
168      * @param entryCollection a collection of balance entries
169      * @param fieldValues the map containing the search fields and values
170      * @param isApproved flag whether the approved entries or all entries will be processed
171      * @param isConsolidated flag whether the results are consolidated or not
172      * @param isCostShareExcluded flag whether the user selects to see the results with cost share subaccount
173      * @see org.kuali.module.gl.web.lookupable.AbstractGLLookupableImpl#updateEntryCollection(java.util.Collection, java.util.Map,
174      *      boolean, boolean, boolean)
175      */
176     @Override
177     protected void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive) {
178         LOG.debug("updateEntryCollection started");
179 
180         // convert the field names of balance object into corresponding ones of pending entry object
181         Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues);
182 
183         // go through the pending entries to update the balance collection
184         Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForEntry(pendingEntryFieldValues, isApproved);
185 
186         String pendingOption = isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY;
187         UniversityDate today = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
188         String currentFiscalPeriodCode = today.getUniversityFiscalAccountingPeriod();
189         Integer currentFiscalYear = today.getUniversityFiscalYear();
190         Date postDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
191 
192         while (pendingEntryIterator.hasNext()) {
193             GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next();
194 
195             // Gotta circumvent date checks in the scrubberValidator. They totally kill performance.
196             if (pendingEntry.getUniversityFiscalYear() == null) {
197                 pendingEntry.setUniversityFiscalYear(currentFiscalYear);
198             }
199 
200             if (pendingEntry.getUniversityFiscalPeriodCode() == null) {
201                 pendingEntry.setUniversityFiscalPeriodCode(currentFiscalPeriodCode);
202             }
203 
204             scrubberValidator.validateForInquiry(pendingEntry);
205             
206             Entry entry = new Entry(pendingEntry, postDate);
207             
208             String approvedCode = pendingEntry.getFinancialDocumentApprovedCode();
209             String description = Constant.DocumentApprovedCode.getDescription(approvedCode);
210             entry.getDummyBusinessObject().setPendingEntryOption(description);
211             
212             entryCollection.add(entry);
213         }
214     }
215 
216     /**
217      * Sets the scrubberValidator attribute value.
218      * 
219      * @param scrubberValidator The scrubberValidator to set.
220      */
221     public void setScrubberValidator(ScrubberValidator scrubberValidator) {
222         this.scrubberValidator = scrubberValidator;
223     }
224 
225     /**
226      * Sets the entryService attribute value.
227      * 
228      * @param entryService The entryService to set.
229      */
230     public void setEntryService(EntryService entryService) {
231         this.entryService = entryService;
232     }
233     
234     /**
235      * @return the system's configured implementation of the LaborModuleService
236      */
237     public LaborModuleService getLaborModuleService() {
238         if (laborModuleService == null) {
239             laborModuleService = SpringContext.getBean(LaborModuleService.class);
240         }
241         return laborModuleService;
242     }
243 }