View Javadoc
1   /*
2    * Copyright 2006 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.gl.businessobject.lookup;
17  
18  import java.util.ArrayList;
19  import java.util.Collection;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.kuali.ole.gl.Constant;
25  import org.kuali.ole.gl.GeneralLedgerConstants;
26  import org.kuali.ole.gl.OJBUtility;
27  import org.kuali.ole.gl.batch.service.BalanceCalculator;
28  import org.kuali.ole.gl.businessobject.Balance;
29  import org.kuali.ole.gl.businessobject.TransientBalanceInquiryAttributes;
30  import org.kuali.ole.gl.businessobject.inquiry.BalanceInquirableImpl;
31  import org.kuali.ole.gl.service.BalanceService;
32  import org.kuali.ole.sys.OLEConstants;
33  import org.kuali.ole.sys.OLEPropertyConstants;
34  import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
35  import org.kuali.rice.core.api.util.type.KualiDecimal;
36  import org.kuali.rice.kns.lookup.HtmlData;
37  import org.kuali.rice.kns.web.ui.Field;
38  import org.kuali.rice.kns.web.ui.Row;
39  import org.kuali.rice.krad.bo.BusinessObject;
40  
41  /**
42   * An extension of KualiLookupableImpl to support balance lookups
43   */
44  public class BalanceLookupableHelperServiceImpl extends AbstractGeneralLedgerLookupableHelperServiceImpl {
45      private BalanceCalculator postBalance;
46      private BalanceService balanceService;
47      private Map fieldValues;
48  
49      /**
50       * Returns the url for any drill down links within the lookup
51       * @param bo the business object with a property being drilled down on
52       * @param propertyName the name of the property being drilled down on
53       * @return a String with the URL of the property
54       * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.krad.bo.BusinessObject, java.lang.String)
55       */
56      @Override
57      public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
58          return (new BalanceInquirableImpl()).getInquiryUrl(bo, propertyName);
59      }
60  
61      /**
62       * Generates the list of search results for this inquiry
63       * @param fieldValues the field values of the query to carry out
64       * @return List the search results returned by the lookup
65       * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map)
66       * 
67       * KRAD Conversion: Lookupable modifies the search results based on the fields consolidated.
68       * But all field definitions are in data dictionary.
69       */
70      @Override
71      public List getSearchResults(Map fieldValues) {
72          setBackLocation((String) fieldValues.get(OLEConstants.BACK_LOCATION));
73          setDocFormKey((String) fieldValues.get(OLEConstants.DOC_FORM_KEY));
74  
75          // get the pending entry option. This method must be prior to the get search results
76          String pendingEntryOption = this.getSelectedPendingEntryOption(fieldValues);
77          
78          // KFSMI-410: need to get this before getting isConsolidated because this value will be removed.
79          String consolidationOption = (String) fieldValues.get(GeneralLedgerConstants.DummyBusinessObject.CONSOLIDATION_OPTION);
80          
81          // test if the consolidation option is selected or not
82          boolean isConsolidated = isConsolidationSelected(fieldValues);
83       
84          // KFSMI-410: added one more node for consolidationOption
85          if (consolidationOption.equals(Constant.EXCLUDE_SUBACCOUNTS)){
86              fieldValues.put(Constant.SUB_ACCOUNT_OPTION, OLEConstants.getDashSubAccountNumber());
87              isConsolidated = false;
88          } 
89         
90          // get Amount View Option and determine if the results has to be accumulated
91          String amountViewOption = getSelectedAmountViewOption(fieldValues);
92          boolean isAccumulated = amountViewOption.equals(Constant.ACCUMULATE);
93  
94          // get the search result collection
95          Iterator balanceIterator = balanceService.findBalance(fieldValues, isConsolidated);
96          Collection searchResultsCollection = this.buildBalanceCollection(balanceIterator, isConsolidated, pendingEntryOption);
97  
98          // update search results according to the selected pending entry option
99          updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, isConsolidated, false);
100 
101         // perform the accumulation of the amounts
102         this.accumulate(searchResultsCollection, isAccumulated);
103 
104         // get the actual size of all qualified search results
105         Integer recordCount = balanceService.getBalanceRecordCount(fieldValues, isConsolidated);
106         Long actualSize = OJBUtility.getResultActualSize(searchResultsCollection, recordCount, fieldValues, new Balance());
107 
108         return this.buildSearchResultList(searchResultsCollection, actualSize);
109     }
110 
111     /**
112      * This method builds the balance collection based on the input iterator
113      * 
114      * @param iterator the iterator of search results of balance
115      * @param isConsolidated determine if the consolidated result is desired
116      * @param pendingEntryOption the given pending entry option that can be no, approved or all
117      * @return the balance collection
118      */
119     private Collection buildBalanceCollection(Iterator iterator, boolean isConsolidated, String pendingEntryOption) {
120         Collection balanceCollection = null;
121 
122         if (isConsolidated) {
123             balanceCollection = buildConsolidatedBalanceCollection(iterator, pendingEntryOption);
124         }
125         else {
126             balanceCollection = buildDetailedBalanceCollection(iterator, pendingEntryOption);
127         }
128         return balanceCollection;
129     }
130 
131     /**
132      * This method builds the balance collection with consolidation option from an iterator
133      * 
134      * @param iterator th iterator of balance results
135      * @param pendingEntryOption the selected pending entry option
136      * @return the consolidated balance collection
137      */
138     private Collection buildConsolidatedBalanceCollection(Iterator iterator, String pendingEntryOption) {
139         Collection balanceCollection = new ArrayList();
140 
141         while (iterator.hasNext()) {
142             Object collectionEntry = iterator.next();
143 
144             if (collectionEntry.getClass().isArray()) {
145                 int i = 0;
146                 Object[] array = (Object[]) collectionEntry;
147                 Balance balance = new Balance();
148 
149                 balance.setUniversityFiscalYear(new Integer(array[i++].toString()));
150                 balance.setChartOfAccountsCode(array[i++].toString());
151                 balance.setAccountNumber(array[i++].toString());
152 
153                 String subAccountNumber = Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER;
154                 balance.setSubAccountNumber(subAccountNumber);
155 
156                 balance.setBalanceTypeCode(array[i++].toString());
157                 balance.setObjectCode(array[i++].toString());
158 
159                 balance.setSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE);
160                 balance.setObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE);
161 
162                 balance.setAccountLineAnnualBalanceAmount(new KualiDecimal(array[i++].toString()));
163                 balance.setBeginningBalanceLineAmount(new KualiDecimal(array[i++].toString()));
164                 balance.setContractsGrantsBeginningBalanceAmount(new KualiDecimal(array[i++].toString()));
165 
166                 balance.setMonth1Amount(new KualiDecimal(array[i++].toString()));
167                 balance.setMonth2Amount(new KualiDecimal(array[i++].toString()));
168                 balance.setMonth3Amount(new KualiDecimal(array[i++].toString()));
169                 balance.setMonth4Amount(new KualiDecimal(array[i++].toString()));
170                 balance.setMonth5Amount(new KualiDecimal(array[i++].toString()));
171                 balance.setMonth6Amount(new KualiDecimal(array[i++].toString()));
172                 balance.setMonth7Amount(new KualiDecimal(array[i++].toString()));
173                 balance.setMonth8Amount(new KualiDecimal(array[i++].toString()));
174                 balance.setMonth9Amount(new KualiDecimal(array[i++].toString()));
175 
176                 balance.setMonth10Amount(new KualiDecimal(array[i++].toString()));
177                 balance.setMonth11Amount(new KualiDecimal(array[i++].toString()));
178                 balance.setMonth12Amount(new KualiDecimal(array[i++].toString()));
179                 balance.setMonth13Amount(new KualiDecimal(array[i].toString()));
180 
181                 balance.setDummyBusinessObject(new TransientBalanceInquiryAttributes());
182                 balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption);
183 
184                 balanceCollection.add(balance);
185             }
186         }
187         return balanceCollection;
188     }
189 
190     /**
191      * This method builds the balance collection with detail option from an iterator
192      * 
193      * @param iterator the balance iterator
194      * @param pendingEntryOption the selected pending entry option
195      * @return the detailed balance collection
196      */
197     private Collection buildDetailedBalanceCollection(Iterator iterator, String pendingEntryOption) {
198         Collection balanceCollection = new ArrayList();
199 
200         while (iterator.hasNext()) {
201             Balance balance = (Balance) (iterator.next());
202 
203             balance.setDummyBusinessObject(new TransientBalanceInquiryAttributes());
204             balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption);
205 
206             balanceCollection.add(balance);
207         }
208         return balanceCollection;
209     }
210 
211     /**
212      * This method updates the balance collection with accumulated amounts if required (isAccumulated is true)
213      * 
214      * @param balanceCollection the balance collection to be updated
215      * @param isAccumulated determine if the accumulated result is desired
216      */
217     protected void accumulate(Collection balanceCollection, boolean isAccumulated) {
218 
219         if (isAccumulated) {
220             for (Iterator iterator = balanceCollection.iterator(); iterator.hasNext();) {
221                 Balance balance = (Balance) (iterator.next());
222                 accumulateByBalance(balance, isAccumulated);
223             }
224         }
225     }
226 
227     /**
228      * This method computes the accumulate amount of the given balance and updates its fields
229      * 
230      * @param balance the given balance object
231      * @param isAccumulated determine if the accumulated result is desired
232      */
233     private void accumulateByBalance(Balance balance, boolean isAccumulated) {
234 
235         KualiDecimal annualAmount = balance.getAccountLineAnnualBalanceAmount();
236         KualiDecimal beginningAmount = balance.getBeginningBalanceLineAmount();
237         KualiDecimal CGBeginningAmount = balance.getContractsGrantsBeginningBalanceAmount();
238 
239         KualiDecimal month0Amount = beginningAmount.add(CGBeginningAmount);
240         KualiDecimal month1Amount = balance.getMonth1Amount();
241         month1Amount = accumulateAmount(month1Amount, month0Amount, isAccumulated);
242         balance.setMonth1Amount(month1Amount);
243 
244         KualiDecimal month2Amount = balance.getMonth2Amount();
245         month2Amount = accumulateAmount(month2Amount, month1Amount, isAccumulated);
246         balance.setMonth2Amount(month2Amount);
247 
248         KualiDecimal month3Amount = balance.getMonth3Amount();
249         month3Amount = accumulateAmount(month3Amount, month2Amount, isAccumulated);
250         balance.setMonth3Amount(month3Amount);
251 
252         KualiDecimal month4Amount = balance.getMonth4Amount();
253         month4Amount = accumulateAmount(month4Amount, month3Amount, isAccumulated);
254         balance.setMonth4Amount(month4Amount);
255 
256         KualiDecimal month5Amount = balance.getMonth5Amount();
257         month5Amount = accumulateAmount(month5Amount, month4Amount, isAccumulated);
258         balance.setMonth5Amount(month5Amount);
259 
260         KualiDecimal month6Amount = balance.getMonth6Amount();
261         month6Amount = accumulateAmount(month6Amount, month5Amount, isAccumulated);
262         balance.setMonth6Amount(month6Amount);
263 
264         KualiDecimal month7Amount = balance.getMonth7Amount();
265         month7Amount = accumulateAmount(month7Amount, month6Amount, isAccumulated);
266         balance.setMonth7Amount(month7Amount);
267 
268         KualiDecimal month8Amount = balance.getMonth8Amount();
269         month8Amount = accumulateAmount(month8Amount, month7Amount, isAccumulated);
270         balance.setMonth8Amount(month8Amount);
271 
272         KualiDecimal month9Amount = balance.getMonth9Amount();
273         month9Amount = accumulateAmount(month9Amount, month8Amount, isAccumulated);
274         balance.setMonth9Amount(month9Amount);
275 
276         KualiDecimal month10Amount = balance.getMonth10Amount();
277         month10Amount = accumulateAmount(month10Amount, month9Amount, isAccumulated);
278         balance.setMonth10Amount(month10Amount);
279 
280         KualiDecimal month11Amount = balance.getMonth11Amount();
281         month11Amount = accumulateAmount(month11Amount, month10Amount, isAccumulated);
282         balance.setMonth11Amount(month11Amount);
283 
284         KualiDecimal month12Amount = balance.getMonth12Amount();
285         month12Amount = accumulateAmount(month12Amount, month11Amount, isAccumulated);
286         balance.setMonth12Amount(month12Amount);
287 
288         KualiDecimal month13Amount = balance.getMonth13Amount();
289         month13Amount = accumulateAmount(month13Amount, month12Amount, isAccumulated);
290         balance.setMonth13Amount(month13Amount);
291     }
292 
293     /**
294      * This method converts the amount from String and adds it with the input addend
295      * 
296      * @param stringAugend a String-type augend
297      * @param addend an addend
298      * @param isAccumulated determine if the accumulated result is desired
299      * @return the accumulated amount if accumulate option is selected; otherwise, the input amount itself
300      */
301     private KualiDecimal accumulateAmount(Object stringAugend, KualiDecimal addend, boolean isAccumulated) {
302 
303         KualiDecimal augend = new KualiDecimal(stringAugend.toString());
304         if (isAccumulated) {
305             augend = augend.add(addend);
306         }
307         return augend;
308     }
309 
310     /**
311      * Updates pending entries before their results are included in the lookup results
312      * 
313      * @param entryCollection a collection of balance entries
314      * @param fieldValues the map containing the search fields and values
315      * @param isApproved flag whether the approved entries or all entries will be processed
316      * @param isConsolidated flag whether the results are consolidated or not
317      * @param isCostShareExcluded flag whether the user selects to see the results with cost share subaccount
318      * @see org.kuali.module.gl.web.lookupable.AbstractGLLookupableImpl#updateEntryCollection(java.util.Collection, java.util.Map,
319      *      boolean, boolean, boolean)
320      */
321     public void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive) {
322 
323         // convert the field names of balance object into corresponding ones of pending entry object
324         Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues);
325 
326         // go through the pending entries to update the balance collection
327         Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForBalance(pendingEntryFieldValues, isApproved);
328         while (pendingEntryIterator.hasNext()) {
329             GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next();
330 
331             // if consolidated, change the following fields into the default values for consolidation
332             if (isConsolidated) {
333                 pendingEntry.setSubAccountNumber(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER);
334                 pendingEntry.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE);
335                 pendingEntry.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE);
336             }
337 
338             Balance balance = postBalance.findBalance(entryCollection, pendingEntry);
339 
340             String pendingEntryOption = isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY;
341             balance.setDummyBusinessObject(new TransientBalanceInquiryAttributes());
342             balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption);
343 
344             postBalance.updateBalance(pendingEntry, balance);
345         }
346     }
347 
348     /**
349      * Sets the postBalance attribute value.
350      * 
351      * @param postBalance The postBalance to set.
352      */
353     public void setPostBalance(BalanceCalculator postBalance) {
354         this.postBalance = postBalance;
355     }
356 
357     /**
358      * Sets the balanceService attribute value.
359      * 
360      * @param balanceService The balanceService to set.
361      */
362     public void setBalanceService(BalanceService balanceService) {
363         this.balanceService = balanceService;
364     }
365 
366     /**
367      * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getRows()
368      */
369     @Override
370     public List<Row> getRows() {
371         List<Row> superResults = super.getRows();
372         if (superResults != null) {
373             for (Row row : superResults) {
374                 for (Field field : row.getFields()) {
375                     if (OLEPropertyConstants.ACCOUNT_NUMBER.equals(field.getPropertyName())) {
376                         // because of limitations in BO Metadata service, the account quickfinder was going to prior year account instead of account, therefore
377                         // need to force it to go to Account (or whatever's mapped to the "account" reference in OJB
378                         Class clazz = getPersistenceStructureService().getBusinessObjectAttributeClass(businessObjectClass, OLEPropertyConstants.ACCOUNT);
379                         field.setQuickFinderClassNameImpl(clazz.getName());
380                         return superResults;
381                     }
382                 }
383             }
384         }
385         return superResults;
386     }
387 }