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.Collections;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.commons.lang.StringUtils;
27  import org.kuali.ole.gl.Constant;
28  import org.kuali.ole.gl.service.impl.StringHelper;
29  import org.kuali.ole.sys.OLEPropertyConstants;
30  import org.kuali.ole.sys.document.service.DebitDeterminerService;
31  import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
32  import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl;
33  import org.kuali.rice.kns.lookup.HtmlData;
34  import org.kuali.rice.kns.web.struts.form.LookupForm;
35  import org.kuali.rice.kns.web.ui.Column;
36  import org.kuali.rice.kns.web.ui.Field;
37  import org.kuali.rice.kns.web.ui.ResultRow;
38  import org.kuali.rice.kns.web.ui.Row;
39  import org.kuali.rice.krad.bo.BusinessObject;
40  import org.kuali.rice.krad.lookup.CollectionIncomplete;
41  import org.kuali.rice.krad.util.BeanPropertyComparator;
42  import org.kuali.rice.krad.util.ObjectUtils;
43  
44  /**
45   * The abstract parent class for GL Lookupables, providing base implementations of methods
46   * to make adding new lookupable reports easier
47   */
48  public abstract class AbstractGeneralLedgerLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl {
49  
50      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AbstractGeneralLedgerLookupableHelperServiceImpl.class);
51  
52      protected GeneralLedgerPendingEntryService generalLedgerPendingEntryService;
53      protected DebitDeterminerService debitDeterminerService;
54  
55  
56      /**
57       * This method overides that in parent class so that the maintainance actions are surpressed
58       *
59       * @returns links to edit and copy maintenance action for the current maintenance record. For GL balance inquire, there are no
60       *          maintenance links.
61       */
62      @Override
63      public List<HtmlData> getCustomActionUrls(BusinessObject bo, List pkNames) {
64          return super.getEmptyActionUrls();
65      }
66  
67      /**
68       * This method tests if the user selects to see the general ledger pending entries
69       *
70       * @param fieldValues the map containing the search fields and values
71       * @return the value of pending entry option
72       */
73      protected String getSelectedPendingEntryOption(Map fieldValues) {
74          // truncate the non-property filed
75          String pendingEntryOption = (String) fieldValues.get(Constant.PENDING_ENTRY_OPTION);
76          fieldValues.remove(Constant.PENDING_ENTRY_OPTION);
77  
78          return pendingEntryOption;
79      }
80  
81      /**
82       * This method tests if the user selects to see the Debit/Credit entries
83       *
84       * @param fieldValues the map containing the search fields and values
85       * @return the value of pending entry option
86       */
87      protected String getDebitCreditOption(Map fieldValues) {
88          // truncate the non-property filed
89          String debitCreditOption = (String) fieldValues.get(Constant.DEBIT_CREDIT_OPTION);
90          fieldValues.remove(Constant.DEBIT_CREDIT_OPTION);
91  
92          return debitCreditOption;
93      }
94  
95      /**
96       * This method tests if the user selects to see the reports by monthly or accumulated
97       *
98       * @param fieldValues the map containing the search fields and values
99       * @return the value of amount view option
100      */
101     protected String getSelectedAmountViewOption(Map fieldValues) {
102 
103         String amountViewOption = Constant.EMPTY_STRING;
104         if (fieldValues.containsKey(Constant.AMOUNT_VIEW_OPTION)) {
105             amountViewOption = (String) fieldValues.get(Constant.AMOUNT_VIEW_OPTION);
106 
107             // truncate the non-property filed
108             fieldValues.remove(Constant.AMOUNT_VIEW_OPTION);
109         }
110         return amountViewOption;
111     }
112 
113     /**
114      * This method tests if the user selects to see the details or consolidated results
115      *
116      * @param fieldValues the map containing the search fields and values
117      * @return true if consolidation is selected and subaccount is not specified
118      * 
119      * KRAD Conversion: Lookupable performs checking for a particular attribute and return true or false.
120      * This method is called from AccountBalanceLookupableHelperServiceImpl.java, BalanceLookupableHelperServiceImpl.java,
121      * CashBalanceLookupableHelperServiceImpl.java in gl module.  
122      */
123     protected boolean isConsolidationSelected(Map fieldValues) {
124         // truncate the non-property filed
125         String consolidationOption = (String) fieldValues.get(Constant.CONSOLIDATION_OPTION);
126         fieldValues.remove(Constant.CONSOLIDATION_OPTION);
127 
128         // detail option would be used
129         if (Constant.DETAIL.equals(consolidationOption)) {
130             return false;
131         }
132 
133         // if the subAccountNumber is specified, detail option could be used
134         String subAccountNumber = (String) fieldValues.get(OLEPropertyConstants.SUB_ACCOUNT_NUMBER);
135         if (!StringUtils.isBlank(subAccountNumber)) {
136             this.changeFieldValue(Constant.CONSOLIDATION_OPTION, Constant.DETAIL);
137             return false;
138         }
139 
140         // if the subObjectCode is specified, detail option could be used
141         String subObjectCode = (String) fieldValues.get(OLEPropertyConstants.SUB_OBJECT_CODE);
142         if (!StringUtils.isBlank(subObjectCode)) {
143             this.changeFieldValue(Constant.CONSOLIDATION_OPTION, Constant.DETAIL);
144             return false;
145         }
146 
147         // if the objectTypeCode is specified, detail option could be used
148         String objectTypeCode = (String) fieldValues.get(OLEPropertyConstants.OBJECT_TYPE_CODE);
149         if (!StringUtils.isBlank(objectTypeCode)) {
150             this.changeFieldValue(Constant.CONSOLIDATION_OPTION, Constant.DETAIL);
151             return false;
152         }
153         return true;
154     }
155 
156     /**
157      * This method tests if the user selects to see the results with cost share subaccount
158      *
159      * @param fieldValues the map containing the search fields and values
160      * @return true if inclusive option is selected
161      */
162     protected boolean isCostShareInclusive(Map fieldValues) {
163         // TODO: is this method being called?
164         // truncate the non-property filed
165         String costShareOption = (String) fieldValues.get(Constant.COST_SHARE_OPTION);
166         fieldValues.remove(Constant.COST_SHARE_OPTION);
167 
168         if (costShareOption.equals(Constant.COST_SHARE_INCLUDE)) {
169             return true;
170         }
171         return false;
172     }
173 
174 
175     /**
176      * build the serach result list from the given collection and the number of all qualified search results
177      *
178      * @param searchResultsCollection the given search results, which may be a subset of the qualified search results
179      * @param actualSize the number of all qualified search results
180      * @return the serach result list with the given results and actual size
181      */
182     protected List buildSearchResultList(Collection searchResultsCollection, Long actualSize) {
183         CollectionIncomplete results = new CollectionIncomplete(searchResultsCollection, actualSize);
184 
185         // sort list if default sort column given
186         List searchResults = results;
187         List defaultSortColumns = getDefaultSortColumns();
188         if (defaultSortColumns.size() > 0) {
189             Collections.sort(results, new BeanPropertyComparator(defaultSortColumns, true));
190         }
191         return searchResults;
192     }
193 
194     @Override
195     public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
196         Map fieldsForLookup = new HashMap(lookupForm.getFieldsForLookup());
197         String debitCreditOption = getDebitCreditOption(fieldsForLookup);
198 
199         Collection displayList = super.performLookup(lookupForm, resultTable, bounded);
200         updateByDebitCreditOption(resultTable, debitCreditOption);
201         return displayList;
202 
203     }
204 
205 
206 
207     protected void updateByDebitCreditOption(Collection resultTable , String debitCreditOption) {
208 
209         if (Constant.DEBIT_CREDIT_EXCLUDE.equals(debitCreditOption)){
210             for(Object table : resultTable) {
211                 ResultRow  row = (ResultRow)table;
212                 List<Column> columns = row.getColumns();
213                 ArrayList<Column> newColumnList = new ArrayList<Column>();
214                 String debitCreditCode = null;
215                 String objectType = null;
216                 Column amountCol = null;
217                 boolean setAmount = false ;
218                 for(Column col: columns) {
219 
220                     String propertyName = col.getPropertyName();
221                     if (propertyName.equals(OLEPropertyConstants.TRANSACTION_DEBIT_CREDIT_CODE)) {
222                         debitCreditCode = col.getPropertyValue();
223                     }
224                     else if (!propertyName.equals(OLEPropertyConstants.TRANSACTION_LEDGER_ENTRY_AMOUNT)){
225                         newColumnList.add(col);
226                     }
227 
228                     if(propertyName.equals(OLEPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE)) {
229                         objectType = col.getPropertyValue();
230                     }
231 
232                     if (propertyName.equals(OLEPropertyConstants.TRANSACTION_LEDGER_ENTRY_AMOUNT)) {
233                         amountCol = col;
234                     }
235 
236                     // determine the amount sign
237                     if (!newColumnList.contains(amountCol)) {
238                         if ((!StringHelper.isNullOrEmpty(objectType)) && (!StringHelper.isNullOrEmpty(debitCreditCode))
239                                 && ObjectUtils.isNotNull(amountCol)) {
240                             String amount = debitDeterminerService.getConvertedAmount(objectType, debitCreditCode, amountCol.getPropertyValue());
241                             amountCol.setPropertyValue(amount);
242                             newColumnList.add(amountCol);
243 
244                         }
245                     }
246 
247                 }
248 
249                 row.setColumns(newColumnList);
250             }
251         }
252 
253     }
254 
255     /**
256      * This method is used to update amounts of the given entries with the corresponding pending amounts. It is a factory that
257      * executes the update methods of individual derived classes.
258      *
259      * @param entryCollection a collection of balance entries
260      * @param fieldValues the map containing the search fields and values
261      * @param pendingEntryOption flag whether the approved entries or all entries will be processed
262      * @param isCostShareInclusive flag whether the user selects to see the results with cost share subaccount
263      * @param isConsolidated flag whether the results are consolidated or not
264      */
265     protected void updateByPendingLedgerEntry(Collection entryCollection, Map fieldValues, String pendingEntryOption, boolean isConsolidated, boolean isCostShareInclusive) {
266 
267         // determine if search results need to be updated by pending ledger entries
268         if (Constant.ALL_PENDING_ENTRY.equals(pendingEntryOption)) {
269             updateEntryCollection(entryCollection, fieldValues, false, isConsolidated, isCostShareInclusive);
270         }
271         else if (Constant.APPROVED_PENDING_ENTRY.equals(pendingEntryOption)) {
272             updateEntryCollection(entryCollection, fieldValues, true, isConsolidated, isCostShareInclusive);
273         }
274     }
275 
276     /**
277      * This method is an abstract method and implemented to update the given entry collection by the children classes. It is called
278      * by updateByPendingLedgerEntry method.
279      *
280      * @param entryCollection a collection of balance entries
281      * @param fieldValues the map containing the search fields and values
282      * @param isApproved flag whether the approved entries or all entries will be processed
283      * @param isCostShareInclusive flag whether the user selects to see the results with cost share subaccount
284      * @param isConsolidated flag whether the results are consolidated or not
285      */
286     protected abstract void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive);
287 
288     // change the value of the field with the given field name into the given field value
289     private void changeFieldValue(String fieldName, String fieldValue) {
290         for (Iterator rowIterator = getRows().iterator(); rowIterator.hasNext();) {
291             Row row = (Row) rowIterator.next();
292 
293             for (Iterator fieldIterator = row.getFields().iterator(); fieldIterator.hasNext();) {
294                 Field field = (Field) fieldIterator.next();
295 
296                 if (field.getPropertyName().equals(fieldName)) {
297                     field.setPropertyValue(fieldValue);
298                 }
299             }
300         }
301     }
302 
303     protected GeneralLedgerPendingEntryService getGeneralLedgerPendingEntryService() {
304         return generalLedgerPendingEntryService;
305     }
306 
307     public void setGeneralLedgerPendingEntryService(GeneralLedgerPendingEntryService generalLedgerPendingEntryService) {
308         this.generalLedgerPendingEntryService = generalLedgerPendingEntryService;
309     }
310 
311     protected DebitDeterminerService getDebitDeterminerService() {
312         return debitDeterminerService;
313     }
314 
315     public void setDebitDeterminerService(DebitDeterminerService debitDeterminerService) {
316         this.debitDeterminerService = debitDeterminerService;
317     }
318 
319 
320 
321 }