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.module.ld.businessobject.lookup; 017 018 import static org.kuali.kfs.module.ld.LaborConstants.BalanceInquiries.BALANCE_TYPE_AC_AND_A21; 019 020 import java.util.ArrayList; 021 import java.util.Collection; 022 import java.util.Collections; 023 import java.util.HashMap; 024 import java.util.Iterator; 025 import java.util.List; 026 import java.util.Map; 027 028 import org.apache.commons.lang.StringUtils; 029 import org.apache.commons.logging.Log; 030 import org.apache.commons.logging.LogFactory; 031 import org.kuali.kfs.gl.Constant; 032 import org.kuali.kfs.gl.OJBUtility; 033 import org.kuali.kfs.module.ld.businessobject.LedgerBalance; 034 import org.kuali.kfs.module.ld.businessobject.inquiry.AbstractLaborInquirableImpl; 035 import org.kuali.kfs.module.ld.businessobject.inquiry.LedgerBalanceInquirableImpl; 036 import org.kuali.kfs.module.ld.businessobject.inquiry.PositionDataDetailsInquirableImpl; 037 import org.kuali.kfs.module.ld.service.LaborInquiryOptionsService; 038 import org.kuali.kfs.module.ld.service.LaborLedgerBalanceService; 039 import org.kuali.kfs.module.ld.util.ConsolidationUtil; 040 import org.kuali.kfs.sys.KFSConstants; 041 import org.kuali.kfs.sys.KFSPropertyConstants; 042 import org.kuali.rice.kns.bo.BusinessObject; 043 import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl; 044 import org.kuali.rice.kns.lookup.CollectionIncomplete; 045 import org.kuali.rice.kns.lookup.HtmlData; 046 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData; 047 import org.kuali.rice.kns.util.BeanPropertyComparator; 048 import org.kuali.rice.kns.util.GlobalVariables; 049 import org.kuali.rice.kns.util.KNSConstants; 050 import org.kuali.rice.kns.util.KualiDecimal; 051 052 /** 053 * Service implementation of LedgerBalanceLookupableHelperService. The class is the front-end for all Ledger balance inquiry 054 * processing. 055 */ 056 public class LedgerBalanceLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl { 057 private static final Log LOG = LogFactory.getLog(LedgerBalanceLookupableHelperServiceImpl.class); 058 059 private LaborLedgerBalanceService balanceService; 060 private LaborInquiryOptionsService laborInquiryOptionsService; 061 062 /** 063 * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String) 064 */ 065 @Override 066 public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) { 067 if (KFSPropertyConstants.POSITION_NUMBER.equals(propertyName)) { 068 LedgerBalance balance = (LedgerBalance) bo; 069 AbstractLaborInquirableImpl positionDataDetailsInquirable = new PositionDataDetailsInquirableImpl(); 070 071 Map<String, String> fieldValues = new HashMap<String, String>(); 072 fieldValues.put(propertyName, balance.getPositionNumber()); 073 074 BusinessObject positionData = positionDataDetailsInquirable.getBusinessObject(fieldValues); 075 076 return positionData == null ? new AnchorHtmlData(KFSConstants.EMPTY_STRING, KFSConstants.EMPTY_STRING) : positionDataDetailsInquirable.getInquiryUrl(positionData, propertyName); 077 } 078 return (new LedgerBalanceInquirableImpl()).getInquiryUrl(bo, propertyName); 079 } 080 081 /** 082 * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map) 083 */ 084 @Override 085 public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) { 086 String wildCards = ""; 087 for (int i = 0; i < KNSConstants.QUERY_CHARACTERS.length; i++) { 088 wildCards += KNSConstants.QUERY_CHARACTERS[i]; 089 } 090 091 if (wildCards.indexOf(fieldValues.get(KFSPropertyConstants.EMPLID).toString().trim()) != -1) { 092 // StringUtils.indexOfAny(fieldValues.get(KFSPropertyConstants.EMPLID).toString().trim(), KFSConstants.QUERY_CHARACTERS) 093 // != 0) { 094 List emptySearchResults = new ArrayList(); 095 Long actualCountIfTruncated = new Long(0); 096 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.EMPLID, KFSConstants.WILDCARD_NOT_ALLOWED_ON_FIELD, "Employee ID field "); 097 return new CollectionIncomplete(emptySearchResults, actualCountIfTruncated); 098 } 099 100 setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION)); 101 setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY)); 102 103 // get the pending entry option. This method must be prior to the get search results 104 String pendingEntryOption = laborInquiryOptionsService.getSelectedPendingEntryOption(fieldValues); 105 106 // test if the consolidation option is selected or not 107 boolean isConsolidated = laborInquiryOptionsService.isConsolidationSelected(fieldValues); 108 109 // get the input balance type code 110 String balanceTypeCode = fieldValues.get(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE); 111 boolean isA21Balance = StringUtils.isNotEmpty(balanceTypeCode) && BALANCE_TYPE_AC_AND_A21.equals(balanceTypeCode.trim()); 112 113 // get the ledger balances with actual balance type code 114 if (isA21Balance) { 115 fieldValues.put(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_ACTUAL); 116 } 117 Integer recordCountForActualBalance = balanceService.getBalanceRecordCount(fieldValues, isConsolidated); 118 Iterator actualBalanceIterator = balanceService.findBalance(fieldValues, isConsolidated); 119 Collection searchResultsCollection = buildBalanceCollection(actualBalanceIterator, isConsolidated, pendingEntryOption); 120 laborInquiryOptionsService.updateLedgerBalanceByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, isConsolidated); 121 122 // get the search result collection 123 Integer recordCountForEffortBalance = 0; 124 if (isA21Balance) { 125 fieldValues.put(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_A21); 126 recordCountForEffortBalance = balanceService.getBalanceRecordCount(fieldValues, isConsolidated); 127 128 Iterator effortBalanceIterator = balanceService.findBalance(fieldValues, isConsolidated); 129 Collection effortBalances = buildBalanceCollection(effortBalanceIterator, isConsolidated, pendingEntryOption); 130 laborInquiryOptionsService.updateLedgerBalanceByPendingLedgerEntry(effortBalances, fieldValues, pendingEntryOption, isConsolidated); 131 132 List<String> consolidationKeyList = LedgerBalance.getPrimaryKeyList(); 133 searchResultsCollection = ConsolidationUtil.consolidateA2Balances(searchResultsCollection, effortBalances, BALANCE_TYPE_AC_AND_A21, consolidationKeyList); 134 } 135 136 // get the actual size of all qualified search results 137 Integer recordCount = recordCountForActualBalance + recordCountForEffortBalance; 138 Long actualSize = OJBUtility.getResultActualSize(searchResultsCollection, recordCount, fieldValues, new LedgerBalance()); 139 140 return this.buildSearchResultList(searchResultsCollection, actualSize); 141 } 142 143 /** 144 * This method builds the balance collection based on the input iterator 145 * 146 * @param iterator the iterator of search results of balance 147 * @param isConsolidated determine if the consolidated result is desired 148 * @param pendingEntryOption the given pending entry option that can be no, approved or all 149 * @return the balance collection 150 */ 151 protected Collection buildBalanceCollection(Iterator iterator, boolean isConsolidated, String pendingEntryOption) { 152 Collection balanceCollection = null; 153 154 if (isConsolidated) { 155 balanceCollection = buildConsolidatedBalanceCollection(iterator, pendingEntryOption); 156 } 157 else { 158 balanceCollection = buildDetailedBalanceCollection(iterator, pendingEntryOption); 159 } 160 return balanceCollection; 161 } 162 163 /** 164 * This method builds the balance collection with consolidation option from an iterator 165 * 166 * @param iterator 167 * @param pendingEntryOption the selected pending entry option 168 * @return the consolidated balance collection 169 */ 170 protected Collection buildConsolidatedBalanceCollection(Iterator iterator, String pendingEntryOption) { 171 Collection balanceCollection = new ArrayList(); 172 173 while (iterator.hasNext()) { 174 Object collectionEntry = iterator.next(); 175 176 if (collectionEntry.getClass().isArray()) { 177 int i = 0; 178 Object[] array = (Object[]) collectionEntry; 179 LedgerBalance balance = new LedgerBalance(); 180 181 if (LedgerBalance.class.isAssignableFrom(getBusinessObjectClass())) { 182 try { 183 balance = (LedgerBalance) getBusinessObjectClass().newInstance(); 184 } 185 catch (Exception e) { 186 LOG.warn("Using " + LedgerBalance.class + " for results because I couldn't instantiate the " + getBusinessObjectClass()); 187 } 188 } 189 else { 190 LOG.warn("Using " + LedgerBalance.class + " for results because I couldn't instantiate the " + getBusinessObjectClass()); 191 } 192 193 balance.setUniversityFiscalYear(new Integer(array[i++].toString())); 194 balance.setChartOfAccountsCode(array[i++].toString()); 195 balance.setAccountNumber(array[i++].toString()); 196 197 String subAccountNumber = Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER; 198 balance.setSubAccountNumber(subAccountNumber); 199 200 balance.setBalanceTypeCode(array[i++].toString()); 201 balance.setFinancialObjectCode(array[i++].toString()); 202 203 balance.setEmplid(array[i++].toString()); 204 balance.setPositionNumber(array[i++].toString()); 205 206 balance.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE); 207 balance.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE); 208 209 balance.setAccountLineAnnualBalanceAmount(new KualiDecimal(array[i++].toString())); 210 balance.setBeginningBalanceLineAmount(new KualiDecimal(array[i++].toString())); 211 balance.setContractsGrantsBeginningBalanceAmount(new KualiDecimal(array[i++].toString())); 212 213 balance.setMonth1Amount(new KualiDecimal(array[i++].toString())); 214 balance.setMonth2Amount(new KualiDecimal(array[i++].toString())); 215 balance.setMonth3Amount(new KualiDecimal(array[i++].toString())); 216 balance.setMonth4Amount(new KualiDecimal(array[i++].toString())); 217 balance.setMonth5Amount(new KualiDecimal(array[i++].toString())); 218 balance.setMonth6Amount(new KualiDecimal(array[i++].toString())); 219 balance.setMonth7Amount(new KualiDecimal(array[i++].toString())); 220 balance.setMonth8Amount(new KualiDecimal(array[i++].toString())); 221 balance.setMonth9Amount(new KualiDecimal(array[i++].toString())); 222 223 balance.setMonth10Amount(new KualiDecimal(array[i++].toString())); 224 balance.setMonth11Amount(new KualiDecimal(array[i++].toString())); 225 balance.setMonth12Amount(new KualiDecimal(array[i++].toString())); 226 balance.setMonth13Amount(new KualiDecimal(array[i].toString())); 227 228 balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption); 229 balance.getDummyBusinessObject().setConsolidationOption(Constant.CONSOLIDATION); 230 231 balanceCollection.add(balance); 232 } 233 } 234 return balanceCollection; 235 } 236 237 /** 238 * This method builds the balance collection with detail option from an iterator 239 * 240 * @param iterator the balance iterator 241 * @param pendingEntryOption the selected pending entry option 242 * @return the detailed balance collection 243 */ 244 protected Collection buildDetailedBalanceCollection(Iterator iterator, String pendingEntryOption) { 245 Collection balanceCollection = new ArrayList(); 246 247 while (iterator.hasNext()) { 248 LedgerBalance copyBalance = (LedgerBalance) (iterator.next()); 249 250 LedgerBalance balance = new LedgerBalance(); 251 if (LedgerBalance.class.isAssignableFrom(getBusinessObjectClass())) { 252 try { 253 balance = (LedgerBalance) getBusinessObjectClass().newInstance(); 254 } 255 catch (Exception e) { 256 LOG.warn("Using " + LedgerBalance.class + " for results because I couldn't instantiate the " + getBusinessObjectClass()); 257 } 258 } 259 else { 260 LOG.warn("Using " + LedgerBalance.class + " for results because I couldn't instantiate the " + getBusinessObjectClass()); 261 } 262 263 balance.setUniversityFiscalYear(copyBalance.getUniversityFiscalYear()); 264 balance.setChartOfAccountsCode(copyBalance.getChartOfAccountsCode()); 265 balance.setAccountNumber(copyBalance.getAccountNumber()); 266 balance.setSubAccountNumber(copyBalance.getSubAccountNumber()); 267 balance.setBalanceTypeCode(copyBalance.getBalanceTypeCode()); 268 balance.setFinancialObjectCode(copyBalance.getFinancialObjectCode()); 269 balance.setEmplid(copyBalance.getEmplid()); 270 balance.setObjectId(copyBalance.getObjectId()); 271 balance.setPositionNumber(copyBalance.getPositionNumber()); 272 balance.setFinancialSubObjectCode(copyBalance.getFinancialSubObjectCode()); 273 balance.setFinancialObjectTypeCode(copyBalance.getFinancialObjectTypeCode()); 274 balance.setAccountLineAnnualBalanceAmount(copyBalance.getAccountLineAnnualBalanceAmount()); 275 balance.setBeginningBalanceLineAmount(copyBalance.getBeginningBalanceLineAmount()); 276 balance.setContractsGrantsBeginningBalanceAmount(copyBalance.getContractsGrantsBeginningBalanceAmount()); 277 balance.setMonth1Amount(copyBalance.getMonth1Amount()); 278 balance.setMonth2Amount(copyBalance.getMonth2Amount()); 279 balance.setMonth3Amount(copyBalance.getMonth3Amount()); 280 balance.setMonth4Amount(copyBalance.getMonth4Amount()); 281 balance.setMonth5Amount(copyBalance.getMonth5Amount()); 282 balance.setMonth6Amount(copyBalance.getMonth6Amount()); 283 balance.setMonth7Amount(copyBalance.getMonth7Amount()); 284 balance.setMonth8Amount(copyBalance.getMonth8Amount()); 285 balance.setMonth9Amount(copyBalance.getMonth9Amount()); 286 balance.setMonth10Amount(copyBalance.getMonth10Amount()); 287 balance.setMonth11Amount(copyBalance.getMonth11Amount()); 288 balance.setMonth12Amount(copyBalance.getMonth12Amount()); 289 balance.setMonth13Amount(copyBalance.getMonth13Amount()); 290 291 balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption); 292 balance.getDummyBusinessObject().setConsolidationOption(Constant.DETAIL); 293 294 balanceCollection.add(balance); 295 } 296 return balanceCollection; 297 } 298 299 /** 300 * build the serach result list from the given collection and the number of all qualified search results 301 * 302 * @param searchResultsCollection the given search results, which may be a subset of the qualified search results 303 * @param actualSize the number of all qualified search results 304 * @return the serach result list with the given results and actual size 305 */ 306 protected List buildSearchResultList(Collection searchResultsCollection, Long actualSize) { 307 CollectionIncomplete results = new CollectionIncomplete(searchResultsCollection, actualSize); 308 309 // sort list if default sort column given 310 List searchResults = (List) results; 311 List defaultSortColumns = getDefaultSortColumns(); 312 if (defaultSortColumns.size() > 0) { 313 Collections.sort(results, new BeanPropertyComparator(defaultSortColumns, true)); 314 } 315 return searchResults; 316 } 317 318 /** 319 * Sets the laborInquiryOptionsService attribute value. 320 * 321 * @param laborInquiryOptionsService The laborInquiryOptionsService to set. 322 */ 323 public void setLaborInquiryOptionsService(LaborInquiryOptionsService laborInquiryOptionsService) { 324 this.laborInquiryOptionsService = laborInquiryOptionsService; 325 } 326 327 /** 328 * Sets the balanceService attribute value. 329 * 330 * @param balanceService The balanceService to set. 331 */ 332 public void setBalanceService(LaborLedgerBalanceService balanceService) { 333 this.balanceService = balanceService; 334 } 335 336 /** 337 * Gets the balanceService attribute. 338 * 339 * @return Returns the balanceService. 340 */ 341 public LaborLedgerBalanceService getBalanceService() { 342 return balanceService; 343 } 344 }