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.gl.businessobject.lookup;
017
018 import java.util.ArrayList;
019 import java.util.Collection;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Map;
023
024 import org.kuali.kfs.gl.Constant;
025 import org.kuali.kfs.gl.OJBUtility;
026 import org.kuali.kfs.gl.batch.service.BalanceCalculator;
027 import org.kuali.kfs.gl.businessobject.Balance;
028 import org.kuali.kfs.gl.businessobject.TransientBalanceInquiryAttributes;
029 import org.kuali.kfs.gl.businessobject.inquiry.BalanceInquirableImpl;
030 import org.kuali.kfs.gl.service.BalanceService;
031 import org.kuali.kfs.sys.KFSConstants;
032 import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry;
033 import org.kuali.rice.kns.bo.BusinessObject;
034 import org.kuali.rice.kns.lookup.HtmlData;
035 import org.kuali.rice.kns.util.KualiDecimal;
036
037 /**
038 * An extension of KualiLookupableImpl to support balance lookups
039 */
040 public class BalanceLookupableHelperServiceImpl extends AbstractGeneralLedgerLookupableHelperServiceImpl {
041 private BalanceCalculator postBalance;
042 private BalanceService balanceService;
043 private Map fieldValues;
044
045 /**
046 * Returns the url for any drill down links within the lookup
047 * @param bo the business object with a property being drilled down on
048 * @param propertyName the name of the property being drilled down on
049 * @return a String with the URL of the property
050 * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
051 */
052 @Override
053 public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
054 return (new BalanceInquirableImpl()).getInquiryUrl(bo, propertyName);
055 }
056
057 /**
058 * Generates the list of search results for this inquiry
059 * @param fieldValues the field values of the query to carry out
060 * @return List the search results returned by the lookup
061 * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map)
062 */
063 @Override
064 public List getSearchResults(Map fieldValues) {
065 setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION));
066 setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY));
067
068 // get the pending entry option. This method must be prior to the get search results
069 String pendingEntryOption = this.getSelectedPendingEntryOption(fieldValues);
070
071 // test if the consolidation option is selected or not
072 boolean isConsolidated = isConsolidationSelected(fieldValues);
073
074 // get Amount View Option and determine if the results has to be accumulated
075 String amountViewOption = getSelectedAmountViewOption(fieldValues);
076 boolean isAccumulated = amountViewOption.equals(Constant.ACCUMULATE);
077
078 // get the search result collection
079 Iterator balanceIterator = balanceService.findBalance(fieldValues, isConsolidated);
080 Collection searchResultsCollection = this.buildBalanceCollection(balanceIterator, isConsolidated, pendingEntryOption);
081
082 // update search results according to the selected pending entry option
083 updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, isConsolidated, false);
084
085 // perform the accumulation of the amounts
086 this.accumulate(searchResultsCollection, isAccumulated);
087
088 // get the actual size of all qualified search results
089 Integer recordCount = balanceService.getBalanceRecordCount(fieldValues, isConsolidated);
090 Long actualSize = OJBUtility.getResultActualSize(searchResultsCollection, recordCount, fieldValues, new Balance());
091
092 return this.buildSearchResultList(searchResultsCollection, actualSize);
093 }
094
095 /**
096 * This method builds the balance collection based on the input iterator
097 *
098 * @param iterator the iterator of search results of balance
099 * @param isConsolidated determine if the consolidated result is desired
100 * @param pendingEntryOption the given pending entry option that can be no, approved or all
101 * @return the balance collection
102 */
103 private Collection buildBalanceCollection(Iterator iterator, boolean isConsolidated, String pendingEntryOption) {
104 Collection balanceCollection = null;
105
106 if (isConsolidated) {
107 balanceCollection = buildConsolidatedBalanceCollection(iterator, pendingEntryOption);
108 }
109 else {
110 balanceCollection = buildDetailedBalanceCollection(iterator, pendingEntryOption);
111 }
112 return balanceCollection;
113 }
114
115 /**
116 * This method builds the balance collection with consolidation option from an iterator
117 *
118 * @param iterator th iterator of balance results
119 * @param pendingEntryOption the selected pending entry option
120 * @return the consolidated balance collection
121 */
122 private Collection buildConsolidatedBalanceCollection(Iterator iterator, String pendingEntryOption) {
123 Collection balanceCollection = new ArrayList();
124
125 while (iterator.hasNext()) {
126 Object collectionEntry = iterator.next();
127
128 if (collectionEntry.getClass().isArray()) {
129 int i = 0;
130 Object[] array = (Object[]) collectionEntry;
131 Balance balance = new Balance();
132
133 balance.setUniversityFiscalYear(new Integer(array[i++].toString()));
134 balance.setChartOfAccountsCode(array[i++].toString());
135 balance.setAccountNumber(array[i++].toString());
136
137 String subAccountNumber = Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER;
138 balance.setSubAccountNumber(subAccountNumber);
139
140 balance.setBalanceTypeCode(array[i++].toString());
141 balance.setObjectCode(array[i++].toString());
142
143 balance.setSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE);
144 balance.setObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE);
145
146 balance.setAccountLineAnnualBalanceAmount(new KualiDecimal(array[i++].toString()));
147 balance.setBeginningBalanceLineAmount(new KualiDecimal(array[i++].toString()));
148 balance.setContractsGrantsBeginningBalanceAmount(new KualiDecimal(array[i++].toString()));
149
150 balance.setMonth1Amount(new KualiDecimal(array[i++].toString()));
151 balance.setMonth2Amount(new KualiDecimal(array[i++].toString()));
152 balance.setMonth3Amount(new KualiDecimal(array[i++].toString()));
153 balance.setMonth4Amount(new KualiDecimal(array[i++].toString()));
154 balance.setMonth5Amount(new KualiDecimal(array[i++].toString()));
155 balance.setMonth6Amount(new KualiDecimal(array[i++].toString()));
156 balance.setMonth7Amount(new KualiDecimal(array[i++].toString()));
157 balance.setMonth8Amount(new KualiDecimal(array[i++].toString()));
158 balance.setMonth9Amount(new KualiDecimal(array[i++].toString()));
159
160 balance.setMonth10Amount(new KualiDecimal(array[i++].toString()));
161 balance.setMonth11Amount(new KualiDecimal(array[i++].toString()));
162 balance.setMonth12Amount(new KualiDecimal(array[i++].toString()));
163 balance.setMonth13Amount(new KualiDecimal(array[i].toString()));
164
165 balance.setDummyBusinessObject(new TransientBalanceInquiryAttributes());
166 balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption);
167
168 balanceCollection.add(balance);
169 }
170 }
171 return balanceCollection;
172 }
173
174 /**
175 * This method builds the balance collection with detail option from an iterator
176 *
177 * @param iterator the balance iterator
178 * @param pendingEntryOption the selected pending entry option
179 * @return the detailed balance collection
180 */
181 private Collection buildDetailedBalanceCollection(Iterator iterator, String pendingEntryOption) {
182 Collection balanceCollection = new ArrayList();
183
184 while (iterator.hasNext()) {
185 Balance balance = (Balance) (iterator.next());
186
187 balance.setDummyBusinessObject(new TransientBalanceInquiryAttributes());
188 balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption);
189
190 balanceCollection.add(balance);
191 }
192 return balanceCollection;
193 }
194
195 /**
196 * This method updates the balance collection with accumulated amounts if required (isAccumulated is true)
197 *
198 * @param balanceCollection the balance collection to be updated
199 * @param isAccumulated determine if the accumulated result is desired
200 */
201 private void accumulate(Collection balanceCollection, boolean isAccumulated) {
202
203 if (isAccumulated) {
204 for (Iterator iterator = balanceCollection.iterator(); iterator.hasNext();) {
205 Balance balance = (Balance) (iterator.next());
206 accumulateByBalance(balance, isAccumulated);
207 }
208 }
209 }
210
211 /**
212 * This method computes the accumulate amount of the given balance and updates its fields
213 *
214 * @param balance the given balance object
215 * @param isAccumulated determine if the accumulated result is desired
216 */
217 private void accumulateByBalance(Balance balance, boolean isAccumulated) {
218
219 KualiDecimal annualAmount = balance.getAccountLineAnnualBalanceAmount();
220 KualiDecimal beginningAmount = balance.getBeginningBalanceLineAmount();
221 KualiDecimal CGBeginningAmount = balance.getContractsGrantsBeginningBalanceAmount();
222
223 KualiDecimal month0Amount = beginningAmount.add(CGBeginningAmount);
224 KualiDecimal month1Amount = balance.getMonth1Amount();
225 month1Amount = accumulateAmount(month1Amount, month0Amount, isAccumulated);
226 balance.setMonth1Amount(month1Amount);
227
228 KualiDecimal month2Amount = balance.getMonth2Amount();
229 month2Amount = accumulateAmount(month2Amount, month1Amount, isAccumulated);
230 balance.setMonth2Amount(month2Amount);
231
232 KualiDecimal month3Amount = balance.getMonth3Amount();
233 month3Amount = accumulateAmount(month3Amount, month2Amount, isAccumulated);
234 balance.setMonth3Amount(month3Amount);
235
236 KualiDecimal month4Amount = balance.getMonth4Amount();
237 month4Amount = accumulateAmount(month4Amount, month3Amount, isAccumulated);
238 balance.setMonth4Amount(month4Amount);
239
240 KualiDecimal month5Amount = balance.getMonth5Amount();
241 month5Amount = accumulateAmount(month5Amount, month4Amount, isAccumulated);
242 balance.setMonth5Amount(month5Amount);
243
244 KualiDecimal month6Amount = balance.getMonth6Amount();
245 month6Amount = accumulateAmount(month6Amount, month5Amount, isAccumulated);
246 balance.setMonth6Amount(month6Amount);
247
248 KualiDecimal month7Amount = balance.getMonth7Amount();
249 month7Amount = accumulateAmount(month7Amount, month6Amount, isAccumulated);
250 balance.setMonth7Amount(month7Amount);
251
252 KualiDecimal month8Amount = balance.getMonth8Amount();
253 month8Amount = accumulateAmount(month8Amount, month7Amount, isAccumulated);
254 balance.setMonth8Amount(month8Amount);
255
256 KualiDecimal month9Amount = balance.getMonth9Amount();
257 month9Amount = accumulateAmount(month9Amount, month8Amount, isAccumulated);
258 balance.setMonth9Amount(month9Amount);
259
260 KualiDecimal month10Amount = balance.getMonth10Amount();
261 month10Amount = accumulateAmount(month10Amount, month9Amount, isAccumulated);
262 balance.setMonth10Amount(month10Amount);
263
264 KualiDecimal month11Amount = balance.getMonth11Amount();
265 month11Amount = accumulateAmount(month11Amount, month10Amount, isAccumulated);
266 balance.setMonth11Amount(month11Amount);
267
268 KualiDecimal month12Amount = balance.getMonth12Amount();
269 month12Amount = accumulateAmount(month12Amount, month11Amount, isAccumulated);
270 balance.setMonth12Amount(month12Amount);
271
272 KualiDecimal month13Amount = balance.getMonth13Amount();
273 month13Amount = accumulateAmount(month13Amount, month12Amount, isAccumulated);
274 balance.setMonth13Amount(month13Amount);
275 }
276
277 /**
278 * This method converts the amount from String and adds it with the input addend
279 *
280 * @param stringAugend a String-type augend
281 * @param addend an addend
282 * @param isAccumulated determine if the accumulated result is desired
283 * @return the accumulated amount if accumulate option is selected; otherwise, the input amount itself
284 */
285 private KualiDecimal accumulateAmount(Object stringAugend, KualiDecimal addend, boolean isAccumulated) {
286
287 KualiDecimal augend = new KualiDecimal(stringAugend.toString());
288 if (isAccumulated) {
289 augend = augend.add(addend);
290 }
291 return augend;
292 }
293
294 /**
295 * Updates pending entries before their results are included in the lookup results
296 *
297 * @param entryCollection a collection of balance entries
298 * @param fieldValues the map containing the search fields and values
299 * @param isApproved flag whether the approved entries or all entries will be processed
300 * @param isConsolidated flag whether the results are consolidated or not
301 * @param isCostShareExcluded flag whether the user selects to see the results with cost share subaccount
302 * @see org.kuali.module.gl.web.lookupable.AbstractGLLookupableImpl#updateEntryCollection(java.util.Collection, java.util.Map,
303 * boolean, boolean, boolean)
304 */
305 public void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive) {
306
307 // convert the field names of balance object into corresponding ones of pending entry object
308 Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues);
309
310 // go through the pending entries to update the balance collection
311 Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForBalance(pendingEntryFieldValues, isApproved);
312 while (pendingEntryIterator.hasNext()) {
313 GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next();
314
315 // if consolidated, change the following fields into the default values for consolidation
316 if (isConsolidated) {
317 pendingEntry.setSubAccountNumber(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER);
318 pendingEntry.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE);
319 pendingEntry.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE);
320 }
321
322 Balance balance = postBalance.findBalance(entryCollection, pendingEntry);
323
324 String pendingEntryOption = isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY;
325 balance.setDummyBusinessObject(new TransientBalanceInquiryAttributes());
326 balance.getDummyBusinessObject().setPendingEntryOption(pendingEntryOption);
327
328 postBalance.updateBalance(pendingEntry, balance);
329 }
330 }
331
332 /**
333 * Sets the postBalance attribute value.
334 *
335 * @param postBalance The postBalance to set.
336 */
337 public void setPostBalance(BalanceCalculator postBalance) {
338 this.postBalance = postBalance;
339 }
340
341 /**
342 * Sets the balanceService attribute value.
343 *
344 * @param balanceService The balanceService to set.
345 */
346 public void setBalanceService(BalanceService balanceService) {
347 this.balanceService = balanceService;
348 }
349
350 }