/* * 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.bc.businessobject.lookup; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.module.bc.BCConstants; import org.kuali.kfs.module.bc.BCKeyConstants; import org.kuali.kfs.module.bc.BCPropertyConstants; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionFundingLock; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockSummary; import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition; import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding; import org.kuali.kfs.module.bc.document.service.LockService; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.rice.core.api.config.property.ConfigurationService; import org.kuali.rice.kim.api.identity.principal.Principal; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.kns.document.authorization.BusinessObjectRestrictions; import org.kuali.rice.kns.lookup.HtmlData; import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData; import org.kuali.rice.kns.lookup.HtmlData.InputHtmlData; import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl; import org.kuali.rice.kns.web.struts.form.LookupForm; import org.kuali.rice.krad.bo.BusinessObject; import org.kuali.rice.krad.lookup.CollectionIncomplete; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; /** * Implements custom search routine to find the current budget locks and build up the result List. Set an unlock URL for each lock. */ public class LockMonitorLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl { private ConfigurationService kualiConfigurationService; /** * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getSearchResults(java.util.Map) */ @Override public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) { setBackLocation(fieldValues.get(KFSConstants.BACK_LOCATION)); setDocFormKey(fieldValues.get(KFSConstants.DOC_FORM_KEY)); setReferencesToRefresh(fieldValues.get(KFSConstants.REFERENCES_TO_REFRESH)); List<BudgetConstructionLockSummary> results = new ArrayList<BudgetConstructionLockSummary>(); // get universal identifier from network id String lockUserID = fieldValues.get(BCPropertyConstants.LOCK_USER_ID); String lockUnivId = getUniversalIdFromNetworkID(lockUserID); getAccountLocks(results, lockUnivId); getTransactionLocks(results, lockUnivId); getOrphanFundingLocks(results, lockUnivId); getPositionFundingLocks(results, lockUnivId); getOrphanPositionLocks(results, lockUnivId); return new CollectionIncomplete(results, new Long(0)); } /** * Calls lock service to retrieve all current account locks and builds a lock summary object for each returned lock. * * @param results - result list to add lock summaries */ protected void getAccountLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { List<BudgetConstructionHeader> accountLocks = SpringContext.getBean(LockService.class).getAllAccountLocks(lockUnivId); for (BudgetConstructionHeader header : accountLocks) { BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); lockSummary.setLockType(BCConstants.LockTypes.ACCOUNT_LOCK); lockSummary.setLockUserId(header.getBudgetLockUser().getPrincipalName()); lockSummary.setDocumentNumber(header.getDocumentNumber()); lockSummary.setUniversityFiscalYear(header.getUniversityFiscalYear()); lockSummary.setChartOfAccountsCode(header.getChartOfAccountsCode()); lockSummary.setAccountNumber(header.getAccountNumber()); lockSummary.setSubAccountNumber(header.getSubAccountNumber()); results.add(lockSummary); } } /** * Calls lock service to retrieve all current transaction locks and builds a lock summary object for each returned lock. * * @param results - result list to add lock summaries */ protected void getTransactionLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { List<BudgetConstructionHeader> transLocks = SpringContext.getBean(LockService.class).getAllTransactionLocks(lockUnivId); for (BudgetConstructionHeader header : transLocks) { BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); lockSummary.setLockType(BCConstants.LockTypes.TRANSACTION_LOCK); lockSummary.setLockUserId(header.getBudgetTransactionLockUser().getPrincipalName()); lockSummary.setDocumentNumber(header.getDocumentNumber()); lockSummary.setUniversityFiscalYear(header.getUniversityFiscalYear()); lockSummary.setChartOfAccountsCode(header.getChartOfAccountsCode()); lockSummary.setAccountNumber(header.getAccountNumber()); lockSummary.setSubAccountNumber(header.getSubAccountNumber()); results.add(lockSummary); } } /** * Calls lock service to retrieve all funding locks that do not have a corresponding position locks and builds a lock summary * object for each returned lock. * * @param results - result list to add lock summaries */ protected void getOrphanFundingLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { List<BudgetConstructionFundingLock> fundingLocks = SpringContext.getBean(LockService.class).getOrphanedFundingLocks(lockUnivId); for (BudgetConstructionFundingLock fundingLock : fundingLocks) { BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); lockSummary.setLockType(BCConstants.LockTypes.FUNDING_LOCK); lockSummary.setLockUserId(fundingLock.getAppointmentFundingLockUser().getPrincipalName()); lockSummary.setUniversityFiscalYear(fundingLock.getUniversityFiscalYear()); lockSummary.setChartOfAccountsCode(fundingLock.getChartOfAccountsCode()); lockSummary.setAccountNumber(fundingLock.getAccountNumber()); lockSummary.setSubAccountNumber(fundingLock.getSubAccountNumber()); results.add(lockSummary); } } /** * Calls lock service to retrieve all current position/funding locks and builds a lock summary object for each returned lock. * * @param results - result list to add lock summaries */ protected void getPositionFundingLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { List<PendingBudgetConstructionAppointmentFunding> positionFundingLocks = SpringContext.getBean(LockService.class).getAllPositionFundingLocks(lockUnivId); for (PendingBudgetConstructionAppointmentFunding appointmentFunding : positionFundingLocks) { BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); lockSummary.setLockType(BCConstants.LockTypes.POSITION_FUNDING_LOCK); lockSummary.setLockUserId(appointmentFunding.getBudgetConstructionPosition().getPositionLockUser().getPrincipalName()); lockSummary.setUniversityFiscalYear(appointmentFunding.getUniversityFiscalYear()); lockSummary.setChartOfAccountsCode(appointmentFunding.getChartOfAccountsCode()); lockSummary.setAccountNumber(appointmentFunding.getAccountNumber()); lockSummary.setSubAccountNumber(appointmentFunding.getSubAccountNumber()); lockSummary.setPositionNumber(appointmentFunding.getBudgetConstructionPosition().getPositionNumber()); lockSummary.setPositionDescription(appointmentFunding.getBudgetConstructionPosition().getPositionDescription()); results.add(lockSummary); } } /** * Calls lock service to retrieve all current position locks without a corresponding funding lock and builds a lock summary * object for each returned lock. * * @param results - result list to add lock summaries */ protected void getOrphanPositionLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) { List<BudgetConstructionPosition> positionLocks = SpringContext.getBean(LockService.class).getOrphanedPositionLocks(lockUnivId); for (BudgetConstructionPosition position : positionLocks) { BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary(); lockSummary.setLockType(BCConstants.LockTypes.POSITION_LOCK); lockSummary.setLockUserId(position.getPositionLockUser().getPrincipalName()); lockSummary.setUniversityFiscalYear(position.getUniversityFiscalYear()); lockSummary.setPositionNumber(position.getPositionNumber()); lockSummary.setPositionDescription(position.getPositionDescription()); results.add(lockSummary); } } /** * Builds unlink action for each type of lock. * * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getCustomActionUrls(org.kuali.rice.krad.bo.BusinessObject, java.util.List) */ @Override public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) { BudgetConstructionLockSummary lockSummary = (BudgetConstructionLockSummary) businessObject; String imageDirectory = kualiConfigurationService.getPropertyValueAsString(KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY); String lockFields = lockSummary.getUniversityFiscalYear() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getChartOfAccountsCode() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getAccountNumber() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getSubAccountNumber() + BCConstants.LOCK_STRING_DELIMITER + lockSummary.getPositionNumber() + BCConstants.LOCK_STRING_DELIMITER; lockFields = StringUtils.replace(lockFields, "null", ""); String name = KFSConstants.DISPATCH_REQUEST_PARAMETER + "." + BCConstants.TEMP_LIST_UNLOCK_METHOD + "."; name += KFSConstants.METHOD_TO_CALL_PARM1_LEFT_DEL + StringUtils.replace(lockSummary.getLockType()," ","_") + KFSConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL; name += KFSConstants.METHOD_TO_CALL_PARM9_LEFT_DEL + lockFields + KFSConstants.METHOD_TO_CALL_PARM9_RIGHT_DEL; name += KFSConstants.METHOD_TO_CALL_PARM3_LEFT_DEL + lockSummary.getLockUserId() + KFSConstants.METHOD_TO_CALL_PARM3_RIGHT_DEL; String src = imageDirectory + BCConstants.UNLOCK_BUTTON_NAME; String inputType = "image"; String styleClass = "tinybutton"; String border= "0"; List<HtmlData> htmlDataList = new ArrayList<HtmlData>(); InputHtmlData inputHtmlData = new InputHtmlData(name, inputType, src); inputHtmlData.setStyleClass(styleClass); inputHtmlData.setBorder(border); htmlDataList.add(inputHtmlData); return htmlDataList; } /** * Uses org.kuali.rice.kim.api.identity.IdentityService to retrieve user object associated with the given network id (if not blank) and then * returns universal id. Add error to GlobalVariables if the user was not found. * * @param networkID - network id for the user to find * @return universal id for the user or null if not found or the network id was blank */ protected String getUniversalIdFromNetworkID(String networkID) { String universalId = null; if (StringUtils.isNotBlank(networkID)) { Principal user = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(networkID); if (user != null) { universalId = user.getPrincipalId(); } else { GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_LOCK_INVALID_USER, networkID); } } return universalId; } /** * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getReturnUrl(org.kuali.rice.krad.bo.BusinessObject, java.util.Map, java.lang.String) */ @Override public HtmlData getReturnUrl(BusinessObject businessObject, LookupForm lookupForm, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) { return getEmptyAnchorHtmlData(); } /** * Overridden to prevent a validation exception from thrown when the search method is called to refresh the * results after an error is encountered. * * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map) */ @Override public void validateSearchParameters(Map fieldValues) { } /** * Since this lookupable is called by the budget lookup action, the context will be KFS, not Rice. So the generated inquiries * will not have the Rice context (kr/) and be invalid. This override adds the Rice context to the inquiry Url to working * around the issue. * * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getInquiryUrl(org.kuali.rice.krad.bo.BusinessObject, * java.lang.String) */ @Override public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) { AnchorHtmlData inquiryUrl = (AnchorHtmlData)super.getInquiryUrl(bo, propertyName); inquiryUrl.setHref(StringUtils.replace(inquiryUrl.getHref(), KRADConstants.INQUIRY_ACTION, KFSConstants.INQUIRY_ACTION)); return inquiryUrl; } /** * Sets the kualiConfigurationService attribute value. * * @param kualiConfigurationService The kualiConfigurationService to set. */ public void setConfigurationService(ConfigurationService kualiConfigurationService) { this.kualiConfigurationService = kualiConfigurationService; } }