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 }