/*
* 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.sql.Date;
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.gl.Constant;
import org.kuali.kfs.gl.businessobject.Entry;
import org.kuali.kfs.gl.businessobject.inquiry.EntryInquirableImpl;
import org.kuali.kfs.gl.businessobject.inquiry.InquirableFinancialDocument;
import org.kuali.kfs.gl.service.EntryService;
import org.kuali.kfs.gl.service.ScrubberValidator;
import org.kuali.kfs.integration.ld.LaborModuleService;
import org.kuali.kfs.sys.KFSConstants;
import org.kuali.kfs.sys.KFSKeyConstants;
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.datetime.DateTimeService;
import org.kuali.rice.kns.lookup.HtmlData;
import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
import org.kuali.rice.krad.bo.BusinessObject;
import org.kuali.rice.krad.exception.ValidationException;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
/**
* An extension of KualiLookupableImpl to support entry lookups
*/
public class EntryLookupableHelperServiceImpl extends AbstractGeneralLedgerLookupableHelperServiceImpl {
private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(EntryLookupableHelperServiceImpl.class);
private ScrubberValidator scrubberValidator;
private EntryService entryService;
private volatile static LaborModuleService laborModuleService;
/**
* Validate the university fiscal year that has been queried on
*
* @param fieldValues the queried fields
* @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
*/
@Override
public void validateSearchParameters(Map fieldValues) {
super.validateSearchParameters(fieldValues);
String valueFiscalYear = (String) fieldValues.get("universityFiscalYear");
if (!StringUtils.isEmpty(valueFiscalYear)) {
try {
int year = Integer.parseInt(valueFiscalYear);
}
catch (NumberFormatException e) {
GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_CUSTOM, new String[] { "Fiscal Year must be a four-digit number" });
throw new ValidationException("errors in search criteria");
}
}
if (!allRequiredsForAccountSearch(fieldValues) && !allRequiredsForDocumentSearch(fieldValues)) {
GlobalVariables.getMessageMap().putError("universityFiscalYear", KFSKeyConstants.ERROR_GL_LOOKUP_ENTRY_NON_MATCHING_REQUIRED_FIELDS, new String[] {});
throw new ValidationException("errors in search criteria");
}
}
/**
* Determines if all the required values for an account based search are present - fiscal year, chart, account number, and fiscal period code
* @param fieldValues field values to check
* @return true if all the account-based required search fields are present; false otherwise
*/
protected boolean allRequiredsForAccountSearch(Map fieldValues) {
final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
final String chartOfAccountsCode = (String)fieldValues.get("chartOfAccountsCode");
final String accountNumber = (String)fieldValues.get("accountNumber");
final String fiscalPeriodCode = (String)fieldValues.get("universityFiscalPeriodCode");
return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(chartOfAccountsCode) && !StringUtils.isBlank(accountNumber) && !StringUtils.isBlank(fiscalPeriodCode);
}
/**
* Determines if all the required values for an document based search are present - fiscal year and document number
* @param fieldValues field values to check
* @return true if all the document-based required search fields are present; false otherwise
*/
protected boolean allRequiredsForDocumentSearch(Map fieldValues) {
final String fiscalYearAsString = (String)fieldValues.get("universityFiscalYear");
final String documentNumber = (String)fieldValues.get("documentNumber");
return !StringUtils.isBlank(fiscalYearAsString) && !StringUtils.isBlank(documentNumber);
}
/**
* Returns the url for any drill down links within the lookup
* @param bo the business object with a property being drilled down on
* @param propertyName the name of the property being drilled down on
* @return a String with the URL of the property
* @see org.kuali.rice.kns.lookup.Lookupable#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject, java.lang.String)
*/
@Override
public HtmlData getInquiryUrl(BusinessObject businessObject, String propertyName) {
if (KFSPropertyConstants.DOCUMENT_NUMBER.equals(propertyName)) {
if (businessObject instanceof Entry) {
Entry entry = (Entry) businessObject;
if (getLaborModuleService().getLaborLedgerGLOriginCodes() != null && !getLaborModuleService().getLaborLedgerGLOriginCodes().isEmpty() && getLaborModuleService().getLaborLedgerGLOriginCodes().contains(entry.getFinancialSystemOriginationCode())) {
return getLaborModuleService().getInquiryUrlForGeneralLedgerEntryDocumentNumber(entry);
}
return new AnchorHtmlData(new InquirableFinancialDocument().getInquirableDocumentUrl(entry), KRADConstants.EMPTY_STRING, "view entry "+entry.toString());
}
}
return (new EntryInquirableImpl()).getInquiryUrl(businessObject, propertyName);
}
/**
* Generates the list of search results for this inquiry
* @param fieldValues the field values of the query to carry out
* @return List the search results returned by the lookup
* @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 = this.getSelectedPendingEntryOption(fieldValues);
String debitCreditOption = this.getDebitCreditOption(fieldValues);
// get the search result collection
Collection searchResultsCollection = getLookupService().findCollectionBySearch(getBusinessObjectClass(), fieldValues);
int searchResultsCollectionSize = searchResultsCollection.size();
// update search results according to the selected pending entry option
updateByPendingLedgerEntry(searchResultsCollection, fieldValues, pendingEntryOption, false, false);
// get the actual size of all qualified search results
Long actualSize = new Long(entryService.getEntryRecordCount(fieldValues));
// calculate how many pending entries were included in the original results
int numPendingEntriesAdded = searchResultsCollection.size() - searchResultsCollectionSize;
actualSize += numPendingEntriesAdded;
return this.buildSearchResultList(searchResultsCollection, actualSize);
}
/**
* Updates pending entries before their results are included in the lookup 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) {
LOG.debug("updateEntryCollection started");
// convert the field names of balance object into corresponding ones of pending entry object
Map pendingEntryFieldValues = BusinessObjectFieldConverter.convertToTransactionFieldValues(fieldValues);
// go through the pending entries to update the balance collection
Iterator pendingEntryIterator = getGeneralLedgerPendingEntryService().findPendingLedgerEntriesForEntry(pendingEntryFieldValues, isApproved);
String pendingOption = isApproved ? Constant.APPROVED_PENDING_ENTRY : Constant.ALL_PENDING_ENTRY;
UniversityDate today = SpringContext.getBean(UniversityDateService.class).getCurrentUniversityDate();
String currentFiscalPeriodCode = today.getUniversityFiscalAccountingPeriod();
Integer currentFiscalYear = today.getUniversityFiscalYear();
Date postDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
while (pendingEntryIterator.hasNext()) {
GeneralLedgerPendingEntry pendingEntry = (GeneralLedgerPendingEntry) pendingEntryIterator.next();
// Gotta circumvent date checks in the scrubberValidator. They totally kill performance.
if (pendingEntry.getUniversityFiscalYear() == null) {
pendingEntry.setUniversityFiscalYear(currentFiscalYear);
}
if (pendingEntry.getUniversityFiscalPeriodCode() == null) {
pendingEntry.setUniversityFiscalPeriodCode(currentFiscalPeriodCode);
}
scrubberValidator.validateForInquiry(pendingEntry);
Entry entry = new Entry(pendingEntry, postDate);
String approvedCode = pendingEntry.getFinancialDocumentApprovedCode();
String description = Constant.DocumentApprovedCode.getDescription(approvedCode);
entry.getDummyBusinessObject().setPendingEntryOption(description);
entryCollection.add(entry);
}
}
/**
* Sets the scrubberValidator attribute value.
*
* @param scrubberValidator The scrubberValidator to set.
*/
public void setScrubberValidator(ScrubberValidator scrubberValidator) {
this.scrubberValidator = scrubberValidator;
}
/**
* Sets the entryService attribute value.
*
* @param entryService The entryService to set.
*/
public void setEntryService(EntryService entryService) {
this.entryService = entryService;
}
/**
* @return the system's configured implementation of the LaborModuleService
*/
public LaborModuleService getLaborModuleService() {
if (laborModuleService == null) {
laborModuleService = SpringContext.getBean(LaborModuleService.class);
}
return laborModuleService;
}
}