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.module.bc.businessobject.lookup;
017
018 import java.util.ArrayList;
019 import java.util.List;
020 import java.util.Map;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.kuali.kfs.module.bc.BCConstants;
024 import org.kuali.kfs.module.bc.BCKeyConstants;
025 import org.kuali.kfs.module.bc.BCPropertyConstants;
026 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionFundingLock;
027 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader;
028 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockSummary;
029 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition;
030 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding;
031 import org.kuali.kfs.module.bc.document.service.LockService;
032 import org.kuali.kfs.sys.KFSConstants;
033 import org.kuali.kfs.sys.context.SpringContext;
034 import org.kuali.rice.kim.bo.Person;
035 import org.kuali.rice.kim.service.PersonService;
036 import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
037 import org.kuali.rice.kns.bo.BusinessObject;
038 import org.kuali.rice.kns.lookup.CollectionIncomplete;
039 import org.kuali.rice.kns.lookup.HtmlData;
040 import org.kuali.rice.kns.lookup.KualiLookupableHelperServiceImpl;
041 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
042 import org.kuali.rice.kns.lookup.HtmlData.InputHtmlData;
043 import org.kuali.rice.kns.service.KualiConfigurationService;
044 import org.kuali.rice.kns.util.GlobalVariables;
045 import org.kuali.rice.kns.util.KNSConstants;
046 import org.kuali.rice.kns.web.struts.form.LookupForm;
047
048 /**
049 * Implements custom search routine to find the current budget locks and build up the result List. Set an unlock URL for each lock.
050 */
051 public class LockMonitorLookupableHelperServiceImpl extends KualiLookupableHelperServiceImpl {
052 private KualiConfigurationService kualiConfigurationService;
053 private PersonService<Person> personService;
054
055 /**
056 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getSearchResults(java.util.Map)
057 */
058 @Override
059 public List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues) {
060 setBackLocation(fieldValues.get(KFSConstants.BACK_LOCATION));
061 setDocFormKey(fieldValues.get(KFSConstants.DOC_FORM_KEY));
062 setReferencesToRefresh(fieldValues.get(KFSConstants.REFERENCES_TO_REFRESH));
063
064 List<BudgetConstructionLockSummary> results = new ArrayList<BudgetConstructionLockSummary>();
065
066 // get universal identifier from network id
067 String lockUserID = fieldValues.get(BCPropertyConstants.LOCK_USER_ID);
068 String lockUnivId = getUniversalIdFromNetworkID(lockUserID);
069
070 getAccountLocks(results, lockUnivId);
071 getTransactionLocks(results, lockUnivId);
072 getOrphanFundingLocks(results, lockUnivId);
073 getPositionFundingLocks(results, lockUnivId);
074 getOrphanPositionLocks(results, lockUnivId);
075
076 return new CollectionIncomplete(results, new Long(0));
077 }
078
079 /**
080 * Calls lock service to retrieve all current account locks and builds a lock summary object for each returned lock.
081 *
082 * @param results - result list to add lock summaries
083 */
084 protected void getAccountLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) {
085 List<BudgetConstructionHeader> accountLocks = SpringContext.getBean(LockService.class).getAllAccountLocks(lockUnivId);
086 for (BudgetConstructionHeader header : accountLocks) {
087 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary();
088 lockSummary.setLockType(BCConstants.LockTypes.ACCOUNT_LOCK);
089 lockSummary.setLockUserId(header.getBudgetLockUser().getPrincipalName());
090
091 lockSummary.setDocumentNumber(header.getDocumentNumber());
092 lockSummary.setUniversityFiscalYear(header.getUniversityFiscalYear());
093 lockSummary.setChartOfAccountsCode(header.getChartOfAccountsCode());
094 lockSummary.setAccountNumber(header.getAccountNumber());
095 lockSummary.setSubAccountNumber(header.getSubAccountNumber());
096
097 results.add(lockSummary);
098 }
099 }
100
101 /**
102 * Calls lock service to retrieve all current transaction locks and builds a lock summary object for each returned lock.
103 *
104 * @param results - result list to add lock summaries
105 */
106 protected void getTransactionLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) {
107 List<BudgetConstructionHeader> transLocks = SpringContext.getBean(LockService.class).getAllTransactionLocks(lockUnivId);
108 for (BudgetConstructionHeader header : transLocks) {
109 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary();
110 lockSummary.setLockType(BCConstants.LockTypes.TRANSACTION_LOCK);
111 lockSummary.setLockUserId(header.getBudgetTransactionLockUser().getPrincipalName());
112
113 lockSummary.setDocumentNumber(header.getDocumentNumber());
114 lockSummary.setUniversityFiscalYear(header.getUniversityFiscalYear());
115 lockSummary.setChartOfAccountsCode(header.getChartOfAccountsCode());
116 lockSummary.setAccountNumber(header.getAccountNumber());
117 lockSummary.setSubAccountNumber(header.getSubAccountNumber());
118
119 results.add(lockSummary);
120 }
121 }
122
123 /**
124 * Calls lock service to retrieve all funding locks that do not have a corresponding position locks and builds a lock summary
125 * object for each returned lock.
126 *
127 * @param results - result list to add lock summaries
128 */
129 protected void getOrphanFundingLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) {
130 List<BudgetConstructionFundingLock> fundingLocks = SpringContext.getBean(LockService.class).getOrphanedFundingLocks(lockUnivId);
131 for (BudgetConstructionFundingLock fundingLock : fundingLocks) {
132 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary();
133 lockSummary.setLockType(BCConstants.LockTypes.FUNDING_LOCK);
134 lockSummary.setLockUserId(fundingLock.getAppointmentFundingLockUser().getPrincipalName());
135
136 lockSummary.setUniversityFiscalYear(fundingLock.getUniversityFiscalYear());
137 lockSummary.setChartOfAccountsCode(fundingLock.getChartOfAccountsCode());
138 lockSummary.setAccountNumber(fundingLock.getAccountNumber());
139 lockSummary.setSubAccountNumber(fundingLock.getSubAccountNumber());
140
141 results.add(lockSummary);
142 }
143 }
144
145 /**
146 * Calls lock service to retrieve all current position/funding locks and builds a lock summary object for each returned lock.
147 *
148 * @param results - result list to add lock summaries
149 */
150 protected void getPositionFundingLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) {
151 List<PendingBudgetConstructionAppointmentFunding> positionFundingLocks = SpringContext.getBean(LockService.class).getAllPositionFundingLocks(lockUnivId);
152 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : positionFundingLocks) {
153 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary();
154 lockSummary.setLockType(BCConstants.LockTypes.POSITION_FUNDING_LOCK);
155 lockSummary.setLockUserId(appointmentFunding.getBudgetConstructionPosition().getPositionLockUser().getPrincipalName());
156
157 lockSummary.setUniversityFiscalYear(appointmentFunding.getUniversityFiscalYear());
158 lockSummary.setChartOfAccountsCode(appointmentFunding.getChartOfAccountsCode());
159 lockSummary.setAccountNumber(appointmentFunding.getAccountNumber());
160 lockSummary.setSubAccountNumber(appointmentFunding.getSubAccountNumber());
161
162 lockSummary.setPositionNumber(appointmentFunding.getBudgetConstructionPosition().getPositionNumber());
163 lockSummary.setPositionDescription(appointmentFunding.getBudgetConstructionPosition().getPositionDescription());
164
165 results.add(lockSummary);
166 }
167 }
168
169 /**
170 * Calls lock service to retrieve all current position locks without a corresponding funding lock and builds a lock summary
171 * object for each returned lock.
172 *
173 * @param results - result list to add lock summaries
174 */
175 protected void getOrphanPositionLocks(List<BudgetConstructionLockSummary> results, String lockUnivId) {
176 List<BudgetConstructionPosition> positionLocks = SpringContext.getBean(LockService.class).getOrphanedPositionLocks(lockUnivId);
177 for (BudgetConstructionPosition position : positionLocks) {
178 BudgetConstructionLockSummary lockSummary = new BudgetConstructionLockSummary();
179 lockSummary.setLockType(BCConstants.LockTypes.POSITION_LOCK);
180 lockSummary.setLockUserId(position.getPositionLockUser().getPrincipalName());
181
182 lockSummary.setUniversityFiscalYear(position.getUniversityFiscalYear());
183 lockSummary.setPositionNumber(position.getPositionNumber());
184 lockSummary.setPositionDescription(position.getPositionDescription());
185
186 results.add(lockSummary);
187 }
188 }
189
190 /**
191 * Builds unlink action for each type of lock.
192 *
193 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getCustomActionUrls(org.kuali.rice.kns.bo.BusinessObject, java.util.List)
194 */
195 @Override
196 public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
197 BudgetConstructionLockSummary lockSummary = (BudgetConstructionLockSummary) businessObject;
198
199 String imageDirectory = kualiConfigurationService.getPropertyString(KFSConstants.EXTERNALIZABLE_IMAGES_URL_KEY);
200 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;
201 lockFields = StringUtils.replace(lockFields, "null", "");
202
203 String name = KFSConstants.DISPATCH_REQUEST_PARAMETER + "." + BCConstants.TEMP_LIST_UNLOCK_METHOD + ".";
204 name +=
205 KFSConstants.METHOD_TO_CALL_PARM1_LEFT_DEL + StringUtils.replace(lockSummary.getLockType()," ","_") +
206 KFSConstants.METHOD_TO_CALL_PARM1_RIGHT_DEL;
207 name += KFSConstants.METHOD_TO_CALL_PARM9_LEFT_DEL + lockFields + KFSConstants.METHOD_TO_CALL_PARM9_RIGHT_DEL;
208 name +=
209 KFSConstants.METHOD_TO_CALL_PARM3_LEFT_DEL + lockSummary.getLockUserId() +
210 KFSConstants.METHOD_TO_CALL_PARM3_RIGHT_DEL;
211 String src = imageDirectory + BCConstants.UNLOCK_BUTTON_NAME;
212 String inputType = "image";
213 String styleClass = "tinybutton";
214 String border= "0";
215
216 List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
217 InputHtmlData inputHtmlData = new InputHtmlData(name, inputType, src);
218 inputHtmlData.setStyleClass(styleClass);
219 inputHtmlData.setBorder(border);
220 htmlDataList.add(inputHtmlData);
221 return htmlDataList;
222 }
223
224 /**
225 * Uses org.kuali.rice.kim.service.PersonService to retrieve user object associated with the given network id (if not blank) and then
226 * returns universal id. Add error to GlobalVariables if the user was not found.
227 *
228 * @param networkID - network id for the user to find
229 * @return universal id for the user or null if not found or the network id was blank
230 */
231 protected String getUniversalIdFromNetworkID(String networkID) {
232 String universalId = null;
233 if (StringUtils.isNotBlank(networkID)) {
234 Person user = getPersonService().getPersonByPrincipalName(networkID);
235 if (user != null) {
236 universalId = user.getPrincipalId();
237 } else {
238 GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, BCKeyConstants.ERROR_LOCK_INVALID_USER, networkID);
239 }
240 }
241
242 return universalId;
243 }
244
245 /**
246 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getReturnUrl(org.kuali.rice.kns.bo.BusinessObject, java.util.Map, java.lang.String)
247 */
248 @Override
249 public HtmlData getReturnUrl(BusinessObject businessObject, LookupForm lookupForm, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
250 return getEmptyAnchorHtmlData();
251 }
252
253 /**
254 * Overridden to prevent a validation exception from thrown when the search method is called to refresh the
255 * results after an error is encountered.
256 *
257 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#validateSearchParameters(java.util.Map)
258 */
259 @Override
260 public void validateSearchParameters(Map fieldValues) {
261 }
262
263 /**
264 * Since this lookupable is called by the budget lookup action, the context will be KFS, not Rice. So the generated inquiries
265 * will not have the Rice context (kr/) and be invalid. This override adds the Rice context to the inquiry Url to working
266 * around the issue.
267 *
268 * @see org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl#getInquiryUrl(org.kuali.rice.kns.bo.BusinessObject,
269 * java.lang.String)
270 */
271 @Override
272 public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
273 AnchorHtmlData inquiryUrl = (AnchorHtmlData)super.getInquiryUrl(bo, propertyName);
274 inquiryUrl.setHref(StringUtils.replace(inquiryUrl.getHref(), KNSConstants.INQUIRY_ACTION, KFSConstants.INQUIRY_ACTION));
275
276 return inquiryUrl;
277 }
278
279 /**
280 * Sets the kualiConfigurationService attribute value.
281 *
282 * @param kualiConfigurationService The kualiConfigurationService to set.
283 */
284 public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) {
285 this.kualiConfigurationService = kualiConfigurationService;
286 }
287
288 /**
289 * @return Returns the personService.
290 */
291 protected PersonService<Person> getPersonService() {
292 if(personService==null)
293 personService = SpringContext.getBean(PersonService.class);
294 return personService;
295 }
296
297 }