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 }