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.purap.document.web.struts; 017 018 import java.util.Iterator; 019 import java.util.Properties; 020 import java.util.TreeMap; 021 022 import javax.servlet.http.HttpServletRequest; 023 import javax.servlet.http.HttpServletResponse; 024 025 import org.apache.commons.lang.StringUtils; 026 import org.apache.struts.action.ActionForm; 027 import org.apache.struts.action.ActionForward; 028 import org.apache.struts.action.ActionMapping; 029 import org.kuali.kfs.module.purap.PurapConstants; 030 import org.kuali.kfs.module.purap.PurapKeyConstants; 031 import org.kuali.kfs.module.purap.PurapPropertyConstants; 032 import org.kuali.kfs.module.purap.SingleConfirmationQuestion; 033 import org.kuali.kfs.module.purap.PurapConstants.AccountsPayableDocumentStrings; 034 import org.kuali.kfs.module.purap.PurapConstants.CMDocumentsStrings; 035 import org.kuali.kfs.module.purap.PurapConstants.PODocumentsStrings; 036 import org.kuali.kfs.module.purap.PurapConstants.PaymentRequestStatuses; 037 import org.kuali.kfs.module.purap.PurapConstants.PurchaseOrderDocTypes; 038 import org.kuali.kfs.module.purap.PurapConstants.PurchaseOrderStatuses; 039 import org.kuali.kfs.module.purap.document.AccountsPayableDocument; 040 import org.kuali.kfs.module.purap.document.AccountsPayableDocumentBase; 041 import org.kuali.kfs.module.purap.document.PurchaseOrderDocument; 042 import org.kuali.kfs.module.purap.document.PurchasingAccountsPayableDocument; 043 import org.kuali.kfs.module.purap.document.service.AccountsPayableService; 044 import org.kuali.kfs.module.purap.document.service.LogicContainer; 045 import org.kuali.kfs.module.purap.document.service.PurapService; 046 import org.kuali.kfs.module.purap.document.service.PurchaseOrderService; 047 import org.kuali.kfs.module.purap.document.validation.event.AttributedPreCalculateAccountsPayableEvent; 048 import org.kuali.kfs.module.purap.util.PurQuestionCallback; 049 import org.kuali.kfs.sys.KFSConstants; 050 import org.kuali.kfs.sys.KFSPropertyConstants; 051 import org.kuali.kfs.sys.context.SpringContext; 052 import org.kuali.kfs.vnd.VendorConstants; 053 import org.kuali.kfs.vnd.businessobject.VendorAddress; 054 import org.kuali.rice.kew.exception.WorkflowException; 055 import org.kuali.rice.kns.bo.Note; 056 import org.kuali.rice.kns.exception.ValidationException; 057 import org.kuali.rice.kns.question.ConfirmationQuestion; 058 import org.kuali.rice.kns.service.BusinessObjectService; 059 import org.kuali.rice.kns.service.DataDictionaryService; 060 import org.kuali.rice.kns.service.KualiConfigurationService; 061 import org.kuali.rice.kns.service.KualiRuleService; 062 import org.kuali.rice.kns.util.GlobalVariables; 063 import org.kuali.rice.kns.util.MessageList; 064 import org.kuali.rice.kns.util.ObjectUtils; 065 import org.kuali.rice.kns.util.RiceKeyConstants; 066 import org.kuali.rice.kns.util.UrlFactory; 067 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase; 068 069 /** 070 * Struts Action for Accounts Payable documents. 071 */ 072 public class AccountsPayableActionBase extends PurchasingAccountsPayableActionBase { 073 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountsPayableActionBase.class); 074 075 @Override 076 public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 077 PurchasingAccountsPayableFormBase baseForm = (PurchasingAccountsPayableFormBase) form; 078 079 ActionForward fwd = super.execute(mapping, form, request, response); 080 081 AccountsPayableDocumentBase document = (AccountsPayableDocumentBase) baseForm.getDocument(); 082 boolean foundAccountExpiredWarning = false; 083 for(int i=0;i<GlobalVariables.getMessageList().size();i++){ 084 if (StringUtils.equals(GlobalVariables.getMessageList().get(i).getErrorKey(),PurapKeyConstants.MESSAGE_CLOSED_OR_EXPIRED_ACCOUNTS_REPLACED)){ 085 foundAccountExpiredWarning = true; 086 } 087 } 088 089 if (!foundAccountExpiredWarning){ 090 SpringContext.getBean(AccountsPayableService.class).generateExpiredOrClosedAccountWarning(document); 091 } 092 093 return fwd; 094 095 } 096 /** 097 * Performs refresh of objects after a lookup. 098 * 099 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#refresh(org.apache.struts.action.ActionMapping, 100 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 101 */ 102 public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 103 PurchasingAccountsPayableFormBase baseForm = (PurchasingAccountsPayableFormBase) form; 104 105 AccountsPayableDocumentBase document = (AccountsPayableDocumentBase) baseForm.getDocument(); 106 107 if (StringUtils.equals(baseForm.getRefreshCaller(), VendorConstants.VENDOR_ADDRESS_LOOKUPABLE_IMPL)) { 108 if (StringUtils.isNotBlank(request.getParameter(KFSPropertyConstants.DOCUMENT + "." + PurapPropertyConstants.VENDOR_ADDRESS_ID))) { 109 Integer vendorAddressGeneratedId = document.getVendorAddressGeneratedIdentifier(); 110 VendorAddress refreshVendorAddress = new VendorAddress(); 111 refreshVendorAddress.setVendorAddressGeneratedIdentifier(vendorAddressGeneratedId); 112 refreshVendorAddress = (VendorAddress) SpringContext.getBean(BusinessObjectService.class).retrieve(refreshVendorAddress); 113 document.templateVendorAddress(refreshVendorAddress); 114 } 115 } 116 117 return super.refresh(mapping, form, request, response); 118 } 119 120 /** 121 * Checks the continuation account indicator and generates warnings if continuation accounts were used to replace original 122 * accounts on the document. 123 * 124 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase) 125 */ 126 @Override 127 protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException { 128 super.loadDocument(kualiDocumentFormBase); 129 AccountsPayableDocument document = (AccountsPayableDocument) kualiDocumentFormBase.getDocument(); 130 131 SpringContext.getBean(AccountsPayableService.class).generateExpiredOrClosedAccountWarning(document); 132 133 SpringContext.getBean(AccountsPayableService.class).updateItemList(document); 134 ((AccountsPayableFormBase) kualiDocumentFormBase).updateItemCounts(); 135 } 136 137 /** 138 * Perform calculation on item line. 139 * 140 * @param mapping An ActionMapping 141 * @param form An ActionForm 142 * @param request The HttpServletRequest 143 * @param response The HttpServletResponse 144 * @return An ActionForward 145 */ 146 @Override 147 public ActionForward calculate(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 148 AccountsPayableFormBase apForm = (AccountsPayableFormBase) form; 149 AccountsPayableDocument apDoc = (AccountsPayableDocument) apForm.getDocument(); 150 151 // call precalculate 152 if (SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedPreCalculateAccountsPayableEvent(apDoc))) { 153 customCalculate(apDoc); 154 155 // set calculated flag according to document type and status 156 if (apForm instanceof PaymentRequestForm && apDoc.getStatusCode().equals(PaymentRequestStatuses.AWAITING_TAX_REVIEW)) { 157 // set calculated tax flag for tax area calculation 158 PaymentRequestForm preqForm = (PaymentRequestForm)apForm; 159 preqForm.setCalculatedTax(true); 160 } 161 else { 162 // set calculated flag for document calculation, whether or not the process calculation rule passes, since it only gives warning 163 apForm.setCalculated(true); 164 } 165 } 166 167 return super.calculate(mapping, form, request, response); 168 } 169 170 @Override 171 public ActionForward clearAllTaxes(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 172 AccountsPayableFormBase payableForm = (AccountsPayableFormBase) form; 173 AccountsPayableDocument apDoc = (AccountsPayableDocument) payableForm.getDocument(); 174 175 SpringContext.getBean(PurapService.class).clearAllTaxes(apDoc); 176 177 return super.clearAllTaxes(mapping, form, request, response); 178 } 179 180 /** 181 * Checks if calculation is required. Currently it is required when it has not already been calculated and full document entry 182 * status has not already passed. 183 * 184 * @param apForm A Form, which must inherit from <code>AccountsPayableFormBase</code> 185 * @return true if calculation is required, false otherwise 186 */ 187 protected boolean requiresCaculate(AccountsPayableFormBase apForm) { 188 boolean requiresCalculate = true; 189 PurchasingAccountsPayableDocument purapDocument = (PurchasingAccountsPayableDocument) apForm.getDocument(); 190 requiresCalculate = !apForm.isCalculated() && !SpringContext.getBean(PurapService.class).isFullDocumentEntryCompleted(purapDocument); 191 192 return requiresCalculate; 193 } 194 195 /** 196 * Returns the current action name. 197 * 198 * @return A String. Set to null! 199 */ 200 public String getActionName() { 201 return null; 202 } 203 204 /** 205 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#route(org.apache.struts.action.ActionMapping, 206 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 207 */ 208 @Override 209 public ActionForward route(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 210 AccountsPayableFormBase apForm = (AccountsPayableFormBase) form; 211 212 // set the last update user id 213 AccountsPayableDocumentBase document = (AccountsPayableDocumentBase) apForm.getDocument(); 214 document.setLastActionPerformedByPersonId(GlobalVariables.getUserSession().getPerson().getPrincipalId()); 215 216 // if form is not yet calculated, return and prompt user to calculate 217 if (requiresCaculate(apForm)) { 218 GlobalVariables.getMessageMap().putError(KFSConstants.DOCUMENT_ERRORS, PurapKeyConstants.ERROR_APPROVE_REQUIRES_CALCULATE); 219 return mapping.findForward(KFSConstants.MAPPING_BASIC); 220 } 221 222 // recalculate 223 customCalculate((AccountsPayableDocument) apForm.getDocument()); 224 225 // route 226 ActionForward forward = super.route(mapping, form, request, response); 227 228 // if successful, then redirect back to init 229 boolean successMessageFound = false; 230 MessageList messageList = GlobalVariables.getMessageList(); 231 for (int i = 0; i < messageList.size(); i++) { 232 if (StringUtils.equals(messageList.get(i).getErrorKey(), RiceKeyConstants.MESSAGE_ROUTE_SUCCESSFUL)) { 233 successMessageFound = true; 234 break; 235 } 236 } 237 238 if (successMessageFound) { 239 String basePath = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(KFSConstants.APPLICATION_URL_KEY); 240 241 Properties parameters = new Properties(); 242 parameters.put(KFSConstants.DISPATCH_REQUEST_PARAMETER, KFSConstants.DOC_HANDLER_METHOD); 243 parameters.put(KFSConstants.PARAMETER_COMMAND, "initiate"); 244 parameters.put(KFSConstants.DOCUMENT_TYPE_NAME, apForm.getDocTypeName()); 245 246 String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + "purap" + this.getActionName() + ".do", parameters); 247 forward = new ActionForward(lookupUrl, true); 248 } 249 250 return forward; 251 } 252 253 /** 254 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#save(org.apache.struts.action.ActionMapping, 255 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 256 */ 257 @Override 258 public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 259 AccountsPayableFormBase apForm = (AccountsPayableFormBase) form; 260 261 if (!requiresCaculate(apForm)) { 262 return super.save(mapping, form, request, response); 263 } 264 265 GlobalVariables.getMessageMap().putError(KFSConstants.DOCUMENT_ERRORS, PurapKeyConstants.ERROR_SAVE_REQUIRES_CALCULATE); 266 return mapping.findForward(KFSConstants.MAPPING_BASIC); 267 268 } 269 270 /** 271 * A wrapper method which prompts for a reason to hold a payment request or credit memo. 272 * 273 * @param mapping An ActionMapping 274 * @param form An ActionForm 275 * @param request The HttpServletRequest 276 * @param response The HttpServletResponse 277 * @param questionType A String used to distinguish which question is being asked 278 * @param notePrefix A String explaining what action was taken, to be prepended to the note containing the reason, which gets 279 * written to the document 280 * @param operation A one-word String description of the action to be taken, to be substituted into the message. (Can be an 281 * empty String for some messages.) 282 * @param messageKey A key to the message which will appear on the question screen 283 * @param callback A PurQuestionCallback 284 * @return An ActionForward 285 * @throws Exception 286 */ 287 protected ActionForward askQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionType, String notePrefix, String operation, String messageKey, PurQuestionCallback callback) throws Exception { 288 TreeMap<String, PurQuestionCallback> questionsAndCallbacks = new TreeMap<String, PurQuestionCallback>(); 289 questionsAndCallbacks.put(questionType, callback); 290 return askQuestionWithInput(mapping, form, request, response, questionType, notePrefix, operation, messageKey, questionsAndCallbacks, "", mapping.findForward(KFSConstants.MAPPING_BASIC)); 291 } 292 293 /** 294 * Builds and asks questions which require text input by the user for a payment request or a credit memo. 295 * 296 * @param mapping An ActionMapping 297 * @param form An ActionForm 298 * @param request The HttpServletRequest 299 * @param response The HttpServletResponse 300 * @param questionType A String used to distinguish which question is being asked 301 * @param notePrefix A String explaining what action was taken, to be prepended to the note containing the reason, which gets 302 * written to the document 303 * @param operation A one-word String description of the action to be taken, to be substituted into the message. (Can be an 304 * empty String for some messages.) 305 * @param messageKey A (whole) key to the message which will appear on the question screen 306 * @param questionsAndCallbacks A TreeMap associating the type of question to be asked and the type of callback which should 307 * happen in that case 308 * @param messagePrefix The most general part of a key to a message text to be retrieved from KualiConfigurationService, 309 * Describes a collection of questions. 310 * @param redirect An ActionForward to return to if done with questions 311 * @return An ActionForward 312 * @throws Exception 313 */ 314 protected ActionForward askQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionType, String notePrefix, String operation, String messageKey, TreeMap<String, PurQuestionCallback> questionsAndCallbacks, String messagePrefix, ActionForward redirect) throws Exception { 315 KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form; 316 AccountsPayableDocumentBase apDocument = (AccountsPayableDocumentBase) kualiDocumentFormBase.getDocument(); 317 318 String question = (String) request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME); 319 String reason = request.getParameter(KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME); 320 String noteText = ""; 321 322 KualiConfigurationService kualiConfiguration = SpringContext.getBean(KualiConfigurationService.class); 323 String firstQuestion = questionsAndCallbacks.firstKey(); 324 PurQuestionCallback callback = null; 325 Iterator questions = questionsAndCallbacks.keySet().iterator(); 326 String mapQuestion = null; 327 String key = null; 328 329 // Start in logic for confirming the close. 330 if (question == null) { 331 key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, firstQuestion); 332 String message = StringUtils.replace(key, "{0}", operation); 333 334 // Ask question if not already asked. 335 return this.performQuestionWithInput(mapping, form, request, response, firstQuestion, message, KFSConstants.CONFIRMATION_QUESTION, questionType, ""); 336 } 337 else { 338 // find callback for this question 339 while (questions.hasNext()) { 340 mapQuestion = (String) questions.next(); 341 342 if (StringUtils.equals(mapQuestion, question)) { 343 callback = questionsAndCallbacks.get(mapQuestion); 344 break; 345 } 346 } 347 key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, mapQuestion); 348 349 Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON); 350 if (question.equals(mapQuestion) && buttonClicked.equals(ConfirmationQuestion.NO)) { 351 // If 'No' is the button clicked, just reload the doc 352 353 String nextQuestion = null; 354 // ask another question if more left 355 if (questions.hasNext()) { 356 nextQuestion = (String) questions.next(); 357 key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, nextQuestion); 358 359 return this.performQuestionWithInput(mapping, form, request, response, nextQuestion, key, KFSConstants.CONFIRMATION_QUESTION, questionType, ""); 360 } 361 else { 362 363 return mapping.findForward(KFSConstants.MAPPING_BASIC); 364 } 365 } 366 // Have to check length on value entered. 367 String introNoteMessage = notePrefix + KFSConstants.BLANK_SPACE; 368 369 // Build out full message. 370 noteText = introNoteMessage + reason; 371 int noteTextLength = noteText.length(); 372 373 // Get note text max length from DD. 374 int noteTextMaxLength = SpringContext.getBean(DataDictionaryService.class).getAttributeMaxLength(Note.class, KFSConstants.NOTE_TEXT_PROPERTY_NAME).intValue(); 375 if (StringUtils.isBlank(reason) || (noteTextLength > noteTextMaxLength)) { 376 // Figure out exact number of characters that the user can enter. 377 int reasonLimit = noteTextMaxLength - noteTextLength; 378 if (reason == null) { 379 // Prevent a NPE by setting the reason to a blank string. 380 reason = ""; 381 } 382 383 return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, mapQuestion, key, KFSConstants.CONFIRMATION_QUESTION, questionType, "", reason, PurapKeyConstants.ERROR_PAYMENT_REQUEST_REASON_REQUIRED, KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME, new Integer(reasonLimit).toString()); 384 } 385 } 386 387 // make callback 388 if (ObjectUtils.isNotNull(callback)) { 389 AccountsPayableDocument refreshedApDocument = callback.doPostQuestion(apDocument, noteText); 390 kualiDocumentFormBase.setDocument(refreshedApDocument); 391 } 392 String nextQuestion = null; 393 // ask another question if more left 394 if (questions.hasNext()) { 395 nextQuestion = (String) questions.next(); 396 key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, nextQuestion); 397 398 return this.performQuestionWithInput(mapping, form, request, response, nextQuestion, key, KFSConstants.CONFIRMATION_QUESTION, questionType, ""); 399 } 400 401 return redirect; 402 } 403 404 /** 405 * Used to look up messages to be displayed, from the KualiConfigurationService, given either a whole key or two parts of a key 406 * that may be concatenated together. 407 * 408 * @param messageKey String. One of the message keys in PurapKeyConstants. 409 * @param messagePrefix String. A prefix to the question key, such as "ap.question." that, concatenated with the question, 410 * comprises the whole key of the message. 411 * @param kualiConfiguration An instance of KualiConfigurationService 412 * @param question String. The most specific part of the message key in PurapKeyConstants. 413 * @return The message to be displayed given the key 414 */ 415 protected String getQuestionProperty(String messageKey, String messagePrefix, KualiConfigurationService kualiConfiguration, String question) { 416 return kualiConfiguration.getPropertyString((StringUtils.isEmpty(messagePrefix)) ? messageKey : messagePrefix + question); 417 } 418 419 public ActionForward reopenPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 420 LOG.debug("Reopen PO started"); 421 return askQuestionsAndPerformReopenPurchaseOrder(mapping, form, request, response); 422 } 423 424 /** 425 * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#cancel(org.apache.struts.action.ActionMapping, 426 * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) 427 */ 428 @Override 429 public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 430 return askCancelQuestion(mapping, form, request, response); 431 } 432 433 /** 434 * Constructs and asks the question as to whether the user wants to cancel, for payment requests and credit memos. 435 * 436 * @param mapping An ActionMapping 437 * @param form An ActionForm 438 * @param request The HttpServletRequest 439 * @param response The HttpServletResponse 440 * @return An ActionForward 441 * @throws Exception 442 */ 443 protected ActionForward askCancelQuestion(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 444 PurchasingAccountsPayableFormBase apForm = (PurchasingAccountsPayableFormBase) form; 445 446 String operation = "Cancel "; 447 PurQuestionCallback callback = cancelCallbackMethod(); 448 TreeMap<String, PurQuestionCallback> questionsAndCallbacks = new TreeMap<String, PurQuestionCallback>(); 449 questionsAndCallbacks.put("cancelAP", callback); 450 451 return askQuestionWithInput(mapping, form, request, response, CMDocumentsStrings.CANCEL_CM_QUESTION, AccountsPayableDocumentStrings.CANCEL_NOTE_PREFIX, operation, PurapKeyConstants.CREDIT_MEMO_QUESTION_CANCEL_DOCUMENT, questionsAndCallbacks, PurapKeyConstants.AP_QUESTION_PREFIX, mapping.findForward(KFSConstants.MAPPING_PORTAL)); 452 } 453 454 /** 455 * Returns a question callback for the Cancel Purchase Order action. 456 * 457 * @return A PurQuestionCallback with a post-question activity appropriate to the Cancel PO action 458 */ 459 protected PurQuestionCallback cancelPOActionCallbackMethod() { 460 461 return new PurQuestionCallback() { 462 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 463 // base impl do nothing 464 return document; 465 } 466 }; 467 } 468 469 /** 470 * Returns a question callback for the Cancel action. 471 * 472 * @return A PurQuestionCallback which does post-question tasks appropriate to Cancellation. 473 */ 474 protected PurQuestionCallback cancelCallbackMethod() { 475 return new PurQuestionCallback() { 476 public AccountsPayableDocument doPostQuestion(AccountsPayableDocument document, String noteText) throws Exception { 477 SpringContext.getBean(AccountsPayableService.class).cancelAccountsPayableDocumentByCheckingDocumentStatus(document, noteText); 478 return document; 479 } 480 }; 481 } 482 483 protected ActionForward askQuestionsAndPerformReopenPurchaseOrder(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { 484 LOG.debug("askQuestionsAndPerformDocumentAction started."); 485 KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form; 486 AccountsPayableDocumentBase apDoc = (AccountsPayableDocumentBase) kualiDocumentFormBase.getDocument(); 487 Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME); 488 String questionType = PODocumentsStrings.REOPEN_PO_QUESTION; 489 String confirmType = PODocumentsStrings.CONFIRM_REOPEN_QUESTION; 490 String messageType = PurapKeyConstants.PURCHASE_ORDER_MESSAGE_REOPEN_DOCUMENT; 491 String operation = "Reopen "; 492 493 try { 494 KualiConfigurationService kualiConfiguration = SpringContext.getBean(KualiConfigurationService.class); 495 496 // Start in logic for confirming the proposed operation. 497 if (ObjectUtils.isNull(question)) { 498 String key = kualiConfiguration.getPropertyString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_DOCUMENT); 499 String message = StringUtils.replace(key, "{0}", operation); 500 return this.performQuestionWithoutInput(mapping, form, request, response, questionType, message, KFSConstants.CONFIRMATION_QUESTION, questionType, ""); 501 } 502 else { 503 Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON); 504 if (question.equals(questionType) && buttonClicked.equals(ConfirmationQuestion.NO)) { 505 // If 'No' is the button clicked, just reload the doc 506 return mapping.findForward(KFSConstants.MAPPING_BASIC); 507 } 508 else if (question.equals(confirmType) && buttonClicked.equals(SingleConfirmationQuestion.OK)) { 509 // This is the case when the user clicks on "OK" in the end; redirect to the preq doc 510 return mapping.findForward(KFSConstants.MAPPING_BASIC); 511 } 512 } 513 514 PurchaseOrderDocument po = apDoc.getPurchaseOrderDocument(); 515 if (!po.isPendingActionIndicator() && PurapConstants.PurchaseOrderStatuses.CLOSED.equals(po.getStatusCode())) { 516 /* 517 * Below if-else code block calls PurchaseOrderService methods that will throw ValidationException objects if errors 518 * occur during any process in the attempt to perform its actions. Assume, if these return successfully, that the 519 * PurchaseOrderDocument object returned from each is the newly created document and that all actions in the method 520 * were run correctly. NOTE: IF BELOW IF-ELSE IS EDITED THE NEW METHODS CALLED MUST THROW ValidationException OBJECT 521 * IF AN ERROR IS ADDED TO THE GlobalVariables 522 */ 523 po = initiateReopenPurchaseOrder(po, kualiDocumentFormBase.getAnnotation()); 524 525 if (!GlobalVariables.getMessageMap().hasNoErrors()) { 526 throw new ValidationException("errors occurred during new PO creation"); 527 } 528 529 if (StringUtils.isNotEmpty(messageType)) { 530 GlobalVariables.getMessageList().add(messageType); 531 } 532 return this.performQuestionWithoutInput(mapping, form, request, response, confirmType, kualiConfiguration.getPropertyString(messageType), PODocumentsStrings.SINGLE_CONFIRMATION_QUESTION, questionType, ""); 533 } 534 else { 535 return this.performQuestionWithoutInput(mapping, form, request, response, confirmType, "Unable to reopen the PO at this time due to the incorrect PO status or a pending PO change document.", PODocumentsStrings.SINGLE_CONFIRMATION_QUESTION, questionType, ""); 536 } 537 538 } 539 catch (ValidationException ve) { 540 throw ve; 541 } 542 } 543 544 public PurchaseOrderDocument initiateReopenPurchaseOrder(PurchaseOrderDocument po, String annotation) { 545 try { 546 LogicContainer logicToRun = new LogicContainer() { 547 public Object runLogic(Object[] objects) throws Exception { 548 PurchaseOrderDocument po = (PurchaseOrderDocument) objects[0]; 549 550 Note cancelNote = new Note(); 551 cancelNote.setAuthorUniversalIdentifier(GlobalVariables.getUserSession().getPerson().getPrincipalId()); 552 cancelNote.setNoteText(SpringContext.getBean(KualiConfigurationService.class).getPropertyString(PurapKeyConstants.AP_REOPENS_PURCHASE_ORDER_NOTE)); 553 po.addNote(cancelNote); 554 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(po); 555 556 return SpringContext.getBean(PurchaseOrderService.class).createAndRoutePotentialChangeDocument(po.getDocumentNumber(), PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT, (String) objects[1], null, PurchaseOrderStatuses.PENDING_REOPEN); 557 } 558 }; 559 return (PurchaseOrderDocument) SpringContext.getBean(PurapService.class).performLogicWithFakedUserSession(KFSConstants.SYSTEM_USER, logicToRun, new Object[] { po, annotation }); 560 } 561 catch (WorkflowException e) { 562 String errorMsg = "Workflow Exception caught: " + e.getLocalizedMessage(); 563 LOG.error(errorMsg, e); 564 throw new RuntimeException(errorMsg, e); 565 } 566 catch (Exception e) { 567 throw new RuntimeException(e); 568 } 569 } 570 571 }