/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.gl.businessobject.lookup; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.coa.businessobject.Account; import org.kuali.kfs.gl.Constant; import org.kuali.kfs.gl.GeneralLedgerConstants; import org.kuali.kfs.gl.OJBUtility; import org.kuali.kfs.gl.batch.service.BalanceCalculator; import org.kuali.kfs.gl.businessobject.Balance; import org.kuali.kfs.gl.businessobject.CashBalance; import org.kuali.kfs.gl.businessobject.inquiry.CashBalanceInquirableImpl; import org.kuali.kfs.gl.service.BalanceService; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.businessobject.GeneralLedgerPendingEntry; import org.kuali.kfs.sys.businessobject.UniversityDate; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.service.UniversityDateService; import org.kuali.rice.core.api.util.type.KualiDecimal; import org.kuali.rice.kns.lookup.HtmlData; import org.kuali.rice.kns.web.ui.Field; import org.kuali.rice.kns.web.ui.Row; import org.kuali.rice.krad.bo.BusinessObject; import org.kuali.rice.krad.util.ObjectUtils; /** * An extension of KualiLookupableImpl to support cash lookups */ public class CashBalanceLookupableHelperServiceImpl extends AbstractGeneralLedgerLookupableHelperServiceImpl { private BalanceCalculator postBalance; private BalanceService balanceService; /** * Returns the URL for inquiries on fields returned in the lookup * * @param bo the business object the field to inquiry on is in * @param propertyName the name of the property that an inquiry url is being asked of * @return the String of the url * @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.krad.bo.BusinessObject, java.lang.String) KRAD * Conversion: Lookupable modifies the search results based on the fields consolidated. But all field definitions are in * data dictionary. */ @Override public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) { return (new CashBalanceInquirableImpl()).getInquiryUrl(bo, propertyName); } /** * Generates a list of results for this inquiry * * @param fieldValues the field values that the user entered for this inquiry * @return a List of results * @see org.kuali.rice.kns.lookup.Lookupable#getSearchResults(java.util.Map) */ @Override public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) { setBackLocation((String) fieldValues.get(KFSConstants.BACK_LOCATION)); setDocFormKey((String) fieldValues.get(KFSConstants.DOC_FORM_KEY)); // get the pending entry option. This method must be prior to the get search results String pendingEntryOption = getSelectedPendingEntryOption(fieldValues); // KFSMI-410: need to get this before getting isConsolidated because this value will be removed. String consolidationOption = (String) fieldValues.get(GeneralLedgerConstants.DummyBusinessObject.CONSOLIDATION_OPTION); // get the consolidation option boolean isConsolidated = isConsolidationSelected(fieldValues); // KFSMI-410: added one more node for consolidationOption if (consolidationOption.equals(Constant.EXCLUDE_SUBACCOUNTS)){ fieldValues.put(Constant.SUB_ACCOUNT_OPTION, KFSConstants.getDashSubAccountNumber()); isConsolidated = false; } // get the search result collection Iterator cashBalanceIterator = balanceService.lookupCashBalance(fieldValues, isConsolidated); Collection searchResultsCollection = this.buildCashBalanceCollection(cashBalanceIterator, isConsolidated); // update search results according to the selected pending entry option updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, isConsolidated, false); // get the actual size of all qualified search results Integer recordCount = balanceService.getCashBalanceRecordCount(fieldValues, isConsolidated); Long actualSize = OJBUtility.getResultActualSize(searchResultsCollection, recordCount, fieldValues, new Balance()); return this.buildSearchResultList(searchResultsCollection, actualSize); } /** * This method builds the cash balance collection based on the input iterator * * @param iterator the iterator of search results of avaiable cash balance * @return the cash balance collection */ private Collection buildCashBalanceCollection(Iterator iterator, boolean isConsolidated) { Collection balanceCollection = new ArrayList(); while (iterator.hasNext()) { Object cashBalance = iterator.next(); if (cashBalance.getClass().isArray()) { int i = 0; Object[] array = (Object[]) cashBalance; Balance balance = new CashBalance(); balance.setUniversityFiscalYear(new Integer(array[i++].toString())); balance.setChartOfAccountsCode(array[i++].toString()); balance.setAccountNumber(array[i++].toString()); String subAccountNumber = isConsolidated ? Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER : array[i++].toString(); balance.setSubAccountNumber(subAccountNumber); balance.setBalanceTypeCode(array[i++].toString()); balance.setObjectCode(array[i++].toString()); String subObjectCode = isConsolidated ? Constant.CONSOLIDATED_SUB_OBJECT_CODE : array[i++].toString(); balance.setSubObjectCode(subObjectCode); String objectTypeCode = isConsolidated ? Constant.CONSOLIDATED_OBJECT_TYPE_CODE : array[i++].toString(); balance.setObjectTypeCode(objectTypeCode); KualiDecimal annualAmount = new KualiDecimal(array[i++].toString()); balance.setAccountLineAnnualBalanceAmount(annualAmount); KualiDecimal beginningAmount = new KualiDecimal(array[i++].toString()); balance.setBeginningBalanceLineAmount(beginningAmount); KualiDecimal CGBeginningAmount = new KualiDecimal(array[i].toString()); balance.setContractsGrantsBeginningBalanceAmount(CGBeginningAmount); KualiDecimal totalAvailableAmount = this.getTotalAvailableCashAmount(balance); balance.getDummyBusinessObject().setGenericAmount(totalAvailableAmount); balanceCollection.add(balance); } } return balanceCollection; } /** * Allows an updating of pending entry records before they are applied to the inquiry results * * @param entryCollection a collection of balance entries * @param fieldValues the map containing the search fields and values * @param isApproved flag whether the approved entries or all entries will be processed * @param isConsolidated flag whether the results are consolidated or not * @param isCostShareExcluded flag whether the user selects to see the results with cost share subaccount * @see org.kuali.module.gl.web.lookupable.AbstractGLLookupableImpl#updateEntryCollection(java.util.Collection, java.util.Map, * boolean, boolean, boolean) */ @Override protected void updateEntryCollection(Collection entryCollection, Map fieldValues, boolean isApproved, boolean isConsolidated, boolean isCostShareInclusive) { // convert the field names of balance object into corresponding ones of pending entry object Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues); UniversityDate today = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate(); String currentFiscalPeriodCode = today.getUniversityFiscalAccountingPeriod(); Integer currentFiscalYear = today.getUniversityFiscalYear(); // use the pending entry to update the input entry collection Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForCashBalance(pendingEntryFieldValues, isApproved); while (pendingEntryIterator.hasNext()) { GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next(); // Fix the fiscal period/year if they are null // Don't want to use the GLPE service.fillInFiscalPeriodYear. It totally kills performance. // generalLedgerPendingEntryService.fillInFiscalPeriodYear(pendingEntry); if (pendingEntry.getUniversityFiscalYear() == null) { pendingEntry.setUniversityFiscalYear(currentFiscalYear); } if (pendingEntry.getUniversityFiscalPeriodCode() == null) { pendingEntry.setUniversityFiscalPeriodCode(currentFiscalPeriodCode); } // if consolidated, change the following fields into the default values for consolidation if (isConsolidated) { pendingEntry.setSubAccountNumber(Constant.CONSOLIDATED_SUB_ACCOUNT_NUMBER); pendingEntry.setFinancialSubObjectCode(Constant.CONSOLIDATED_SUB_OBJECT_CODE); pendingEntry.setFinancialObjectTypeCode(Constant.CONSOLIDATED_OBJECT_TYPE_CODE); } Balance balance = postBalance.findBalance(entryCollection, pendingEntry); postBalance.updateBalance(pendingEntry, balance); KualiDecimal totalAvailableAmount = this.getTotalAvailableCashAmount(balance); balance.getDummyBusinessObject().setGenericAmount(totalAvailableAmount); } } // calculate the total available cash amont of the given balance record private KualiDecimal getTotalAvailableCashAmount(Balance balance) { KualiDecimal annualAmount = balance.getAccountLineAnnualBalanceAmount(); KualiDecimal beginningAmount = balance.getBeginningBalanceLineAmount(); KualiDecimal CGBeginningAmount = balance.getContractsGrantsBeginningBalanceAmount(); KualiDecimal totalAvailableAmount = annualAmount.add(beginningAmount); totalAvailableAmount = totalAvailableAmount.add(CGBeginningAmount); return totalAvailableAmount; } /** * Sets the postBalance attribute value. * * @param postBalance The postBalance to set. */ public void setPostBalance(BalanceCalculator postBalance) { this.postBalance = postBalance; } /** * Sets the balanceService attribute value. * * @param balanceService The balanceService to set. */ public void setBalanceService(BalanceService balanceService) { this.balanceService = balanceService; } @Override public List<Row> getRows() { // TODO Auto-generated method stub List<Row> rows = super.getRows(); // look for field and replace BO class for (Iterator iter = rows.iterator(); iter.hasNext();) { Row row = (Row) iter.next(); for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) { Field field = (Field) iterator.next(); if (ObjectUtils.isNotNull(field) && StringUtils.equalsIgnoreCase(field.getPropertyName(), KFSPropertyConstants.ACCOUNT_NUMBER)) { field.setQuickFinderClassNameImpl(Account.class.getName()); } } } return rows; } }