/* * 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.module.tem.businessobject.lookup; import static org.kuali.kfs.module.tem.TemConstants.TravelParameters.EMPLOYEE_TRAVELER_TYPE_CODES; import static org.kuali.kfs.module.tem.TemConstants.TravelParameters.NON_EMPLOYEE_TRAVELER_TYPE_CODES; import static org.kuali.kfs.module.tem.TemKeyConstants.ERROR_TRAVELER_TYPES_NOT_CONFIGURED; import static org.kuali.kfs.module.tem.TemKeyConstants.ERROR_TRAVELER_TYPES_NOT_SELECTED; import static org.kuali.kfs.module.tem.TemPropertyConstants.TRVL_DOC_TRAVELER_TYP_CD; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.kuali.kfs.integration.ar.AccountsReceivableCustomer; import org.kuali.kfs.integration.ar.AccountsReceivableCustomerType; import org.kuali.kfs.integration.ar.AccountsReceivableModuleService; import org.kuali.kfs.module.tem.TemConstants; import org.kuali.kfs.module.tem.TemParameterConstants; import org.kuali.kfs.module.tem.TemPropertyConstants; import org.kuali.kfs.module.tem.businessobject.TravelerDetail; import org.kuali.kfs.module.tem.businessobject.datadictionary.TravelDetailLookupMappedFieldProxy; import org.kuali.kfs.module.tem.dataaccess.TravelerDao; import org.kuali.kfs.module.tem.service.TravelerService; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kim.api.identity.Person; import org.kuali.rice.kim.api.identity.PersonService; import org.kuali.rice.kim.impl.identity.PersonImpl; import org.kuali.rice.kns.datadictionary.BusinessObjectEntry; import org.kuali.rice.kns.datadictionary.FieldDefinition; import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl; import org.kuali.rice.krad.bo.BusinessObject; import org.kuali.rice.krad.exception.ValidationException; import org.kuali.rice.krad.lookup.CollectionIncomplete; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.service.DataDictionaryService; import org.kuali.rice.krad.util.BeanPropertyComparator; import org.kuali.rice.krad.util.GlobalVariables; /** * Custom helper service used to find {@link TravelerDetail} instances of employees or non-employees or both. * */ @SuppressWarnings("deprecation") public class TravelerLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl { public static Logger LOG = Logger.getLogger(TravelerLookupableHelperServiceImpl.class); private BusinessObjectService businessObjectService; private ParameterService parameterService; private PersonService personService; private TravelerService travelerService; private TravelerDao travelerDao; private AccountsReceivableModuleService accountsReceivableModuleService; private static final int NAME_REQUIRED_FILLED_WITH_WILDCARD = 4; /** * @see org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl#getSearchResults(java.util.Map) */ @Override public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) { List<TravelerDetail> searchResults = new ArrayList<TravelerDetail>(); if (isEmployeeSearch(fieldValues)) { searchResults.addAll(getEmployeesAsTravelers(fieldValues)); } else { LOG.debug("Doing search for customers"); searchResults.addAll(getNonEmployeesAsTravelers(fieldValues)); } CollectionIncomplete results = new CollectionIncomplete(searchResults, Long.valueOf(searchResults.size())); // sort list if default sort column given List<String> defaultSortColumns = getDefaultSortColumns(); if (defaultSortColumns.size() > 0) { Collections.sort(results, new BeanPropertyComparator(defaultSortColumns, true)); } return results; } /** * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map) */ @Override public void validateSearchParameters(Map fieldValues) { super.validateSearchParameters(fieldValues); if (fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD) == null || fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD).equals("")) { GlobalVariables.getMessageMap().putError(TRVL_DOC_TRAVELER_TYP_CD, ERROR_TRAVELER_TYPES_NOT_SELECTED, new String[] { (String) fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD) }); } if (!isEmployeeSearch(fieldValues) && !isNonEmployeeSearch(fieldValues)) { GlobalVariables.getMessageMap().putError(TRVL_DOC_TRAVELER_TYP_CD, ERROR_TRAVELER_TYPES_NOT_CONFIGURED, new String[] { (String) fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD) }); } if (GlobalVariables.getMessageMap().hasErrors()) { throw new ValidationException("errors in search criteria"); } } protected Map<String, String> convertFieldValues(final Class boClass, final Map<String, String> fieldValues) { Map<String, String> retval = new HashMap<String, String>(); LOG.debug("Converting field values " + fieldValues); for (final FieldDefinition lookupField : getLookupFieldsFor(TravelerDetail.class.getName())) { final String attrName = lookupField.getAttributeName(); if (lookupField instanceof TravelDetailLookupMappedFieldProxy) { final TravelDetailLookupMappedFieldProxy mappedField = (TravelDetailLookupMappedFieldProxy) lookupField; final String key = mappedField.getAttributeMap().get(boClass.getSimpleName()); String value = fieldValues.get(attrName); if (retval.containsKey(key)) { value = retval.get(key) + value; } if (key != null) { retval.put(key, value); } else { LOG.warn("Got a null key for attribute name " + attrName); } } else if (containsAttribute(boClass, attrName)) { retval.put(attrName, fieldValues.get(attrName)); } } return retval; } /** * Generates a {@link Map} of field values where object properties are mapped to values for * search purposes. * * @param fieldValues original field values passed to the lookup * @return Map of values */ protected Map<String, String> getPersonFieldValues(final Map<String, String> fieldValues) { return convertFieldValues(PersonImpl.class, fieldValues); } /** * Generates a {@link Map} of field values where object properties are mapped to values for * search purposes. * * @param fieldValues original field values passed to the lookup * @return Map of values */ protected Map<String, String> getCustomerFieldValues(final Map<String, String> fieldValues) { return convertFieldValues(getAccountsReceivableModuleService().createCustomer().getClass(), fieldValues); } /** * Determine using fieldValues map from the lookup form whether the user is doing an employee or non-employee * search * * @param fieldValues is a value map of lookup form parameters * @return true if an employee search, false otherwise */ protected boolean isEmployeeSearch(final Map<String, String> fieldValues) { LOG.debug("Checking traveler type code " + fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD)); final String employeeTypes = getParameterService().getParameterValueAsString(TemParameterConstants.TEM_DOCUMENT.class, EMPLOYEE_TRAVELER_TYPE_CODES); return employeeTypes.indexOf(fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD)) != -1; } /** * Determine using fieldValues map from the lookup form whether the user is doing an employee or non-employee * search * * @param fieldValues is a value map of lookup form parameters * @return true if an employee search, false otherwise */ protected boolean isNonEmployeeSearch(final Map<String, String> fieldValues) { LOG.debug("Checking traveler type code " + fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD)); final String nonEmployeeTypes = getParameterService().getParameterValueAsString(TemParameterConstants.TEM_DOCUMENT.class, NON_EMPLOYEE_TRAVELER_TYPE_CODES); return nonEmployeeTypes.indexOf(fieldValues.get(TRVL_DOC_TRAVELER_TYP_CD)) != -1; } protected boolean isKimOnlySearch(final Map<String, String> fieldValues) { return (fieldValues.get("principalName") != null || fieldValues.get("principalId") != null); } /** * Performs a person search and converts the results to {@link TravelerDetail} instances * * @param fieldValues * @return List of {@link TravelerDetail} instances */ protected List<TravelerDetail> getEmployeesAsTravelers(Map<String, String> fieldValues) { final List<TravelerDetail> travelers = new ArrayList<TravelerDetail>(); final Map<String, String> kimFieldsForLookup = this.getPersonFieldValues(fieldValues); LOG.debug("Looking up people with criteria " + kimFieldsForLookup); final List<? extends Person> persons = getPersonService().findPeople(kimFieldsForLookup); for (Person personDetail : persons) { travelers.add(getTravelerService().convertToTraveler(personDetail)); } if (!isKimOnlySearch(fieldValues)) { final Map<String, String> arFieldsForLookup = this.getCustomerFieldValues(fieldValues); final Collection<AccountsReceivableCustomer> customers = getTravelerDao().findCustomersBy(arFieldsForLookup); for (AccountsReceivableCustomer customer : customers) { travelers.add(getTravelerService().convertToTraveler(customer)); } } return travelers; } /** * Performs a customer search and converts the results to {@link TravelerDetail} instances * * @param fieldValues * @return List of {@link TravelerDetail} instances */ protected List<TravelerDetail> getNonEmployeesAsTravelers(final Map<String, String> fieldValues) { final List<TravelerDetail> travelers = new ArrayList<TravelerDetail>(); final Map<String, String> fieldsForLookup = this.getCustomerFieldValues(fieldValues); final List<AccountsReceivableCustomerType> customerTypeList = getAccountsReceivableModuleService().findByCustomerTypeDescription(TemConstants.CUSTOMER_TRAVLER_TYPE_CODE); LOG.debug("Got customer types " + customerTypeList); LOG.debug("Got customer types " + customerTypeList.size()); if(customerTypeList != null && customerTypeList.size() > 0) { LOG.debug("Adding " + TemPropertyConstants.CUSTOMER_TYPE_CODE + " to fields to lookup"); fieldsForLookup.put(TemPropertyConstants.CUSTOMER_TYPE_CODE, customerTypeList.get(0).getCustomerTypeCode()); } LOG.debug("Using fieldsForLookup " + fieldsForLookup); final Collection<AccountsReceivableCustomer> customers = getTravelerDao().findCustomersBy(fieldsForLookup); for (final AccountsReceivableCustomer customer : customers) { travelers.add(getTravelerService().convertToTraveler(customer)); } return travelers; } // replace the keys in fieldValues with the corresponding values defined in fieldConversionMap protected void replaceFieldKeys(final Map<String, String> fieldValues, final Map<String, String> helperMap) { for (String key : helperMap.keySet()) { if (fieldValues.containsKey(key)) { String value = fieldValues.get(key); String newKey = helperMap.get(key); fieldValues.remove(key); fieldValues.put(newKey, value); } } } /** * Sets the personService attribute value. * * @param personService The personService to set. */ public void setPersonService(PersonService personService) { this.personService = personService; } public PersonService getPersonService() { return this.personService; } /** * Sets the parameterService attribute value. * * @param parameterService The parameterService to set. */ @Override public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } @Override public ParameterService getParameterService() { return this.parameterService; } /** * Sets the businessObjectService attribute value. * * @param businessObjectService The businessObjectService to set. */ @Override public void setBusinessObjectService(final BusinessObjectService businessObjectService) { this.businessObjectService = businessObjectService; } @Override public BusinessObjectService getBusinessObjectService() { return this.businessObjectService; } protected Collection<FieldDefinition> getLookupFieldsFor(final String className) { BusinessObjectEntry businessObjectEntry = (BusinessObjectEntry)getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(className); return businessObjectEntry.getLookupDefinition().getLookupFields(); } /** * @see org.kuali.rice.kns.datadictionary.DataDictionary#getBusinessObjectEntry(String) */ @SuppressWarnings("rawtypes") protected boolean containsAttribute(final Class boClass, final String attributeName) { return getDataDictionaryService().isAttributeDefined(boClass, attributeName); } /** * Sets the dataDictionaryService attribute value. * * @param dataDictionaryService The dataDictionaryService to set. */ @Override public void setDataDictionaryService(final DataDictionaryService dataDictionaryService) { this.dataDictionaryService = dataDictionaryService; } @Override public DataDictionaryService getDataDictionaryService() { return this.dataDictionaryService; } protected TravelerDao getTravelerDao() { return travelerDao; } public void setTravelerDao(final TravelerDao travelerDao) { this.travelerDao = travelerDao; } public void setTravelerService(final TravelerService travelerService) { this.travelerService = travelerService; } public TravelerService getTravelerService() { return this.travelerService; } /** * Gets the accountsReceivableModuleService attribute. * * @return Returns the accountsReceivableModuleService. */ protected AccountsReceivableModuleService getAccountsReceivableModuleService() { if (accountsReceivableModuleService == null) { this.accountsReceivableModuleService = SpringContext.getBean(AccountsReceivableModuleService.class); } return accountsReceivableModuleService; } /** * Sets the accountsReceivableModuleService attribute value. * * @param accountsReceivableModuleService The accountsReceivableModuleService to set. */ public void setAccountsReceivableModuleService(AccountsReceivableModuleService accountsReceivableModuleService) { this.accountsReceivableModuleService = accountsReceivableModuleService; } }