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.EMPLOYEE_FUNDING_EXPENSE_OBJECT_TYPE_CODE; 019 import static org.kuali.kfs.module.ld.LaborConstants.BalanceInquiries.EMPLOYEE_FUNDING_NORMAL_OP_EXPENSE_OBJECT_TYPE_CODE; 020 021 import java.util.ArrayList; 022 import java.util.Collection; 023 import java.util.Collections; 024 import java.util.HashMap; 025 import java.util.Iterator; 026 import java.util.List; 027 import java.util.Map; 028 029 import org.apache.commons.lang.ArrayUtils; 030 import org.apache.commons.lang.StringUtils; 031 import org.kuali.kfs.gl.Constant; 032 import org.kuali.kfs.module.ld.businessobject.EmployeeFunding; 033 import org.kuali.kfs.module.ld.businessobject.LaborLedgerPendingEntry; 034 import org.kuali.kfs.module.ld.businessobject.inquiry.AbstractLaborInquirableImpl; 035 import org.kuali.kfs.module.ld.businessobject.inquiry.EmployeeFundingInquirableImpl; 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.service.LaborLedgerPendingEntryService; 040 import org.kuali.kfs.module.ld.util.DebitCreditUtil; 041 import org.kuali.kfs.sys.KFSConstants; 042 import org.kuali.kfs.sys.KFSPropertyConstants; 043 import org.kuali.kfs.sys.ObjectUtil; 044 import org.kuali.rice.kns.bo.BusinessObject; 045 import org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl; 046 import org.kuali.rice.kns.lookup.CollectionIncomplete; 047 import org.kuali.rice.kns.lookup.HtmlData; 048 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData; 049 import org.kuali.rice.kns.util.BeanPropertyComparator; 050 import org.kuali.rice.kns.util.KualiDecimal; 051 052 /** 053 * The EmployeeFundingLookupableHelperServiceImpl class is the front-end for all Employee Funding balance inquiry processing. 054 */ 055 public class EmployeeFundingLookupableHelperServiceImpl extends AbstractLookupableHelperServiceImpl { 056 private static final org.apache.commons.logging.Log LOG = org.apache.commons.logging.LogFactory.getLog(EmployeeFundingLookupableHelperServiceImpl.class); 057 058 private LaborLedgerBalanceService laborLedgerBalanceService; 059 private LaborInquiryOptionsService laborInquiryOptionsService; 060 private LaborLedgerPendingEntryService laborLedgerPendingEntryService; 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 EmployeeFunding employeeFunding = (EmployeeFunding) bo; 069 AbstractLaborInquirableImpl positionDataDetailsInquirable = new PositionDataDetailsInquirableImpl(); 070 071 Map<String, String> fieldValues = new HashMap<String, String>(); 072 fieldValues.put(propertyName, employeeFunding.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 079 return (new EmployeeFundingInquirableImpl()).getInquiryUrl(bo, propertyName); 080 } 081 082 /** 083 * @see org.kuali.rice.kns.lookup.Lookupable#gfetSearchResults(java.util.Map) 084 */ 085 @Override 086 public List getSearchResults(Map fieldValues) { 087 setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION)); 088 setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY)); 089 090 boolean showBlankLine = this.showBlankLines(fieldValues); 091 fieldValues.remove(Constant.BLANK_LINE_OPTION); 092 093 // get the pending entry option. This method must be prior to the get search results 094 String pendingEntryOption = laborInquiryOptionsService.getSelectedPendingEntryOption(fieldValues); 095 096 // test if the consolidation option is selected or not 097 boolean isConsolidated = false; 098 099 Collection<EmployeeFunding> searchResultsCollection = laborLedgerBalanceService.findEmployeeFundingWithCSFTracker(fieldValues, isConsolidated); 100 101 if (!showBlankLine) { 102 Collection<EmployeeFunding> tempSearchResultsCollection = new ArrayList<EmployeeFunding>(); 103 for (EmployeeFunding employeeFunding : searchResultsCollection) { 104 if (employeeFunding.getCurrentAmount().isNonZero() || employeeFunding.getOutstandingEncumbrance().isNonZero()) { 105 tempSearchResultsCollection.add(employeeFunding); 106 } 107 } 108 searchResultsCollection = tempSearchResultsCollection; 109 } 110 111 // update search results according to the selected pending entry option 112 updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, isConsolidated); 113 114 // get the actual size of all qualified search results 115 Long actualSize = new Long(searchResultsCollection.size()); 116 117 return this.buildSearchResultList(searchResultsCollection, actualSize); 118 } 119 120 private boolean showBlankLines(Map fieldValues) { 121 String pendingEntryOption = (String) fieldValues.get(Constant.BLANK_LINE_OPTION); 122 return Constant.SHOW_BLANK_LINE.equals(pendingEntryOption) ? true : false; 123 } 124 125 /** 126 * build the serach result list from the given collection and the number of all qualified search results 127 * 128 * @param searchResultsCollection the given search results, which may be a subset of the qualified search results 129 * @param actualSize the number of all qualified search results 130 * @return the serach result list with the given results and actual size 131 */ 132 protected List buildSearchResultList(Collection searchResultsCollection, Long actualSize) { 133 CollectionIncomplete results = new CollectionIncomplete(searchResultsCollection, actualSize); 134 135 // sort list if default sort column given 136 List searchResults = (List) results; 137 List defaultSortColumns = getDefaultSortColumns(); 138 if (defaultSortColumns.size() > 0) { 139 Collections.sort(results, new BeanPropertyComparator(defaultSortColumns, true)); 140 } 141 return searchResults; 142 } 143 144 /** 145 * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#updateByPendingLedgerEntry(java.util.Collection, 146 * java.util.Map, java.lang.String, boolean) 147 */ 148 public void updateByPendingLedgerEntry(Collection entryCollection, Map fieldValues, String pendingEntryOption, boolean isConsolidated) { 149 150 // determine if search results need to be updated by pending ledger entries 151 if (Constant.ALL_PENDING_ENTRY.equals(pendingEntryOption)) { 152 updateEntryCollection(entryCollection, fieldValues, false, isConsolidated); 153 } 154 else if (Constant.APPROVED_PENDING_ENTRY.equals(pendingEntryOption)) { 155 updateEntryCollection(entryCollection, fieldValues, true, isConsolidated); 156 } 157 } 158 159 /** 160 * @see org.kuali.kfs.module.ld.service.LaborInquiryOptionsService#updateEntryCollection(java.util.Collection, java.util.Map, 161 * boolean, boolean) 162 */ 163 public void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated) { 164 // go through the pending entries to update the balance collection 165 Iterator<LaborLedgerPendingEntry> pendingEntryIterator = laborLedgerPendingEntryService.findPendingLedgerEntriesForLedgerBalance(fieldValues, isApproved); 166 167 while (pendingEntryIterator.hasNext()) { 168 LaborLedgerPendingEntry pendingEntry = pendingEntryIterator.next(); 169 170 if (!isEmployeeFunding(pendingEntry)) { 171 continue; 172 } 173 174 // if consolidated, change the following fields into the default values for consolidation 175 if (isConsolidated) { 176 pendingEntry.setSubAccountNumber(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER); 177 pendingEntry.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE); 178 pendingEntry.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE); 179 } 180 181 EmployeeFunding ledgerBalance = (EmployeeFunding) laborLedgerBalanceService.findLedgerBalance(entryCollection, pendingEntry, getKeyList()); 182 if (ledgerBalance == null) { 183 ledgerBalance = new EmployeeFunding(); 184 ObjectUtil.buildObject(ledgerBalance, pendingEntry); 185 entryCollection.add(ledgerBalance); 186 } 187 else { 188 laborLedgerBalanceService.updateLedgerBalance(ledgerBalance, pendingEntry); 189 } 190 updateAmount(ledgerBalance, pendingEntry); 191 } 192 } 193 194 /** 195 * update the amount of the given employee funding with the given pending entry 196 * 197 * @param employeeFunding the given employee funding 198 * @param pendingEntry the given pending entry 199 */ 200 private void updateAmount(EmployeeFunding employeeFunding, LaborLedgerPendingEntry pendingEntry) { 201 String balanceTypeCode = pendingEntry.getFinancialBalanceTypeCode(); 202 String debitCreditCode = pendingEntry.getTransactionDebitCreditCode(); 203 KualiDecimal amount = DebitCreditUtil.getNumericAmount(pendingEntry.getTransactionLedgerEntryAmount(), pendingEntry.getTransactionDebitCreditCode()); 204 205 if (StringUtils.equals(balanceTypeCode, KFSConstants.BALANCE_TYPE_ACTUAL)) { 206 employeeFunding.setCurrentAmount(amount.add(employeeFunding.getCurrentAmount())); 207 } 208 else if (StringUtils.equals(balanceTypeCode, KFSConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE)) { 209 employeeFunding.setOutstandingEncumbrance(amount.add(employeeFunding.getOutstandingEncumbrance())); 210 } 211 } 212 213 /** 214 * determine whether the given pending entry is qualified to be processed as an employee funding 215 * 216 * @param pendingEntry the given pending entry 217 * @return true if the given pending entry is qualified to be processed as an employee funding; otherwise, false 218 */ 219 private boolean isEmployeeFunding(LaborLedgerPendingEntry pendingEntry) { 220 String balanceTypeCode = pendingEntry.getFinancialBalanceTypeCode(); 221 222 if (StringUtils.equals(balanceTypeCode, KFSConstants.BALANCE_TYPE_ACTUAL)) { 223 String objectTypeCode = pendingEntry.getFinancialObjectTypeCode(); 224 String[] objectTypeCodes = { EMPLOYEE_FUNDING_EXPENSE_OBJECT_TYPE_CODE, EMPLOYEE_FUNDING_NORMAL_OP_EXPENSE_OBJECT_TYPE_CODE }; 225 226 return ArrayUtils.contains(objectTypeCodes, objectTypeCode) ? true : false; 227 } 228 229 if (StringUtils.equals(balanceTypeCode, KFSConstants.BALANCE_TYPE_INTERNAL_ENCUMBRANCE)) { 230 return true; 231 } 232 233 return false; 234 } 235 236 /** 237 * construct the primary key list of the business object 238 * 239 * @return the primary key list of the business object 240 */ 241 private List<String> getKeyList() { 242 List<String> keyList = new ArrayList<String>(); 243 keyList.add(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR); 244 keyList.add(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE); 245 keyList.add(KFSPropertyConstants.ACCOUNT_NUMBER); 246 keyList.add(KFSPropertyConstants.SUB_ACCOUNT_NUMBER); 247 keyList.add(KFSPropertyConstants.FINANCIAL_OBJECT_CODE); 248 keyList.add(KFSPropertyConstants.FINANCIAL_SUB_OBJECT_CODE); 249 keyList.add(KFSPropertyConstants.FINANCIAL_OBJECT_TYPE_CODE); 250 keyList.add(KFSPropertyConstants.POSITION_NUMBER); 251 keyList.add(KFSPropertyConstants.EMPLID); 252 return keyList; 253 } 254 255 /** 256 * Sets the laborLedgerBalanceService attribute value. 257 * 258 * @param laborLedgerBalanceService The laborLedgerBalanceService to set. 259 */ 260 public void setLaborLedgerBalanceService(LaborLedgerBalanceService laborLedgerBalanceService) { 261 this.laborLedgerBalanceService = laborLedgerBalanceService; 262 } 263 264 /** 265 * Sets the laborInquiryOptionsService attribute value. 266 * 267 * @param laborInquiryOptionsService The laborInquiryOptionsService to set. 268 */ 269 public void setLaborInquiryOptionsService(LaborInquiryOptionsService laborInquiryOptionsService) { 270 this.laborInquiryOptionsService = laborInquiryOptionsService; 271 } 272 273 /** 274 * Sets the laborLedgerPendingEntryService attribute value. 275 * 276 * @param laborLedgerPendingEntryService The laborLedgerPendingEntryService to set. 277 */ 278 public void setLaborLedgerPendingEntryService(LaborLedgerPendingEntryService laborLedgerPendingEntryService) { 279 this.laborLedgerPendingEntryService = laborLedgerPendingEntryService; 280 } 281 }