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.apache.commons.collections.IteratorUtils.toList; 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.List; 025 import java.util.Map; 026 027 import org.apache.commons.lang.StringUtils; 028 import org.kuali.kfs.gl.Constant; 029 import org.kuali.kfs.gl.businessobject.TransientBalanceInquiryAttributes; 030 import org.kuali.kfs.integration.ld.LaborLedgerObject; 031 import org.kuali.kfs.module.ld.LaborKeyConstants; 032 import org.kuali.kfs.module.ld.businessobject.AccountStatusCurrentFunds; 033 import org.kuali.kfs.module.ld.businessobject.July1PositionFunding; 034 import org.kuali.kfs.module.ld.businessobject.LaborObject; 035 import org.kuali.kfs.module.ld.businessobject.LedgerBalance; 036 import org.kuali.kfs.module.ld.businessobject.inquiry.AbstractLaborInquirableImpl; 037 import org.kuali.kfs.module.ld.businessobject.inquiry.CurrentFundsInquirableImpl; 038 import org.kuali.kfs.module.ld.businessobject.inquiry.PositionDataDetailsInquirableImpl; 039 import org.kuali.kfs.module.ld.dataaccess.LaborDao; 040 import org.kuali.kfs.module.ld.service.LaborInquiryOptionsService; 041 import org.kuali.kfs.module.ld.service.LaborLedgerBalanceService; 042 import org.kuali.kfs.sys.KFSConstants; 043 import org.kuali.kfs.sys.KFSPropertyConstants; 044 import org.kuali.kfs.sys.ObjectUtil; 045 import org.kuali.rice.kns.bo.BusinessObject; 046 import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl; 047 import org.kuali.rice.kns.lookup.CollectionIncomplete; 048 import org.kuali.rice.kns.lookup.HtmlData; 049 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData; 050 import org.kuali.rice.kns.service.BusinessObjectService; 051 import org.kuali.rice.kns.util.BeanPropertyComparator; 052 import org.kuali.rice.kns.util.GlobalVariables; 053 import org.kuali.rice.kns.util.KualiDecimal; 054 import org.kuali.rice.kns.web.ui.Row; 055 056 /** 057 * Service implementation for the CurrentFundsLookupableHelperServiceImpl class is the front-end for all current funds balance 058 * inquiry processing. 059 */ 060 public class CurrentFundsLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl { 061 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CurrentFundsLookupableHelperServiceImpl.class); 062 private LaborDao laborDao; 063 private LaborLedgerBalanceService balanceService; 064 private LaborInquiryOptionsService laborInquiryOptionsService; 065 private BusinessObjectService businessObjectService; 066 067 /** 068 * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String) 069 */ 070 @Override 071 public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) { 072 if (KFSPropertyConstants.POSITION_NUMBER.equals(propertyName)) { 073 LedgerBalance balance = (LedgerBalance) bo; 074 AbstractLaborInquirableImpl positionDataDetailsInquirable = new PositionDataDetailsInquirableImpl(); 075 076 Map<String, String> fieldValues = new HashMap<String, String>(); 077 fieldValues.put(propertyName, balance.getPositionNumber()); 078 079 BusinessObject positionData = positionDataDetailsInquirable.getBusinessObject(fieldValues); 080 081 return positionData == null ? new AnchorHtmlData(KFSConstants.EMPTY_STRING, KFSConstants.EMPTY_STRING) : positionDataDetailsInquirable.getInquiryUrl(positionData, propertyName); 082 } 083 return (new CurrentFundsInquirableImpl()).getInquiryUrl(bo, propertyName); 084 } 085 086 /** 087 * Gets a list with the fields that will be displayed on page 088 * 089 * @param fieldValues list of fields that are used as a key to filter out data 090 * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map) 091 */ 092 @Override 093 public List getSearchResults(Map fieldValues) { 094 LOG.info("getSearchResults() - Entry"); 095 096 boolean unbounded = false; 097 Long actualCountIfTruncated = new Long(0); 098 099 setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION)); 100 setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY)); 101 102 // get the pending entry option. This method must be prior to the get search results 103 String pendingEntryOption = laborInquiryOptionsService.getSelectedPendingEntryOption(fieldValues); 104 105 // get the consolidation option 106 boolean isConsolidated = laborInquiryOptionsService.isConsolidationSelected(fieldValues, (Collection<Row>) getRows()); 107 108 String searchObjectCodeVal = (String) fieldValues.get(KFSPropertyConstants.FINANCIAL_OBJECT_CODE); 109 // Check for a valid labor object code for this inquiry 110 if (StringUtils.isNotBlank(searchObjectCodeVal)) { 111 Map objectCodeFieldValues = new HashMap(); 112 objectCodeFieldValues.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, fieldValues.get(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR)); 113 objectCodeFieldValues.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, fieldValues.get(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE)); 114 objectCodeFieldValues.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, searchObjectCodeVal); 115 116 LaborLedgerObject foundObjectCode = (LaborLedgerObject) businessObjectService.findByPrimaryKey(LaborObject.class, objectCodeFieldValues); 117 118 if (foundObjectCode == null) { 119 GlobalVariables.getMessageMap().putError(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, LaborKeyConstants.ERROR_INVALID_LABOR_OBJECT_CODE, "2"); 120 return new CollectionIncomplete(new ArrayList(), actualCountIfTruncated); 121 } 122 } 123 124 // Parse the map and call the DAO to process the inquiry 125 Collection<AccountStatusCurrentFunds> searchResultsCollection = buildCurrentFundsCollection(toList(laborDao.getCurrentFunds(fieldValues, isConsolidated)), isConsolidated, pendingEntryOption); 126 127 // update search results according to the selected pending entry option 128 laborInquiryOptionsService.updateCurrentFundsByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, isConsolidated); 129 130 // gets the July1st budget amount column. 131 Collection<July1PositionFunding> july1PositionFundings = laborDao.getJuly1(fieldValues); 132 this.updateJuly1BalanceAmount(searchResultsCollection, july1PositionFundings, isConsolidated); 133 134 // sort list if default sort column given 135 List searchResults = (List) searchResultsCollection; 136 List defaultSortColumns = getDefaultSortColumns(); 137 if (defaultSortColumns.size() > 0) { 138 Collections.sort(searchResults, new BeanPropertyComparator(defaultSortColumns, true)); 139 } 140 return new CollectionIncomplete(searchResults, actualCountIfTruncated); 141 } 142 143 /** 144 * Adds the july1 budget amount to each account found in the 145 * 146 * @param searchResultsCollection collection with the list of current funds where the amount is added 147 * @param july1PositionFundings collection of current funds with july1st budget amounts 148 * @param isConsolidated 149 */ 150 private void updateJuly1BalanceAmount(Collection<AccountStatusCurrentFunds> searchResultsCollection, Collection<July1PositionFunding> july1PositionFundings, boolean isConsolidated) { 151 for (July1PositionFunding july1PositionFunding : july1PositionFundings) { 152 for (AccountStatusCurrentFunds accountStatus : searchResultsCollection) { 153 boolean found = ObjectUtil.equals(accountStatus, july1PositionFunding, accountStatus.getKeyFieldList(isConsolidated)); 154 if (found) { 155 accountStatus.setJuly1BudgetAmount(accountStatus.getJuly1BudgetAmount().add(july1PositionFunding.getJuly1BudgetAmount())); 156 } 157 } 158 } 159 } 160 161 /** 162 * Returns a list with the current funds. 163 * 164 * @param iterator the iterator of search results of account status 165 * @param isConsolidated determine if the consolidated result is desired 166 * @param pendingEntryOption the given pending entry option that can be no, approved or all 167 * @return the current funds collection 168 */ 169 private Collection<AccountStatusCurrentFunds> buildCurrentFundsCollection(Collection collection, boolean isConsolidated, String pendingEntryOption) { 170 Collection<AccountStatusCurrentFunds> retval = null; 171 172 if (isConsolidated) { 173 retval = buildCosolidatedCurrentFundsCollection(collection, pendingEntryOption); 174 } 175 else { 176 retval = buildDetailedCurrentFundsCollection(collection, pendingEntryOption); 177 } 178 return retval; 179 } 180 181 /** 182 * Builds the current funds collection with consolidation option from an iterator 183 * 184 * @param iterator 185 * @param pendingEntryOption the selected pending entry option 186 * @return the consolidated current funds collection 187 */ 188 private Collection<AccountStatusCurrentFunds> buildCosolidatedCurrentFundsCollection(Collection collection, String pendingEntryOption) { 189 Collection<AccountStatusCurrentFunds> retval = new ArrayList<AccountStatusCurrentFunds>(); 190 for (Object collectionEntry : collection) { 191 if (collectionEntry.getClass().isArray()) { 192 int i = 0; 193 Object[] array = (Object[]) collectionEntry; 194 AccountStatusCurrentFunds cf = new AccountStatusCurrentFunds(); 195 LOG.debug("element length " + array.length); 196 for (Object element : array) { 197 LOG.debug("I found this element " + element); 198 } 199 200 if (AccountStatusCurrentFunds.class.isAssignableFrom(getBusinessObjectClass())) { 201 try { 202 cf = (AccountStatusCurrentFunds) getBusinessObjectClass().newInstance(); 203 } 204 catch (Exception e) { 205 LOG.warn("Using " + AccountStatusCurrentFunds.class + " for results because I couldn't instantiate the " + getBusinessObjectClass()); 206 } 207 } 208 else { 209 LOG.warn("Using " + AccountStatusCurrentFunds.class + " for results because I couldn't instantiate the " + getBusinessObjectClass()); 210 } 211 212 cf.setUniversityFiscalYear(new Integer(array[i++].toString())); 213 cf.setChartOfAccountsCode(array[i++].toString()); 214 cf.setAccountNumber(array[i++].toString()); 215 216 String subAccountNumber = Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER; 217 cf.setSubAccountNumber(subAccountNumber); 218 219 cf.setBalanceTypeCode(array[i++].toString()); 220 cf.setFinancialObjectCode(array[i++].toString()); 221 222 cf.setEmplid(array[i++].toString()); 223 cf.setPositionNumber(array[i++].toString()); 224 225 cf.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE); 226 cf.setObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE); 227 228 cf.setAccountLineAnnualBalanceAmount(new KualiDecimal(array[i++].toString())); 229 cf.setBeginningBalanceLineAmount(new KualiDecimal(array[i++].toString())); 230 cf.setContractsGrantsBeginningBalanceAmount(new KualiDecimal(array[i++].toString())); 231 232 cf.setMonth1Amount(new KualiDecimal(array[i++].toString())); 233 234 cf.setDummyBusinessObject(new TransientBalanceInquiryAttributes()); 235 cf.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption); 236 cf.setOutstandingEncum(getOutstandingEncum(cf)); 237 238 cf.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption); 239 cf.getDummyBusinessObject().setConsolidationOption(Constant.CONSOLIDATION); 240 241 retval.add(cf); 242 } 243 } 244 return retval; 245 } 246 247 /** 248 * Builds the current funds collection with detail option from an iterator 249 * 250 * @param iterator the current funds iterator 251 * @param pendingEntryOption the selected pending entry option 252 * @return the detailed balance collection 253 */ 254 private Collection<AccountStatusCurrentFunds> buildDetailedCurrentFundsCollection(Collection collection, String pendingEntryOption) { 255 Collection<AccountStatusCurrentFunds> retval = new ArrayList<AccountStatusCurrentFunds>(); 256 257 for (LedgerBalance balance : ((Collection<LedgerBalance>) collection)) { 258 AccountStatusCurrentFunds cf = new AccountStatusCurrentFunds(); 259 ObjectUtil.buildObject(cf, balance); 260 261 cf.setDummyBusinessObject(new TransientBalanceInquiryAttributes()); 262 cf.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption); 263 cf.setOutstandingEncum(getOutstandingEncum(cf)); 264 265 cf.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption); 266 cf.getDummyBusinessObject().setConsolidationOption(Constant.DETAIL); 267 268 retval.add(cf); 269 } 270 return retval; 271 } 272 273 /** 274 * Gets the outstanding encumbrance amount 275 * 276 * @param AccountStatusCurrentFunds 277 * @param Map fieldValues 278 */ 279 private KualiDecimal getOutstandingEncum(AccountStatusCurrentFunds bo) { 280 Map<String, String> fieldValues = new HashMap(); 281 fieldValues.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, bo.getUniversityFiscalYear().toString()); 282 fieldValues.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, bo.getChartOfAccountsCode()); 283 fieldValues.put(KFSPropertyConstants.ACCOUNT_NUMBER, bo.getAccountNumber()); 284 285 if (!bo.getSubAccountNumber().equals(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER)) { 286 fieldValues.put(KFSPropertyConstants.SUB_ACCOUNT_NUMBER, bo.getSubAccountNumber()); 287 } 288 289 fieldValues.put(KFSPropertyConstants.FINANCIAL_OBJECT_CODE, bo.getFinancialObjectCode()); 290 291 if (!bo.getFinancialSubObjectCode().equals(Constant.CONSOLIDATED_SUB_OBJECT_CODE)) { 292 fieldValues.put(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE, bo.getFinancialSubObjectCode()); 293 } 294 fieldValues.put(KFSPropertyConstants.FINANCIAL_BALANCE_TYPE_CODE, KFSConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE); // Encumberance 295 // Balance 296 // Type 297 fieldValues.put(KFSPropertyConstants.EMPLID, bo.getEmplid()); 298 LOG.debug("using " + fieldValues.values()); 299 LOG.debug("using " + fieldValues.keySet()); 300 return (KualiDecimal) laborDao.getEncumbranceTotal(fieldValues); 301 } 302 303 /** 304 * Sets the balanceService attribute value. 305 * 306 * @param balanceService The balanceService to set. 307 */ 308 public void setBalanceService(LaborLedgerBalanceService balanceService) { 309 this.balanceService = balanceService; 310 } 311 312 /** 313 * Sets the laborDao attribute value. 314 * 315 * @param laborDao The laborDao to set. 316 */ 317 public void setLaborDao(LaborDao laborDao) { 318 this.laborDao = laborDao; 319 } 320 321 /** 322 * Sets the laborInquiryOptionsService attribute value. 323 * 324 * @param laborInquiryOptionsService The laborInquiryOptionsService to set. 325 */ 326 public void setLaborInquiryOptionsService(LaborInquiryOptionsService laborInquiryOptionsService) { 327 this.laborInquiryOptionsService = laborInquiryOptionsService; 328 } 329 330 /** 331 * Sets the businessObjectService attribute value. 332 * 333 * @param businessObjectService The businessObjectService to set. 334 */ 335 public void setBusinessObjectService(BusinessObjectService businessObjectService) { 336 this.businessObjectService = businessObjectService; 337 } 338 339 }