View Javadoc

1   /*
2    * Copyright 2006 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.module.purap.document.web.struts;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.*;
20  import org.kuali.ole.module.purap.*;
21  import org.kuali.ole.module.purap.PurapConstants.PODocumentsStrings;
22  import org.kuali.ole.module.purap.PurapConstants.PurchaseOrderDocTypes;
23  import org.kuali.ole.module.purap.PurapConstants.PurchaseOrderStatuses;
24  import org.kuali.ole.module.purap.businessobject.*;
25  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
26  import org.kuali.ole.module.purap.document.PurchaseOrderRetransmitDocument;
27  import org.kuali.ole.module.purap.document.PurchaseOrderSplitDocument;
28  import org.kuali.ole.module.purap.document.service.FaxService;
29  import org.kuali.ole.module.purap.document.service.PurapService;
30  import org.kuali.ole.module.purap.document.service.PurchaseOrderService;
31  import org.kuali.ole.module.purap.document.validation.event.AttributedAddVendorToQuoteEvent;
32  import org.kuali.ole.module.purap.document.validation.event.AttributedAssignSensitiveDataEvent;
33  import org.kuali.ole.module.purap.document.validation.event.AttributedSplitPurchaseOrderEvent;
34  import org.kuali.ole.module.purap.service.SensitiveDataService;
35  import org.kuali.ole.sys.OLEConstants;
36  import org.kuali.ole.sys.OLEPropertyConstants;
37  import org.kuali.ole.sys.context.SpringContext;
38  import org.kuali.ole.vnd.VendorConstants.AddressTypes;
39  import org.kuali.ole.vnd.businessobject.VendorAddress;
40  import org.kuali.ole.vnd.businessobject.VendorDetail;
41  import org.kuali.ole.vnd.document.service.VendorService;
42  import org.kuali.rice.core.api.config.property.ConfigurationService;
43  import org.kuali.rice.core.api.datetime.DateTimeService;
44  import org.kuali.rice.kew.api.WorkflowDocument;
45  import org.kuali.rice.kew.api.exception.WorkflowException;
46  import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
47  import org.kuali.rice.kns.question.ConfirmationQuestion;
48  import org.kuali.rice.kns.service.DataDictionaryService;
49  import org.kuali.rice.kns.service.DictionaryValidationService;
50  import org.kuali.rice.kns.service.DocumentHelperService;
51  import org.kuali.rice.kns.util.KNSGlobalVariables;
52  import org.kuali.rice.kns.web.struts.form.BlankFormFile;
53  import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
54  import org.kuali.rice.krad.bo.Note;
55  import org.kuali.rice.krad.exception.ValidationException;
56  import org.kuali.rice.krad.service.BusinessObjectService;
57  import org.kuali.rice.krad.service.DocumentService;
58  import org.kuali.rice.krad.service.KualiRuleService;
59  import org.kuali.rice.krad.service.SequenceAccessorService;
60  import org.kuali.rice.krad.util.GlobalVariables;
61  import org.kuali.rice.krad.util.ObjectUtils;
62  import org.kuali.rice.krad.util.UrlFactory;
63  
64  import javax.servlet.ServletOutputStream;
65  import javax.servlet.http.HttpServletRequest;
66  import javax.servlet.http.HttpServletResponse;
67  import java.io.ByteArrayOutputStream;
68  import java.sql.Date;
69  import java.util.*;
70  
71  /**
72   * Struts Action for Purchase Order document.
73   */
74  public class PurchaseOrderAction extends PurchasingActionBase {
75      protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PurchaseOrderAction.class);
76  
77      /**
78       * @see org.kuali.rice.kns.web.struts.action.KualiAction#refresh(org.apache.struts.action.ActionMapping,
79       *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
80       */
81      @Override
82      public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
83  
84          PurchaseOrderForm poForm = (PurchaseOrderForm) form;
85  
86          PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
87          BusinessObjectService businessObjectService = SpringContext.getBean(BusinessObjectService.class);
88  
89          // Handling lookups for alternate vendor for non-primary vendor payment that are only specific to Purchase Order.
90          if (request.getParameter("document.alternateVendorHeaderGeneratedIdentifier") != null && request.getParameter("document.alternateVendorDetailAssignedIdentifier") != null) {
91              Integer alternateVendorDetailAssignedId = document.getAlternateVendorDetailAssignedIdentifier();
92              Integer alternateVendorHeaderGeneratedId = document.getAlternateVendorHeaderGeneratedIdentifier();
93              VendorDetail refreshVendorDetail = new VendorDetail();
94              refreshVendorDetail.setVendorDetailAssignedIdentifier(alternateVendorDetailAssignedId);
95              refreshVendorDetail.setVendorHeaderGeneratedIdentifier(alternateVendorHeaderGeneratedId);
96              refreshVendorDetail = (VendorDetail) businessObjectService.retrieve(refreshVendorDetail);
97              document.templateAlternateVendor(refreshVendorDetail);
98          }
99  
100         // Handling lookups for quote list that is specific to Purchase Order.
101         if (request.getParameter("document.purchaseOrderQuoteListIdentifier") != null) {
102             // do a lookup and add all the vendors!
103             Integer poQuoteListIdentifier = document.getPurchaseOrderQuoteListIdentifier();
104             PurchaseOrderQuoteList poQuoteList = new PurchaseOrderQuoteList();
105             poQuoteList.setPurchaseOrderQuoteListIdentifier(poQuoteListIdentifier);
106             poQuoteList = (PurchaseOrderQuoteList) businessObjectService.retrieve(poQuoteList);
107             if (poQuoteList.isActive()) {
108                 for (PurchaseOrderQuoteListVendor poQuoteListVendor : poQuoteList.getQuoteListVendors()) {
109                     if (poQuoteListVendor.isActive()) {
110                         VendorDetail newVendor = poQuoteListVendor.getVendorDetail();
111                         if (newVendor.isActiveIndicator() && !newVendor.isVendorDebarred()) {
112                             PurchaseOrderVendorQuote newPOVendorQuote = SpringContext.getBean(PurchaseOrderService.class).populateQuoteWithVendor(newVendor.getVendorHeaderGeneratedIdentifier(), newVendor.getVendorDetailAssignedIdentifier(), document.getDocumentNumber());
113                             document.getPurchaseOrderVendorQuotes().add(newPOVendorQuote);
114                         }
115                     }
116                 }
117             }
118         }
119 
120         // Handling lookups for quote vendor search that is specific to Purchase Order.
121         String newVendorHeaderGeneratedIdentifier = request.getParameter("newPurchaseOrderVendorQuote.vendorHeaderGeneratedIdentifier");
122         String newVendorDetailAssignedIdentifier = request.getParameter("newPurchaseOrderVendorQuote.vendorDetailAssignedIdentifier");
123         if (newVendorHeaderGeneratedIdentifier != null && newVendorDetailAssignedIdentifier != null) {
124 
125             PurchaseOrderVendorQuote newPOVendorQuote = SpringContext.getBean(PurchaseOrderService.class).populateQuoteWithVendor(new Integer(newVendorHeaderGeneratedIdentifier), new Integer(newVendorDetailAssignedIdentifier), document.getDocumentNumber());
126 
127             poForm.setNewPurchaseOrderVendorQuote(newPOVendorQuote);
128         }
129 
130         String newStipulation = request.getParameter(OLEPropertyConstants.DOCUMENT + "." + PurapPropertyConstants.VENDOR_STIPULATION_DESCRIPTION);
131         if (StringUtils.isNotEmpty(newStipulation)) {
132             poForm.getNewPurchaseOrderVendorStipulationLine().setVendorStipulationDescription(newStipulation);
133         }
134 
135         return super.refresh(mapping, form, request, response);
136     }
137 
138     /**
139      * Inactivate an item from the purchase order document.
140      *
141      * @param mapping  An ActionMapping
142      * @param form     An ActionForm
143      * @param request  The HttpServletRequest
144      * @param response The HttpServletResponse
145      * @return An ActionForward
146      * @throws Exception
147      */
148     public ActionForward inactivateItem(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
149         PurchasingAccountsPayableFormBase purchasingForm = (PurchasingAccountsPayableFormBase) form;
150 
151         PurchaseOrderDocument purDocument = (PurchaseOrderDocument) purchasingForm.getDocument();
152         List items = purDocument.getItems();
153         PurchaseOrderItem item = (PurchaseOrderItem) items.get(getSelectedLine(request));
154         item.setItemActiveIndicator(false);
155 
156         return mapping.findForward(OLEConstants.MAPPING_BASIC);
157     }
158 
159     /**
160      * For use with a specific set of methods of this class that create new purchase order-derived document types in response to
161      * user actions, including <code>closePo</code>, <code>reopenPo</code>, <code>paymentHoldPo</code>, <code>removeHoldPo</code>,
162      * <code>splitPo</code>, <code>amendPo</code>, and <code>voidPo</code>. It employs the question framework to ask
163      * the user for a response before creating and routing the new document. The response should consist of a note detailing a
164      * reason, and either yes or no. This method can be better understood if it is noted that it will be gone through twice (via the
165      * question framework); when each question is originally asked, and again when the yes/no response is processed, for
166      * confirmation.
167      *
168      * @param mapping      These are boiler-plate.
169      * @param form         "
170      * @param request      "
171      * @param response     "
172      * @param questionType A string identifying the type of question being asked.
173      * @param confirmType  A string identifying which type of question is being confirmed.
174      * @param documentType A string, the type of document to create
175      * @param notePrefix   A string to appear before the note in the BO Notes tab
176      * @param messageType  A string to appear on the PO once the question framework is done, describing the action taken
177      * @param operation    A string, the verb to insert in the original question describing the action to be taken
178      * @return An ActionForward
179      * @throws Exception
180      */
181     protected ActionForward askQuestionsAndPerformDocumentAction(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionType, String confirmType, String documentType, String notePrefix, String messageType, String operation) throws Exception {
182         LOG.debug("askQuestionsAndPerformDocumentAction started.");
183         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
184         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
185         Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
186         String reason = request.getParameter(OLEConstants.QUESTION_REASON_ATTRIBUTE_NAME);
187         String noteText = "";
188 
189         try {
190             ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
191 
192             // Start in logic for confirming the proposed operation.
193             if (ObjectUtils.isNull(question)) {
194                 String message = "";
195                 if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_SPLIT_DOCUMENT)) {
196                     message = kualiConfiguration.getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_SPLIT_QUESTION_TEXT);
197                 } else {
198                     String key = kualiConfiguration.getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_DOCUMENT);
199                     message = StringUtils.replace(key, "{0}", operation);
200                 }
201                 // Ask question if not already asked.
202                 return this.performQuestionWithInput(mapping, form, request, response, questionType, message, OLEConstants.CONFIRMATION_QUESTION, questionType, "");
203             } else {
204                 Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
205                 if (question.equals(questionType) && buttonClicked.equals(ConfirmationQuestion.NO)) {
206 
207                     // If 'No' is the button clicked, just reload the doc
208                     return returnToPreviousPage(mapping, kualiDocumentFormBase);
209                 } else if (question.equals(confirmType) && buttonClicked.equals(SingleConfirmationQuestion.OK)) {
210 
211                     // This is the case when the user clicks on "OK" in the end.
212                     // After we inform the user that the close has been rerouted, we'll redirect to the portal page.
213                     return mapping.findForward(OLEConstants.MAPPING_PORTAL);
214                 } else {
215                     // Have to check length on value entered.
216                     String introNoteMessage = notePrefix + OLEConstants.BLANK_SPACE;
217 
218                     // Build out full message.
219                     noteText = introNoteMessage + reason;
220                     int noteTextLength = noteText.length();
221 
222                     // Get note text max length from DD.
223                     int noteTextMaxLength = SpringContext.getBean(DataDictionaryService.class).getAttributeMaxLength(Note.class, OLEConstants.NOTE_TEXT_PROPERTY_NAME).intValue();
224 
225                     if (StringUtils.isBlank(reason) || (noteTextLength > noteTextMaxLength)) {
226                         // Figure out exact number of characters that the user can enter.
227                         int reasonLimit = noteTextMaxLength - noteTextLength;
228 
229                         if (ObjectUtils.isNull(reason)) {
230                             // Prevent a NPE by setting the reason to a blank string.
231                             reason = "";
232                         }
233 
234                         String message = "";
235                         String key = kualiConfiguration.getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_DOCUMENT);
236                         message = StringUtils.replace(key, "{0}", operation);
237 
238                         return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, questionType, message, OLEConstants.CONFIRMATION_QUESTION, questionType, "", reason, PurapKeyConstants.ERROR_PURCHASE_ORDER_REASON_REQUIRED, OLEConstants.QUESTION_REASON_ATTRIBUTE_NAME, new Integer(reasonLimit).toString());
239                     }
240                 }
241             }
242             // Below used as a place holder to allow code to specify actionForward to return if not a 'success question'
243             ActionForward returnActionForward = null;
244             if (!po.isPendingActionIndicator()) {
245                 /*
246                  * Below if-else code block calls PurchaseOrderService methods that will throw ValidationException objects if errors
247                  * occur during any process in the attempt to perform its actions. Assume, if these return successfully, that the
248                  * PurchaseOrderDocument object returned from each is the newly created document and that all actions in the method
249                  * were run correctly. NOTE: IF BELOW IF-ELSE IS EDITED THE NEW METHODS CALLED MUST THROW ValidationException OBJECT
250                  * IF AN ERROR IS ADDED TO THE GlobalVariables
251                  */
252                 if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_SPLIT_DOCUMENT)) {
253                     po.setPendingSplit(true);
254                     // Save adding the note for after the items are picked.
255                     ((PurchaseOrderForm) kualiDocumentFormBase).setSplitNoteText(noteText);
256                     returnActionForward = mapping.findForward(OLEConstants.MAPPING_BASIC);
257                 } else {
258                     String newStatus = null;
259                     if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_AMENDMENT_DOCUMENT)) {
260                         newStatus = PurchaseOrderStatuses.APPDOC_AMENDMENT;
261                         po = SpringContext.getBean(PurchaseOrderService.class).createAndSavePotentialChangeDocument(kualiDocumentFormBase.getDocument().getDocumentNumber(), documentType, newStatus);
262                         returnActionForward = mapping.findForward(OLEConstants.MAPPING_BASIC);
263                     } else {
264                         if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_CLOSE_DOCUMENT)) {
265                             newStatus = PurchaseOrderStatuses.APPDOC_PENDING_CLOSE;
266                         } else if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT)) {
267                             newStatus = PurchaseOrderStatuses.APPDOC_PENDING_REOPEN;
268                         } else if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_VOID_DOCUMENT)) {
269                             newStatus = PurchaseOrderStatuses.APPDOC_PENDING_VOID;
270                         } else if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_PAYMENT_HOLD_DOCUMENT)) {
271                             newStatus = PurchaseOrderStatuses.APPDOC_PENDING_PAYMENT_HOLD;
272                         } else if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_REMOVE_HOLD_DOCUMENT)) {
273                             newStatus = PurchaseOrderStatuses.APPDOC_PENDING_REMOVE_HOLD;
274                         } else if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_RETRANSMIT_DOCUMENT)) {
275                             newStatus = PurchaseOrderStatuses.APPDOC_PENDING_RETRANSMIT;
276                         }
277                         po = SpringContext.getBean(PurchaseOrderService.class).createAndRoutePotentialChangeDocument(kualiDocumentFormBase.getDocument().getDocumentNumber(), documentType, kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase), newStatus);
278                     }
279                     if (!GlobalVariables.getMessageMap().hasNoErrors()) {
280                         throw new ValidationException("errors occurred during new PO creation");
281                     }
282 
283                     String previousDocumentId = kualiDocumentFormBase.getDocId();
284                     // Assume at this point document was created properly and 'po' variable is new PurchaseOrderDocument created
285                     kualiDocumentFormBase.setDocument(po);
286                     kualiDocumentFormBase.setDocId(po.getDocumentNumber());
287                     kualiDocumentFormBase.setDocTypeName(po.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
288 
289                     Note newNote = new Note();
290                     if (documentType.equals(PurapConstants.PurchaseOrderDocTypes.PURCHASE_ORDER_AMENDMENT_DOCUMENT)) {
291                         noteText = noteText + " (Previous Document Id is " + previousDocumentId + ")";
292                     }
293                     newNote.setNoteText(noteText);
294                     newNote.setNoteTypeCode(OLEConstants.NoteTypeEnum.BUSINESS_OBJECT_NOTE_TYPE.getCode());
295                     kualiDocumentFormBase.setNewNote(newNote);
296 
297                     kualiDocumentFormBase.setAttachmentFile(new BlankFormFile());
298 
299                     insertBONote(mapping, kualiDocumentFormBase, request, response);
300 
301                     //the newly created notes needed to be set to the docuemnt
302                     //on the oldest purchase order otherwise, in POA when you try to save
303                     //the POA, it will throw Ojblockexception error.
304                     //OLEMI-8394
305                     PurchaseOrderDocument oldestPurchaseOrder = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
306                     List<Note> newNotes = getNoteService().getByRemoteObjectId(oldestPurchaseOrder.getObjectId());
307 
308                     oldestPurchaseOrder.setNotes(newNotes);
309                 }
310                 if (StringUtils.isNotEmpty(messageType)) {
311                     KNSGlobalVariables.getMessageList().add(messageType);
312                 }
313             }
314             if (ObjectUtils.isNotNull(returnActionForward)) {
315                 return returnActionForward;
316             } else {
317 
318                 return this.performQuestionWithoutInput(mapping, form, request, response, confirmType, kualiConfiguration.getPropertyValueAsString(messageType), PODocumentsStrings.SINGLE_CONFIRMATION_QUESTION, questionType, "");
319             }
320         } catch (ValidationException ve) {
321             throw ve;
322         }
323     }
324 
325     /**
326      * Invoked when the user pressed on the Close Order button on a Purchase Order page to Close the PO. It will
327      * display the question page to the user to ask whether the user really wants to close the PO and ask the user to enter a reason
328      * in the text area. If the user has entered the reason, it will invoke a service method to do the processing for closing a PO,
329      * then display a Single Confirmation page to inform the user that the PO Close Document has been routed.
330      *
331      * @param mapping  An ActionMapping
332      * @param form     An ActionForm
333      * @param request  The HttpServletRequest
334      * @param response The HttpServletResponse
335      * @return An ActionForward
336      * @throws Exception
337      */
338     public ActionForward closePo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
339         LOG.debug("ClosePO started.");
340         String operation = "Close ";
341         PurchaseOrderDocument po = ((PurchaseOrderForm) form).getPurchaseOrderDocument();
342 
343         if (po.canClosePOForTradeIn()) {
344             return askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.CLOSE_QUESTION, PODocumentsStrings.CLOSE_CONFIRM, PurchaseOrderDocTypes.PURCHASE_ORDER_CLOSE_DOCUMENT, PODocumentsStrings.CLOSE_NOTE_PREFIX, PurapKeyConstants.PURCHASE_ORDER_MESSAGE_CLOSE_DOCUMENT, operation);
345         } else {
346             return mapping.findForward(OLEConstants.MAPPING_BASIC);
347         }
348     }
349 
350     /**
351      * Is invoked when the user pressed on the Payment Hold button on a Purchase Order page to put the PO on hold. It
352      * will display the question page to the user to ask whether the user really wants to put the PO on hold and ask the user to
353      * enter a reason in the text area. If the user has entered the reason, it will invoke a service method to do the processing for
354      * putting a PO on hold, then display a Single Confirmation page to inform the user that the PO Payment Hold Document has been
355      * routed.
356      *
357      * @param mapping  An ActionMapping
358      * @param form     An ActionForm
359      * @param request  The HttpServletRequest
360      * @param response The HttpServletResponse
361      * @return An ActionForward
362      * @throws Exception
363      */
364     public ActionForward paymentHoldPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
365         LOG.debug("PaymentHoldPO started.");
366         String operation = "Hold Payment ";
367 
368         return askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.PAYMENT_HOLD_QUESTION, PODocumentsStrings.PAYMENT_HOLD_CONFIRM, PurchaseOrderDocTypes.PURCHASE_ORDER_PAYMENT_HOLD_DOCUMENT, PODocumentsStrings.PAYMENT_HOLD_NOTE_PREFIX, PurapKeyConstants.PURCHASE_ORDER_MESSAGE_PAYMENT_HOLD, operation);
369     }
370 
371     /**
372      * Is invoked when the user pressed on the Remove Hold button on a Payment Hold PO page to remove the PO from hold.
373      * It will display the question page to the user to ask whether the user really wants to remove the PO from hold and ask the
374      * user to enter a reason in the text area. If the user has entered the reason, it will invoke a service method to do the
375      * processing for removing a PO from hold, then display a Single Confirmation page to inform the user that the PO Remove Hold
376      * Document has been routed.
377      *
378      * @param mapping  An ActionMapping
379      * @param form     An ActionForm
380      * @param request  The HttpServletRequest
381      * @param response The HttpServletResponse
382      * @return An ActionForward
383      * @throws Exception
384      */
385     public ActionForward removeHoldPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
386         LOG.debug("RemoveHoldPO started.");
387         String operation = "Remove Payment Hold ";
388         ActionForward forward = askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.REMOVE_HOLD_QUESTION, PODocumentsStrings.REMOVE_HOLD_CONFIRM, PurchaseOrderDocTypes.PURCHASE_ORDER_REMOVE_HOLD_DOCUMENT, PODocumentsStrings.REMOVE_HOLD_NOTE_PREFIX, PurapKeyConstants.PURCHASE_ORDER_MESSAGE_REMOVE_HOLD, operation);
389 
390         return forward;
391     }
392 
393     /**
394      * Is invoked when the user pressed on the Open Order button on a Purchase Order page that has status "Close" to
395      * reopen the PO. It will display the question page to the user to ask whether the user really wants to reopen the PO and ask
396      * the user to enter a reason in the text area. If the user has entered the reason, it will invoke the a service method to do
397      * the processing for reopening a PO, then display a Single Confirmation page to inform the user that the
398      * <code>PurchaseOrderReopenDocument</code> has been routed.
399      *
400      * @param mapping  An ActionMapping
401      * @param form     An ActionForm
402      * @param request  The HttpServletRequest
403      * @param response The HttpServletResponse
404      * @return An ActionForward
405      * @throws Exception
406      * @see org.kuali.ole.module.purap.document.PurchaseOrderReopenDocument
407      */
408     public ActionForward reopenPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
409         LOG.debug("Reopen PO started");
410         String operation = "Reopen ";
411 
412         return askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.REOPEN_PO_QUESTION, PODocumentsStrings.CONFIRM_REOPEN_QUESTION, PurchaseOrderDocTypes.PURCHASE_ORDER_REOPEN_DOCUMENT, PODocumentsStrings.REOPEN_NOTE_PREFIX, PurapKeyConstants.PURCHASE_ORDER_MESSAGE_REOPEN_DOCUMENT, operation);
413     }
414 
415     /**
416      * Is invoked when the user pressed on the Amend button on a Purchase Order page to amend the PO. It will display
417      * the question page to the user to ask whether the user really wants to amend the PO and ask the user to enter a reason in the
418      * text area. If the user has entered the reason, it will invoke a service method to do the processing for amending the PO, then
419      * display a Single Confirmation page to inform the user that the <code>PurchaseOrderAmendmentDocument</code> has been routed.
420      *
421      * @param mapping  An ActionMapping
422      * @param form     An ActionForm
423      * @param request  The HttpServletRequest
424      * @param response The HttpServletResponse
425      * @return An ActionForward
426      * @throws Exception
427      * @see org.kuali.ole.module.purap.document.PurchaseOrderAmendmentDocument
428      */
429     public ActionForward amendPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
430         LOG.debug("Amend PO started");
431         String operation = "Amend ";
432 
433         return askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.AMENDMENT_PO_QUESTION, PODocumentsStrings.CONFIRM_AMENDMENT_QUESTION, PurchaseOrderDocTypes.PURCHASE_ORDER_AMENDMENT_DOCUMENT, PODocumentsStrings.AMENDMENT_NOTE_PREFIX, null, operation);
434     }
435 
436     /**
437      * Is invoked when the user pressed on the Void button on a Purchase Order page to void the PO. It will display the
438      * question page to the user to ask whether the user really wants to void the PO and ask the user to enter a reason in the text
439      * area. If the user has entered the reason, it will invoke a service method to do the processing for voiding the PO, then
440      * display a Single Confirmation page to inform the user that the <code>PurchaseOrderVoidDocument</code> has been routed.
441      *
442      * @param mapping  An ActionMapping
443      * @param form     An ActionForm
444      * @param request  The HttpServletRequest
445      * @param response The HttpServletResponse
446      * @return An ActionForward
447      * @throws Exception
448      * @see org.kuali.ole.module.purap.document.PurchaseOrderVoidDocument
449      */
450     public ActionForward voidPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
451         LOG.debug("Void PO started");
452         String operation = "Void ";
453 
454         return askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.VOID_QUESTION, PODocumentsStrings.VOID_CONFIRM, PurchaseOrderDocTypes.PURCHASE_ORDER_VOID_DOCUMENT, PODocumentsStrings.VOID_NOTE_PREFIX, PurapKeyConstants.PURCHASE_ORDER_MESSAGE_VOID_DOCUMENT, operation);
455     }
456 
457     /**
458      * Invoked to initiate the splitting of a Purchase Order.  Displays a question page to ask for a reason and confirmation
459      * of the user's desire to split the Purchase Order, and, if confirmed, a page on which the Split PO tab only is showing,
460      * and the items to move to the new PO are chosen. If that is done, and the user continues, a new Split Purchase Order document
461      * will be created, with the chosen items.  That same set of items will be deleted from the original Purchase Order.
462      *
463      * @param mapping  An ActionMapping
464      * @param form     An ActionForm
465      * @param request  The HttpServeletRequest
466      * @param response The HttpServeletResponse
467      * @return An ActionForward
468      * @throws Exception
469      * @see org.kuali.ole.module.purap.document.PurchaseOrderSplitDocument
470      */
471     public ActionForward splitPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
472         LOG.debug("Split PO started");
473         String operation = "Split ";
474 
475         return askQuestionsAndPerformDocumentAction(mapping, form, request, response, PODocumentsStrings.SPLIT_QUESTION, PODocumentsStrings.SPLIT_CONFIRM, PurchaseOrderDocTypes.PURCHASE_ORDER_SPLIT_DOCUMENT, PODocumentsStrings.SPLIT_NOTE_PREFIX_OLD_DOC, PurapKeyConstants.PURCHASE_ORDER_MESSAGE_SPLIT_DOCUMENT, operation);
476     }
477 
478     /**
479      * Invoked when only the Split Purchase Order tab is showing to continue the process of splitting the PO, once items are chosen
480      * to be moved to the new PO.
481      *
482      * @param mapping  An ActionMapping
483      * @param form     An ActionForm
484      * @param request  The HttpServeletRequest
485      * @param response The HttpServeletResponse
486      * @return An ActionForward
487      * @throws Exception
488      */
489     public ActionForward continuePurchaseOrderSplit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
490         LOG.debug("Continue Purchase Order Split started");
491 
492         PurchaseOrderForm purchaseOrderForm = (PurchaseOrderForm) form;
493         // This PO does not contain all data, but enough for our purposes; it has been reloaded with only the Split PO tab showing.
494         PurchaseOrderDocument poToSplit = (PurchaseOrderDocument) purchaseOrderForm.getDocument();
495         boolean copyNotes = poToSplit.isCopyingNotesWhenSplitting();
496 
497         // Check business rules before splitting.
498 
499         boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedSplitPurchaseOrderEvent(poToSplit));
500         if (!rulePassed) {
501             poToSplit.setPendingSplit(true);
502         } else {
503             HashMap<String, List<PurchaseOrderItem>> categorizedItems = SpringContext.getBean(PurchaseOrderService.class).categorizeItemsForSplit(poToSplit.getItems());
504             List<PurchaseOrderItem> movingPOItems = categorizedItems.get(PODocumentsStrings.ITEMS_MOVING_TO_SPLIT);
505             List<PurchaseOrderItem> remainingPOItems = categorizedItems.get(PODocumentsStrings.ITEMS_REMAINING);
506 
507             // Fetch the whole PO from the database, and reset and renumber the items on it.
508             poToSplit = SpringContext.getBean(PurchaseOrderService.class).getCurrentPurchaseOrder(poToSplit.getPurapDocumentIdentifier());
509             poToSplit.setItems(remainingPOItems);
510             poToSplit.renumberItems(0);
511 
512             // Add the note that would normally have gone in after the confirmation page.
513             String noteText = purchaseOrderForm.getSplitNoteText();
514             // Following code block commented as Notes is not saved for the document from here.
515             /*try {
516                 Note splitNote = SpringContext.getBean(DocumentService.class).createNoteFromDocument(poToSplit, noteText);
517                 poToSplit.addNote(splitNote);
518                 SpringContext.getBean(NoteService.class).save(splitNote);
519             } catch ( Exception e ) {
520                 throw new RuntimeException(e);
521             }*/
522             SpringContext.getBean(PurapService.class).saveDocumentNoValidation(poToSplit);
523 
524             PurchaseOrderSplitDocument splitPO = SpringContext.getBean(PurchaseOrderService.class).createAndSavePurchaseOrderSplitDocument(movingPOItems, poToSplit, copyNotes, noteText);
525 
526             Long nextLinkIdentifier = SpringContext.getBean(SequenceAccessorService.class).getNextAvailableSequenceNumber("AP_PUR_DOC_LNK_ID");
527             splitPO.setAccountsPayablePurchasingDocumentLinkIdentifier(nextLinkIdentifier.intValue());
528 
529             purchaseOrderForm.setDocument(splitPO);
530             purchaseOrderForm.setDocId(splitPO.getDocumentNumber());
531             purchaseOrderForm.setDocTypeName(splitPO.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
532             try {
533                 loadDocument(purchaseOrderForm);
534             } catch (WorkflowException we) {
535                 throw new RuntimeException(we);
536             }
537         }
538 
539         return mapping.findForward(OLEConstants.MAPPING_BASIC);
540     }
541 
542     /**
543      * Invoked from the page on which the Split PO tab is showing to cancel the splitting of the PO and return it to its original state.
544      *
545      * @param mapping  An ActionMapping
546      * @param form     An ActionForm
547      * @param request  The HttpServeletRequest
548      * @param response The HttpServeletResponse
549      * @return An ActionForward
550      * @throws Exception
551      */
552     public ActionForward cancelPurchaseOrderSplit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
553         LOG.debug("Cancel Purchase Order Split started");
554 
555         PurchaseOrderForm purchaseOrderForm = (PurchaseOrderForm) form;
556         PurchaseOrderDocument po = (PurchaseOrderDocument) purchaseOrderForm.getDocument();
557 
558         po = SpringContext.getBean(PurchaseOrderService.class).getPurchaseOrderByDocumentNumber(po.getDocumentNumber());
559 
560         po.setPendingSplit(false);
561         po.setCopyingNotesWhenSplitting(false);
562         purchaseOrderForm.setDocument(po);
563         reload(mapping, purchaseOrderForm, request, response);
564 
565         return mapping.findForward(OLEConstants.MAPPING_BASIC);
566     }
567 
568     /**
569      * Invoked when an authorized user presses "Sensitive Data" button on the purchase order page.
570      *
571      * @param mapping  An ActionMapping
572      * @param form     An ActionForm
573      * @param request  The HttpServeletRequest
574      * @param response The HttpServeletResponse
575      * @return An ActionForward
576      * @throws Exception
577      */
578     public ActionForward assignSensitiveData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
579         LOG.debug("Assign Sensitive Data started");
580 
581         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
582         PurchaseOrderDocument po = (PurchaseOrderDocument) poForm.getDocument();
583         Integer poId = po.getPurapDocumentIdentifier();
584         SensitiveDataService sdService = SpringContext.getBean(SensitiveDataService.class);
585 
586         // set the assignment flag and reset input fields
587         po.setAssigningSensitiveData(true);
588         poForm.setSensitiveDataAssignmentReason("");
589         poForm.setNewSensitiveDataLine(new SensitiveData());
590 
591         // load previous assignment info
592         SensitiveDataAssignment sda = sdService.getLastSensitiveDataAssignment(poId);
593         poForm.setLastSensitiveDataAssignment(sda);
594 
595         // even though at this point, the sensitive data entries should have been loaded into the form already,
596         // we still load them again in case that someone else has changed that during the time period
597         List<SensitiveData> posds = sdService.getSensitiveDatasAssignedByPoId(poId);
598         poForm.setSensitiveDatasAssigned(posds);
599 
600         return mapping.findForward(OLEConstants.MAPPING_BASIC);
601     }
602 
603     /**
604      * Invoked when an authorized user presses "Submit" button on the "Assign Sensitive Data" page.
605      *
606      * @param mapping  An ActionMapping
607      * @param form     An ActionForm
608      * @param request  The HttpServeletRequest
609      * @param response The HttpServeletResponse
610      * @return An ActionForward
611      * @throws Exception
612      */
613     public ActionForward submitSensitiveData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
614         LOG.debug("Submit Sensitive Data started");
615 
616         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
617         PurchaseOrderDocument po = (PurchaseOrderDocument) poForm.getDocument();
618         Integer poId = po.getPurapDocumentIdentifier();
619         List<SensitiveData> sds = poForm.getSensitiveDatasAssigned();
620         String sdaReason = poForm.getSensitiveDataAssignmentReason();
621         SensitiveDataService sdService = SpringContext.getBean(SensitiveDataService.class);
622 
623         // check business rules
624         boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedAssignSensitiveDataEvent("", po, sdaReason, sds));
625         if (!rulePassed) {
626             return mapping.findForward(OLEConstants.MAPPING_BASIC);
627         }
628 
629         // update table SensitiveDataAssignment
630         SensitiveDataAssignment sda = new SensitiveDataAssignment(poId, poForm.getSensitiveDataAssignmentReason(), GlobalVariables.getUserSession().getPerson().getPrincipalName(), poForm.getSensitiveDatasAssigned());
631         SpringContext.getBean(BusinessObjectService.class).save(sda);
632 
633         // update table PurchaseOrderSensitiveData
634         sdService.deletePurchaseOrderSensitiveDatas(poId);
635         List<PurchaseOrderSensitiveData> posds = new ArrayList<PurchaseOrderSensitiveData>();
636         for (SensitiveData sd : sds) {
637             posds.add(new PurchaseOrderSensitiveData(poId, po.getRequisitionIdentifier(), sd.getSensitiveDataCode()));
638         }
639         SpringContext.getBean(BusinessObjectService.class).save(posds);
640 
641         // need this to update workflow doc for searching restrictions on sensitive data
642         SpringContext.getBean(PurapService.class).saveRoutingDataForRelatedDocuments(po.getAccountsPayablePurchasingDocumentLinkIdentifier());
643 
644         // reset the sensitive data related fields in the po form
645         po.setAssigningSensitiveData(false);
646 
647         return mapping.findForward(OLEConstants.MAPPING_BASIC);
648     }
649 
650     /**
651      * Invoked when an authorized user presses "Cancel" button on the "Assign Sensitive Data" page.
652      *
653      * @param mapping  An ActionMapping
654      * @param form     An ActionForm
655      * @param request  The HttpServeletRequest
656      * @param response The HttpServeletResponse
657      * @return An ActionForward
658      * @throws Exception
659      */
660     public ActionForward cancelSensitiveData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
661         LOG.debug("Cancel Sensitive Data started");
662 
663         // reset the sensitive data flag in the po form, reload sensitive data from database to undo the canceled changes
664         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
665         PurchaseOrderDocument po = (PurchaseOrderDocument) poForm.getDocument();
666         po.setAssigningSensitiveData(false);
667         List<SensitiveData> sds = SpringContext.getBean(SensitiveDataService.class).getSensitiveDatasAssignedByPoId(po.getPurapDocumentIdentifier());
668         poForm.setSensitiveDatasAssigned(sds);
669 
670         return mapping.findForward(OLEConstants.MAPPING_BASIC);
671     }
672 
673     /**
674      * Invoked when an authorized user presses "Add" button on the "Assign Sensitive Data" page.
675      *
676      * @param mapping  An ActionMapping
677      * @param form     An ActionForm
678      * @param request  The HttpServeletRequest
679      * @param response The HttpServeletResponse
680      * @return An ActionForward
681      * @throws Exception
682      */
683     public ActionForward addSensitiveData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
684         LOG.debug("Add Sensitive Data started");
685 
686         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
687         SensitiveDataService sdService = SpringContext.getBean(SensitiveDataService.class);
688 
689         // retrieve new sensitive data by code, add the new line
690         SensitiveData newsd = poForm.getNewSensitiveDataLine();
691         newsd = sdService.getSensitiveDataByCode(newsd.getSensitiveDataCode());
692         List<SensitiveData> sds = poForm.getSensitiveDatasAssigned();
693         sds.add(newsd);
694 
695         // reset new line
696         poForm.setNewSensitiveDataLine(new SensitiveData());
697 
698         return mapping.findForward(OLEConstants.MAPPING_BASIC);
699     }
700 
701     /**
702      * Invoked when an authorized user presses "Delete" button on the "Assign Sensitive Data" page.
703      *
704      * @param mapping  An ActionMapping
705      * @param form     An ActionForm
706      * @param request  The HttpServeletRequest
707      * @param response The HttpServeletResponse
708      * @return An ActionForward
709      * @throws Exception
710      */
711     public ActionForward deleteSensitiveData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
712         LOG.debug("Delete Sensitive Data started");
713 
714         // remove the selected sensitive data line
715         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
716         List<SensitiveData> sds = poForm.getSensitiveDatasAssigned();
717         sds.remove(getSelectedLine(request));
718 
719         return mapping.findForward(OLEConstants.MAPPING_BASIC);
720     }
721 
722     /**
723      * This is a utility method used to prepare to and to return to a previous page, making sure that the buttons will be restored
724      * in the process.
725      *
726      * @param kualiDocumentFormBase The Form, considered as a KualiDocumentFormBase, as it typically is here.
727      * @return An actionForward mapping back to the original page.
728      */
729     protected ActionForward returnToPreviousPage(ActionMapping mapping, KualiDocumentFormBase kualiDocumentFormBase) {
730 
731         return mapping.findForward(OLEConstants.MAPPING_BASIC);
732     }
733 
734     /**
735      * Is executed when the user clicks on the "print" button on a Purchase Order Print Document page. On a non
736      * javascript enabled browser, it will display a page with 2 buttons. One is to display the PDF, the other is to view the PO
737      * tabbed page where the PO document statuses, buttons, etc have already been updated (the updates of those occurred while the
738      * <code>performPurchaseOrderFirstTransmitViaPrinting</code> method is invoked. On a javascript enabled browser, it will
739      * display both the PO tabbed page containing the updated PO document info and the pdf on the next window/tab of the browser.
740      *
741      * @param mapping  An ActionMapping
742      * @param form     An ActionForm
743      * @param request  The HttpServletRequest
744      * @param response The HttpServletResponse
745      * @return An ActionForward
746      * @throws Exception
747      */
748     public ActionForward firstTransmitPrintPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
749         String poDocId = ((PurchaseOrderForm) form).getDocId();
750         ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
751         try {
752             SpringContext.getBean(PurchaseOrderService.class).performPurchaseOrderFirstTransmitViaPrinting(poDocId, baosPDF);
753         } finally {
754             if (baosPDF != null) {
755                 baosPDF.reset();
756             }
757         }
758         String basePath = getApplicationBaseUrl();
759         String docId = ((PurchaseOrderForm) form).getDocId();
760         String methodToCallPrintPurchaseOrderPDF = "printPurchaseOrderPDFOnly";
761         String methodToCallDocHandler = "docHandler";
762         String printPOPDFUrl = getUrlForPrintPO(basePath, docId, methodToCallPrintPurchaseOrderPDF);
763         String displayPOTabbedPageUrl = getUrlForPrintPO(basePath, docId, methodToCallDocHandler);
764         request.setAttribute("printPOPDFUrl", printPOPDFUrl);
765         request.setAttribute("displayPOTabbedPageUrl", displayPOTabbedPageUrl);
766         String label = SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
767         request.setAttribute("purchaseOrderLabel", label);
768 
769         return mapping.findForward("printPurchaseOrderPDF");
770     }
771 
772     /**
773      * Creates a URL to be used in printing the purchase order.
774      *
775      * @param basePath     String: The base path of the current URL
776      * @param docId        String: The document ID of the document to be printed
777      * @param methodToCall String: The name of the method that will be invoked to do this particular print
778      * @return The URL
779      */
780     protected String getUrlForPrintPO(String basePath, String docId, String methodToCall) {
781         StringBuffer result = new StringBuffer(basePath);
782         result.append("/purapPurchaseOrder.do?methodToCall=");
783         result.append(methodToCall);
784         result.append("&docId=");
785         result.append(docId);
786         result.append("&command=displayDocSearchView");
787 
788         return result.toString();
789     }
790 
791     /**
792      * Prints the PDF only, as opposed to <code>firstTransmitPrintPo</code>, which calls this method (indirectly) to print the
793      * PDF, and calls the doc handler to display the PO tabbed page.
794      *
795      * @param mapping  An ActionMapping
796      * @param form     An ActionForm
797      * @param request  The HttpServletRequest
798      * @param response The HttpServletResponse
799      * @return An ActionForward
800      * @throws Exception
801      */
802     public ActionForward printPurchaseOrderPDFOnly(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
803         String poDocId = request.getParameter("docId");
804         ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
805         try {
806             // will throw validation exception if errors occur
807             SpringContext.getBean(PurchaseOrderService.class).performPrintPurchaseOrderPDFOnly(poDocId, baosPDF);
808 
809             response.setHeader("Cache-Control", "max-age=30");
810             response.setContentType("application/pdf");
811             StringBuffer sbContentDispValue = new StringBuffer();
812             String useJavascript = request.getParameter("useJavascript");
813             if (useJavascript == null || useJavascript.equalsIgnoreCase("false")) {
814                 sbContentDispValue.append("attachment");
815             } else {
816                 sbContentDispValue.append("inline");
817             }
818             StringBuffer sbFilename = new StringBuffer();
819             sbFilename.append("PURAP_PO_");
820             sbFilename.append(poDocId);
821             sbFilename.append("_");
822             sbFilename.append(System.currentTimeMillis());
823             sbFilename.append(".pdf");
824             sbContentDispValue.append("; filename=");
825             sbContentDispValue.append(sbFilename);
826 
827             response.setHeader("Content-disposition", sbContentDispValue.toString());
828 
829             response.setContentLength(baosPDF.size());
830 
831             ServletOutputStream sos;
832 
833             sos = response.getOutputStream();
834 
835             baosPDF.writeTo(sos);
836 
837             sos.flush();
838 
839         } finally {
840             if (baosPDF != null) {
841                 baosPDF.reset();
842             }
843         }
844 
845         return null;
846     }
847 
848     /**
849      * Print a particular selected PO Quote as a PDF.
850      *
851      * @param mapping  An ActionMapping
852      * @param form     An ActionForm -- The PO Quote must be selected here.
853      * @param request  The HttpServletRequest
854      * @param response The HttpServletResponse
855      * @return An ActionForward
856      * @throws Exception
857      */
858     public ActionForward printPoQuote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
859         // String poDocId = request.getParameter("docId");
860         // PurchaseOrderDocument po = (PurchaseOrderDocument)
861         // SpringContext.getBean(DocumentService.class).getByDocumentHeaderId(poDocId);
862         // Integer poSelectedVendorId = new Integer(request.getParameter("quoteVendorId"));
863         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
864         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
865         PurchaseOrderVendorQuote poVendorQuote = po.getPurchaseOrderVendorQuotes().get(getSelectedLine(request));
866         ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
867         poVendorQuote.setTransmitPrintDisplayed(false);
868         try {
869             StringBuffer sbFilename = new StringBuffer();
870             sbFilename.append("PURAP_PO_QUOTE_");
871             sbFilename.append(po.getPurapDocumentIdentifier());
872             sbFilename.append("_");
873             sbFilename.append(System.currentTimeMillis());
874             sbFilename.append(".pdf");
875 
876             boolean success = SpringContext.getBean(PurchaseOrderService.class).printPurchaseOrderQuotePDF(po, poVendorQuote, baosPDF);
877 
878             if (!success) {
879                 poVendorQuote.setTransmitPrintDisplayed(true);
880                 poVendorQuote.setPdfDisplayedToUserOnce(false);
881 
882                 if (baosPDF != null) {
883                     baosPDF.reset();
884                 }
885                 return mapping.findForward(OLEConstants.MAPPING_BASIC);
886             }
887             response.setHeader("Cache-Control", "max-age=30");
888             response.setContentType("application/pdf");
889             StringBuffer sbContentDispValue = new StringBuffer();
890             // sbContentDispValue.append("inline");
891             sbContentDispValue.append("attachment");
892             sbContentDispValue.append("; filename=");
893             sbContentDispValue.append(sbFilename);
894 
895             response.setHeader("Content-disposition", sbContentDispValue.toString());
896 
897             response.setContentLength(baosPDF.size());
898 
899             ServletOutputStream sos;
900 
901             sos = response.getOutputStream();
902 
903             baosPDF.writeTo(sos);
904 
905             sos.flush();
906 
907         } finally {
908             if (baosPDF != null) {
909                 baosPDF.reset();
910             }
911         }
912 
913         return null;
914     }
915 
916     public ActionForward printPoQuoteList(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
917         String poDocId = ((PurchaseOrderForm) form).getDocId();
918         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
919         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
920         SpringContext.getBean(PurapService.class).saveDocumentNoValidation(po);
921         String basePath = getApplicationBaseUrl();
922         String methodToCallPrintPurchaseOrderPDF = "printPoQuoteListOnly";
923         String methodToCallDocHandler = "docHandler";
924         String printPOQuoteListPDFUrl = getUrlForPrintPO(basePath, poDocId, methodToCallPrintPurchaseOrderPDF);
925         String displayPOTabbedPageUrl = getUrlForPrintPO(basePath, poDocId, methodToCallDocHandler);
926         request.setAttribute("printPOQuoteListPDFUrl", printPOQuoteListPDFUrl);
927         request.setAttribute("displayPOTabbedPageUrl", displayPOTabbedPageUrl);
928         String label = SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
929         request.setAttribute("purchaseOrderLabel", label);
930 
931         return mapping.findForward("printPOQuoteListPDF");
932     }
933 
934     /**
935      * Print the list of PO Quote requests.
936      *
937      * @param mapping  An ActionMapping
938      * @param form     An ActionForm
939      * @param request  The HttpServletRequest
940      * @param response The HttpServletResponse
941      * @return An ActionForward
942      * @throws Exception
943      */
944     public ActionForward printPoQuoteListOnly(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
945         String poDocId = request.getParameter("docId");
946         ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
947         try {
948             StringBuffer sbFilename = new StringBuffer();
949             sbFilename.append("PURAP_PO_QUOTE_LIST_");
950             sbFilename.append(poDocId);
951             sbFilename.append("_");
952             sbFilename.append(System.currentTimeMillis());
953             sbFilename.append(".pdf");
954 
955             boolean success = SpringContext.getBean(PurchaseOrderService.class).printPurchaseOrderQuoteRequestsListPDF(poDocId, baosPDF);
956 
957             if (!success) {
958                 if (baosPDF != null) {
959                     baosPDF.reset();
960                 }
961                 return mapping.findForward(OLEConstants.MAPPING_PORTAL);
962             }
963             response.setHeader("Cache-Control", "max-age=30");
964             response.setContentType("application/pdf");
965             StringBuffer sbContentDispValue = new StringBuffer();
966             String useJavascript = request.getParameter("useJavascript");
967             if (useJavascript == null || useJavascript.equalsIgnoreCase("false")) {
968                 sbContentDispValue.append("attachment");
969             } else {
970                 sbContentDispValue.append("inline");
971             }
972             sbContentDispValue.append("; filename=");
973             sbContentDispValue.append(sbFilename);
974 
975             response.setHeader("Content-disposition", sbContentDispValue.toString());
976 
977             response.setContentLength(baosPDF.size());
978 
979             ServletOutputStream sos;
980 
981             sos = response.getOutputStream();
982 
983             baosPDF.writeTo(sos);
984 
985             sos.flush();
986 
987         } finally {
988             if (baosPDF != null) {
989                 baosPDF.reset();
990             }
991         }
992 
993         return null;
994     }
995 
996     /**
997      * Initiates transmission of a PO Quote request.
998      *
999      * @param mapping  An ActionMapping
1000      * @param form     An ActionForm
1001      * @param request  The HttpServletRequest
1002      * @param response The HttpServletResponse
1003      * @return An ActionForward
1004      * @throws Exception
1005      */
1006     public ActionForward transmitPurchaseOrderQuote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1007         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1008         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
1009         PurchaseOrderVendorQuote vendorQuote = po.getPurchaseOrderVendorQuotes().get(getSelectedLine(request));
1010         if (PurapConstants.QuoteTransmitTypes.PRINT.equals(vendorQuote.getPurchaseOrderQuoteTransmitTypeCode())) {
1011             vendorQuote.setPurchaseOrderQuoteTransmitTimestamp(SpringContext.getBean(DateTimeService.class).getCurrentTimestamp());
1012             vendorQuote.setTransmitPrintDisplayed(true);
1013             vendorQuote.setPdfDisplayedToUserOnce(false);
1014             SpringContext.getBean(PurapService.class).saveDocumentNoValidation(po);
1015         } else if (PurapConstants.QuoteTransmitTypes.FAX.equals(vendorQuote.getPurchaseOrderQuoteTransmitTypeCode())) {
1016             // call fax service
1017             GlobalVariables.getMessageMap().clearErrorMessages();
1018             FaxService faxService = SpringContext.getBean(FaxService.class);
1019             faxService.faxPurchaseOrderPdf(po, false);
1020             if (GlobalVariables.getMessageMap().getNumberOfPropertiesWithErrors() == 0) {
1021                 vendorQuote.setPurchaseOrderQuoteTransmitTimestamp(SpringContext.getBean(DateTimeService.class).getCurrentTimestamp());
1022                 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(po);
1023             }
1024         } else {
1025             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_TRANSMIT_TYPE_NOT_SELECTED);
1026         }
1027 
1028         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1029     }
1030 
1031     /**
1032      * Is invoked when the user clicks on the Select All button on a Purchase Order Retransmit document. It will select
1033      * the checkboxes of all the items to be included in the retransmission of the PO.
1034      *
1035      * @param mapping  An ActionMapping
1036      * @param form     An ActionForm
1037      * @param request  The HttpServletRequest
1038      * @param response The HttpServletResponse
1039      * @return An ActionForward
1040      * @throws Exception
1041      */
1042     public ActionForward selectAllForRetransmit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1043         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1044         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
1045         List<PurchaseOrderItem> items = po.getItems();
1046         for (PurchaseOrderItem item : items) {
1047             item.setItemSelectedForRetransmitIndicator(true);
1048         }
1049 
1050         return returnToPreviousPage(mapping, kualiDocumentFormBase);
1051     }
1052 
1053     /**
1054      * Is invoked when the user clicks on the Deselect All button on a Purchase Order Retransmit document. It will
1055      * uncheck the checkboxes of all the items to be excluded from the retransmission of the PO.
1056      *
1057      * @param mapping  An ActionMapping
1058      * @param form     An ActionForm
1059      * @param request  The HttpServletRequest
1060      * @param response The HttpServletResponse
1061      * @return An ActionForward
1062      * @throws Exception
1063      */
1064     public ActionForward deselectAllForRetransmit(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1065         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1066         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
1067         List<PurchaseOrderItem> items = po.getItems();
1068         for (PurchaseOrderItem item : items) {
1069             item.setItemSelectedForRetransmitIndicator(false);
1070         }
1071 
1072         return returnToPreviousPage(mapping, kualiDocumentFormBase);
1073     }
1074 
1075     /**
1076      * Is invoked when the user clicks on the Retransmit button on both the PO tabbed page and on the Purchase Order
1077      * Retransmit Document page, which is essentially a PO tabbed page with the other irrelevant tabs being hidden. If it was
1078      * invoked from the PO tabbed page, if the PO's pending indicator is false, this method will invoke a method in the
1079      * PurchaseOrderService to update the flags, create the PurchaseOrderRetransmitDocument and route it. If the routing was
1080      * successful, we'll display the Purchase Order Retransmit Document page to the user, containing the newly created and routed
1081      * PurchaseOrderRetransmitDocument and a retransmit button as well as a list of items that the user can select to be
1082      * retransmitted. If it was invoked from the Purchase Order Retransmit Document page, we'll invoke the
1083      * retransmitPurchaseOrderPDF method to create a PDF document based on the PO information and the items that were selected by
1084      * the user on the Purchase Order Retransmit Document page to be retransmitted, then display the PDF to the browser.
1085      *
1086      * @param mapping  An ActionMapping
1087      * @param form     An ActionForm
1088      * @param request  The HttpServletRequest
1089      * @param response The HttpServletResponse
1090      * @return An ActionForward
1091      * @throws Exception
1092      */
1093     public ActionForward retransmitPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1094         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1095         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
1096 
1097         boolean success;
1098         if (po.isPendingActionIndicator()) {
1099             success = false;
1100             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.PURCHASE_ORDER_IDENTIFIER, PurapKeyConstants.ERROR_PURCHASE_ORDER_IS_PENDING);
1101         } else {
1102             po = SpringContext.getBean(PurchaseOrderService.class).createAndRoutePotentialChangeDocument(kualiDocumentFormBase.getDocument().getDocumentNumber(), PurchaseOrderDocTypes.PURCHASE_ORDER_RETRANSMIT_DOCUMENT, kualiDocumentFormBase.getAnnotation(), combineAdHocRecipients(kualiDocumentFormBase), PurchaseOrderStatuses.APPDOC_PENDING_RETRANSMIT);
1103             ((PurchaseOrderRetransmitDocument) po).setShouldDisplayRetransmitTab(true);
1104         }
1105 
1106         kualiDocumentFormBase.setDocument(po);
1107         // we only need to set the editing mode to displayRetransmitTab if it's not yet
1108         // in the editingMode.
1109         if (!kualiDocumentFormBase.getEditingMode().containsKey(PurapAuthorizationConstants.PurchaseOrderEditMode.DISPLAY_RETRANSMIT_TAB)) {
1110             DocumentAuthorizer documentAuthorizer = SpringContext.getBean(DocumentHelperService.class).getDocumentAuthorizer(po);
1111             // TODO this method is gone, fix for kim
1112 //            kualiDocumentFormBase.populateAuthorizationFields(documentAuthorizer);
1113         }
1114 
1115         return returnToPreviousPage(mapping, kualiDocumentFormBase);
1116     }
1117 
1118 
1119     /**
1120      * Is invoked when the user clicks on the Retransmit button on both the PO tabbed page and on the Purchase Order
1121      * Retransmit Document page, which is essentially a PO tabbed page with the other irrelevant tabs being hidden. If it was
1122      * invoked from the PO tabbed page, if the PO's pending indicator is false, this method will invoke a method in the
1123      * PurchaseOrderService to update the flags, create the PurchaseOrderRetransmitDocument and route it. If the routing was
1124      * successful, we'll display the Purchase Order Retransmit Document page to the user, containing the newly created and routed
1125      * PurchaseOrderRetransmitDocument and a retransmit button as well as a list of items that the user can select to be
1126      * retransmitted. If it was invoked from the Purchase Order Retransmit Document page, we'll invoke the
1127      * retransmitPurchaseOrderPDF method to create a PDF document based on the PO information and the items that were selected by
1128      * the user on the Purchase Order Retransmit Document page to be retransmitted, then display the PDF to the browser.
1129      *
1130      * @param mapping  An ActionMapping
1131      * @param form     An ActionForm
1132      * @param request  The HttpServletRequest
1133      * @param response The HttpServletResponse
1134      * @return An ActionForward
1135      * @throws Exception
1136      */
1137     public ActionForward printingPreviewPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1138         String poDocId = ((PurchaseOrderForm) form).getDocId();
1139         ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
1140         try {
1141             SpringContext.getBean(PurchaseOrderService.class).performPurchaseOrderPreviewPrinting(poDocId, baosPDF);
1142         } finally {
1143             if (baosPDF != null) {
1144                 baosPDF.reset();
1145             }
1146         }
1147         String basePath = getApplicationBaseUrl();
1148         String docId = ((PurchaseOrderForm) form).getDocId();
1149         String methodToCallPrintPurchaseOrderPDF = "printPurchaseOrderPDFOnly";
1150         String methodToCallDocHandler = "docHandler";
1151         String printPOPDFUrl = getUrlForPrintPO(basePath, docId, methodToCallPrintPurchaseOrderPDF);
1152         String displayPOTabbedPageUrl = getUrlForPrintPO(basePath, docId, methodToCallDocHandler);
1153         request.setAttribute("printPOPDFUrl", printPOPDFUrl);
1154         request.setAttribute("displayPOTabbedPageUrl", displayPOTabbedPageUrl);
1155         String label = SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
1156         request.setAttribute("purchaseOrderLabel", label);
1157         GlobalVariables.getUserSession().addObject("isPreview", new Boolean(true));
1158 
1159         return mapping.findForward("printPurchaseOrderPDF");
1160     }
1161 
1162     /**
1163      * Forwards to the RetransmitForward.jsp page so that we could open 2 windows for retransmit,
1164      * one is to display the PO tabbed page and the other one display the pdf document.
1165      *
1166      * @param mapping
1167      * @param form
1168      * @param request
1169      * @param response
1170      * @return
1171      * @throws Exception
1172      */
1173     public ActionForward printingRetransmitPo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1174         String basePath = getApplicationBaseUrl();
1175         String docId = ((PurchaseOrderForm) form).getPurchaseOrderDocument().getDocumentNumber();
1176         String methodToCallPrintRetransmitPurchaseOrderPDF = "printingRetransmitPoOnly";
1177         String methodToCallDocHandler = "docHandler";
1178         String printPOPDFUrl = getUrlForPrintPO(basePath, docId, methodToCallPrintRetransmitPurchaseOrderPDF);
1179         String displayPOTabbedPageUrl = getUrlForPrintPO(basePath, docId, methodToCallDocHandler);
1180 
1181         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1182         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
1183 
1184         StringBuffer itemIndexesBuffer = createSelectedItemIndexes(po.getItems());
1185         if (itemIndexesBuffer.length() > 0) {
1186             itemIndexesBuffer.deleteCharAt(itemIndexesBuffer.lastIndexOf(","));
1187             request.setAttribute("selectedItemIndexes", itemIndexesBuffer.toString());
1188         }
1189 
1190         request.setAttribute("printPOPDFUrl", printPOPDFUrl);
1191         request.setAttribute("displayPOTabbedPageUrl", displayPOTabbedPageUrl);
1192         request.setAttribute("docId", docId);
1193         String label = SpringContext.getBean(DataDictionaryService.class).getDocumentLabelByTypeName(OLEConstants.FinancialDocumentTypeCodes.PURCHASE_ORDER);
1194         request.setAttribute("purchaseOrderLabel", label);
1195         return mapping.findForward("retransmitPurchaseOrderPDF");
1196     }
1197 
1198     /**
1199      * Helper method to create a StringBuffer of the indexes of items that the user
1200      * has selected for retransmit to be passed in as an attribute to the RetransmitForward
1201      * page so that we could add these items later on to the pdf page.
1202      *
1203      * @param items The List of items on the PurchaseOrderDocument.
1204      * @return
1205      */
1206     protected StringBuffer createSelectedItemIndexes(List<PurchaseOrderItem> items) {
1207         StringBuffer itemIndexesBuffer = new StringBuffer();
1208         int i = 0;
1209         for (PurchaseOrderItem item : items) {
1210             if (item.isItemSelectedForRetransmitIndicator()) {
1211                 itemIndexesBuffer.append(i);
1212                 itemIndexesBuffer.append(',');
1213             }
1214             i++;
1215         }
1216         return itemIndexesBuffer;
1217     }
1218 
1219     /**
1220      * Creates a PDF document based on the PO information and the items that were selected by the user on the Purchase Order
1221      * Retransmit Document page to be retransmitted, then display the PDF to the browser.
1222      *
1223      * @param mapping  An ActionMapping
1224      * @param form     An ActionForm
1225      * @param request  The HttpServletRequest
1226      * @param response The HttpServletResponse
1227      * @return An ActionForward
1228      * @throws Exception
1229      */
1230     public ActionForward printingRetransmitPoOnly(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1231 
1232         String selectedItemIndexes = request.getParameter("selectedItemIndexes");
1233         String documentNumber = request.getParameter("poDocumentNumberForRetransmit");
1234         PurchaseOrderDocument po = SpringContext.getBean(PurchaseOrderService.class).getPurchaseOrderByDocumentNumber(documentNumber);
1235         String retransmitHeader = request.getParameter("retransmitHeader");
1236 
1237         // setting the isItemSelectedForRetransmitIndicator items of the PO obtained from the database based on its value from
1238         // the po from the form
1239 
1240         setItemSelectedForRetransmitIndicatorFromPOInForm(selectedItemIndexes, po.getItems());
1241         po.setRetransmitHeader(retransmitHeader);
1242         ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
1243         try {
1244             StringBuffer sbFilename = new StringBuffer();
1245             sbFilename.append("PURAP_PO_");
1246             sbFilename.append(po.getPurapDocumentIdentifier());
1247             sbFilename.append("_");
1248             sbFilename.append(System.currentTimeMillis());
1249             sbFilename.append(".pdf");
1250 
1251             // below method will throw ValidationException if errors are found
1252             SpringContext.getBean(PurchaseOrderService.class).retransmitPurchaseOrderPDF(po, baosPDF);
1253 
1254             response.setHeader("Cache-Control", "max-age=30");
1255             response.setContentType("application/pdf");
1256             StringBuffer sbContentDispValue = new StringBuffer();
1257             sbContentDispValue.append("inline");
1258             sbContentDispValue.append("; filename=");
1259             sbContentDispValue.append(sbFilename);
1260 
1261             response.setHeader("Content-disposition", sbContentDispValue.toString());
1262 
1263             response.setContentLength(baosPDF.size());
1264 
1265             ServletOutputStream sos;
1266 
1267             sos = response.getOutputStream();
1268 
1269             baosPDF.writeTo(sos);
1270 
1271             sos.flush();
1272 
1273         } catch (ValidationException e) {
1274             LOG.warn("Caught ValidationException while trying to retransmit PO with doc id " + po.getDocumentNumber());
1275             return mapping.findForward(OLEConstants.MAPPING_ERROR);
1276         } finally {
1277             if (baosPDF != null) {
1278                 baosPDF.reset();
1279             }
1280         }
1281 
1282         return null;
1283     }
1284 
1285     /**
1286      * Sets the itemSelectedForRetransmitIndicator to true to the items that the
1287      * user has selected for retransmit.
1288      *
1289      * @param selectedItemIndexes The String containing the indexes of items selected to be retransmitted, separated by comma.
1290      * @param itemsFromDB         The List of items of the PurchaseOrderDocument obtained from the database.
1291      */
1292     protected void setItemSelectedForRetransmitIndicatorFromPOInForm(String selectedItemIndexes, List itemsFromDB) {
1293         int i = 0;
1294         StringTokenizer tok = new StringTokenizer(selectedItemIndexes, ",");
1295         while (tok.hasMoreTokens()) {
1296             i = Integer.parseInt(tok.nextToken());
1297             ((PurchaseOrderItem) (itemsFromDB.get(i))).setItemSelectedForRetransmitIndicator(true);
1298         }
1299     }
1300 
1301     /**
1302      * Checks on a few conditions that would cause a warning message to be displayed on top of the Purchase Order page.
1303      *
1304      * @param po the PurchaseOrderDocument whose status and indicators are to be checked in the conditions
1305      * @return boolean true if the Purchase Order doesn't have any warnings and false otherwise.
1306      */
1307     protected void checkForPOWarnings(PurchaseOrderDocument po, ActionMessages messages) {
1308         // "This is not the current version of this Purchase Order." (curr_ind = N and doc status is not enroute)
1309         if (!po.isPurchaseOrderCurrentIndicator() && !po.getDocumentHeader().getWorkflowDocument().isEnroute()) {
1310             KNSGlobalVariables.getMessageList().add(PurapKeyConstants.WARNING_PURCHASE_ORDER_NOT_CURRENT);
1311         }
1312         // "This document is a pending action. This is not the current version of this Purchase Order" (curr_ind = N and doc status
1313         // is enroute)
1314         if (!po.isPurchaseOrderCurrentIndicator() && po.getDocumentHeader().getWorkflowDocument().isEnroute()) {
1315             KNSGlobalVariables.getMessageList().add(PurapKeyConstants.WARNING_PURCHASE_ORDER_PENDING_ACTION_NOT_CURRENT);
1316         }
1317         // "There is a pending action on this Purchase Order." (pend_action = Y)
1318         if (po.isPendingActionIndicator()) {
1319             KNSGlobalVariables.getMessageList().add(PurapKeyConstants.WARNING_PURCHASE_ORDER_PENDING_ACTION);
1320         }
1321 
1322         if (!po.isPurchaseOrderCurrentIndicator()) {
1323             ActionMessage noteMessage = new ActionMessage(PurapKeyConstants.WARNING_PURCHASE_ORDER_ALL_NOTES);
1324             messages.add(PurapConstants.NOTE_TAB_WARNING, noteMessage);
1325         }
1326     }
1327 
1328     /**
1329      * Add a stipulation to the document.
1330      *
1331      * @param mapping  An ActionMapping
1332      * @param form     An ActionForm
1333      * @param request  The HttpServletRequest
1334      * @param response The HttpServletResponse
1335      * @return An ActionForward
1336      * @throws Exception
1337      */
1338     public ActionForward addStipulation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1339         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1340         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1341 
1342         if (StringUtils.isBlank(poForm.getNewPurchaseOrderVendorStipulationLine().getVendorStipulationDescription())) {
1343             GlobalVariables.getMessageMap().putError(OLEConstants.DOCUMENT_PROPERTY_NAME + "." + PurapPropertyConstants.VENDOR_STIPULATION, PurapKeyConstants.ERROR_STIPULATION_DESCRIPTION);
1344         } else {
1345             PurchaseOrderVendorStipulation newStipulation = poForm.getAndResetNewPurchaseOrderVendorStipulationLine();
1346             document.getPurchaseOrderVendorStipulations().add(newStipulation);
1347         }
1348 
1349         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1350     }
1351 
1352     /**
1353      * Delete a stipulation from the document.
1354      *
1355      * @param mapping  An ActionMapping
1356      * @param form     An ActionForm
1357      * @param request  The HttpServletRequest
1358      * @param response The HttpServletResponse
1359      * @return An ActionForward
1360      * @throws Exception
1361      */
1362     public ActionForward deleteStipulation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1363         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1364         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1365         document.getPurchaseOrderVendorStipulations().remove(getSelectedLine(request));
1366 
1367         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1368     }
1369 
1370     /**
1371      * Overrides the docHandler method in the superclass. In addition to doing the normal process in the superclass and returning
1372      * its action forward from the superclass, it also invokes the <code>checkForPOWarnings</code> method to check on a few
1373      * conditions that could have caused warning messages to be displayed on top of Purchase Order page.
1374      *
1375      * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#docHandler(org.apache.struts.action.ActionMapping,
1376      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
1377      */
1378     @Override
1379     public ActionForward docHandler(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1380         ActionForward forward = super.docHandler(mapping, form, request, response);
1381         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1382         PurchaseOrderDocument po = (PurchaseOrderDocument) poForm.getDocument();
1383 
1384         ActionMessages messages = new ActionMessages();
1385         checkForPOWarnings(po, messages);
1386         saveMessages(request, messages);
1387         return forward;
1388     }
1389 
1390     /**
1391      * Sets up the PO document for Quote processing.
1392      *
1393      * @param mapping  An ActionMapping
1394      * @param form     An ActionForm
1395      * @param request  The HttpServletRequest
1396      * @param response The HttpServletResponse
1397      * @return An ActionForward
1398      * @throws Exception
1399      */
1400     public ActionForward initiateQuote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1401         DateTimeService dateTimeService = SpringContext.getBean(DateTimeService.class);
1402         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1403         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1404         if (!PurchaseOrderStatuses.APPDOC_IN_PROCESS.equals(document.getApplicationDocumentStatus())) {
1405             // PO must be "in process" in order to initiate a quote
1406             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_NOT_IN_PROCESS);
1407             return mapping.findForward(OLEConstants.MAPPING_BASIC);
1408         }
1409         Calendar currentCalendar = dateTimeService.getCurrentCalendar();
1410         Date currentSqlDate = new java.sql.Date(currentCalendar.getTimeInMillis());
1411         document.setPurchaseOrderQuoteInitializationDate(currentSqlDate);
1412         document.updateAndSaveAppDocStatus(PurchaseOrderStatuses.APPDOC_QUOTE);
1413 
1414         document.setStatusChange(PurchaseOrderStatuses.APPDOC_QUOTE);
1415 
1416         //TODO this needs to be done better, and probably make it a parameter
1417         Calendar expCalendar = (Calendar) currentCalendar.clone();
1418         expCalendar.add(Calendar.DAY_OF_MONTH, 10);
1419         java.sql.Date expDate = new java.sql.Date(expCalendar.getTimeInMillis());
1420 
1421         document.setPurchaseOrderQuoteDueDate(expDate);
1422         document.getPurchaseOrderVendorQuotes().clear();
1423         SpringContext.getBean(PurapService.class).saveDocumentNoValidation(document);
1424 
1425         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1426     }
1427 
1428     /**
1429      * Add to the Quotes a line to contain a Vendor.
1430      *
1431      * @param mapping  An ActionMapping
1432      * @param form     An ActionForm
1433      * @param request  The HttpServletRequest
1434      * @param response The HttpServletResponse
1435      * @return An ActionForward
1436      * @throws Exception
1437      */
1438     public ActionForward addVendor(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1439         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1440         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1441         PurchaseOrderVendorQuote vendorQuote = poForm.getNewPurchaseOrderVendorQuote();
1442         String errorPrefix = PurapPropertyConstants.NEW_PURCHASE_ORDER_VENDOR_QUOTE_TEXT;
1443         boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedAddVendorToQuoteEvent(errorPrefix, document, vendorQuote));
1444         if (rulePassed) {
1445             poForm.getNewPurchaseOrderVendorQuote().setDocumentNumber(document.getDocumentNumber());
1446             document.getPurchaseOrderVendorQuotes().add(vendorQuote);
1447             poForm.setNewPurchaseOrderVendorQuote(new PurchaseOrderVendorQuote());
1448         }
1449         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1450     }
1451 
1452     /**
1453      * Deletes a Vendor from the list of those from which a Quote should be obtained.
1454      *
1455      * @param mapping  An ActionMapping
1456      * @param form     An ActionForm
1457      * @param request  The HttpServletRequest
1458      * @param response The HttpServletResponse
1459      * @return An ActionForward
1460      * @throws Exception
1461      */
1462     public ActionForward deleteVendor(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1463         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1464         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1465         document.getPurchaseOrderVendorQuotes().remove(getSelectedLine(request));
1466 
1467         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1468     }
1469 
1470     /**
1471      * Once an awarded Vendor number is present on the PO, verifies the fact, asks the user for confirmation to complete the quoting
1472      * process with the awarded Vendor, and sets the Vendor information on the purchase order, if confirmation is obtained.
1473      *
1474      * @param mapping  An ActionMapping
1475      * @param form     An ActionForm
1476      * @param request  The HttpServletRequest
1477      * @param response The HttpServletResponse
1478      * @return An ActionForward
1479      * @throws Exception
1480      */
1481     public ActionForward completeQuote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1482         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1483         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1484         PurchaseOrderVendorQuote awardedQuote = new PurchaseOrderVendorQuote();
1485 
1486         // verify that all vendors have a quote status
1487         // also run dictionary validations to validate against the DD.
1488         boolean dictionaryValid = true;
1489         for (PurchaseOrderVendorQuote poQuote : document.getPurchaseOrderVendorQuotes()) {
1490             if (poQuote.getPurchaseOrderQuoteStatusCode() == null) {
1491                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_STATUS_NOT_SELECTED);
1492                 return mapping.findForward(OLEConstants.MAPPING_BASIC);
1493             } else {
1494                 dictionaryValid &= SpringContext.getBean(DictionaryValidationService.class).isBusinessObjectValid(poQuote, PurapPropertyConstants.VENDOR_QUOTES);
1495             }
1496         }
1497 
1498         if (!dictionaryValid) {
1499             return mapping.findForward(OLEConstants.MAPPING_BASIC);
1500         }
1501 
1502         // verify quote status fields
1503         if (poForm.getAwardedVendorNumber() == null) {
1504             GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_NO_VENDOR_AWARDED);
1505 
1506             return mapping.findForward(OLEConstants.MAPPING_BASIC);
1507         } else {
1508             awardedQuote = document.getPurchaseOrderVendorQuote(poForm.getAwardedVendorNumber().intValue());
1509             if (awardedQuote.getPurchaseOrderQuoteStatusCode() == null) {
1510                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_NOT_TRANSMITTED);
1511 
1512                 return mapping.findForward(OLEConstants.MAPPING_BASIC);
1513             } else {
1514                 VendorDetail awardedVendor = SpringContext.getBean(VendorService.class).getVendorDetail(awardedQuote.getVendorHeaderGeneratedIdentifier(), awardedQuote.getVendorDetailAssignedIdentifier());
1515                 if (!awardedVendor.getVendorHeader().getVendorTypeCode().equals("PO")) {
1516                     GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_AWARD_NON_PO);
1517 
1518                     return mapping.findForward(OLEConstants.MAPPING_BASIC);
1519                 }
1520             }
1521         }
1522 
1523         // use question framework to make sure they REALLY want to complete the quote...
1524         // since the html table tags are not supported for now, the awarded vendor info is displayed without them.
1525 //        String message = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_CONFIRM_AWARD);
1526 //        String vendorRow = SpringContext.getBean(KualiConfigurationService.class).getPropertyString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_CONFIRM_AWARD_ROW);
1527 //
1528 //        String tempRows = "";
1529 //        for (PurchaseOrderVendorQuote poQuote : document.getPurchaseOrderVendorQuotes()) {
1530 //            String tempRow = vendorRow;
1531 //            tempRow = StringUtils.replace(tempRow, "{0}", poQuote.getVendorName());
1532 //            if (poQuote.getPurchaseOrderQuoteAwardTimestamp() == null) {
1533 //                if (awardedQuote.getVendorNumber().equals(poQuote.getVendorNumber())) {
1534 //                    tempRow = StringUtils.replace(tempRow, "{1}", SpringContext.getBean(DateTimeService.class).getCurrentSqlDate().toString());
1535 //                }
1536 //                else {
1537 //                    tempRow = StringUtils.replace(tempRow, "{1}", "");
1538 //                }
1539 //            }
1540 //            else {
1541 //                tempRow = StringUtils.replace(tempRow, "{1}", poQuote.getPurchaseOrderQuoteAwardTimestamp().toString());
1542 //            }
1543 //            if (poQuote.getPurchaseOrderQuoteStatusCode() != null) {
1544 //                poQuote.refreshReferenceObject(PurapPropertyConstants.PURCHASE_ORDER_QUOTE_STATUS);
1545 //                tempRow = StringUtils.replace(tempRow, "{2}", poQuote.getPurchaseOrderQuoteStatus().getStatusDescription());
1546 //            }
1547 //            else {
1548 //                tempRow = StringUtils.replace(tempRow, "{2}", "N/A");
1549 //            }
1550 //            if (poQuote.getPurchaseOrderQuoteRankNumber() != null) {
1551 //                tempRow = StringUtils.replace(tempRow, "{3}", poQuote.getPurchaseOrderQuoteRankNumber());
1552 //            }
1553 //            else {
1554 //                tempRow = StringUtils.replace(tempRow, "{3}", "N/A");
1555 //            }
1556 //            tempRows += tempRow;
1557 //        }
1558 //        message = StringUtils.replace(message, "{0}", tempRows);
1559         // without the html table tags
1560         StringBuffer awardedVendorInfo = new StringBuffer(SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_CONFIRM_AWARD));
1561         int awardNbr = 0;
1562         for (PurchaseOrderVendorQuote poQuote : document.getPurchaseOrderVendorQuotes()) {
1563 
1564             // vendor name
1565             awardedVendorInfo.append(++awardNbr + ". ").append("Vendor Name: ");
1566             awardedVendorInfo.append(poQuote.getVendorName()).append("[br]");
1567 
1568             // awarded date
1569             awardedVendorInfo.append("Awarded Date: ");
1570             if (poQuote.getPurchaseOrderQuoteAwardTimestamp() == null) {
1571                 if (awardedQuote.getVendorNumber().equals(poQuote.getVendorNumber())) {
1572                     awardedVendorInfo.append(SpringContext.getBean(DateTimeService.class).getCurrentSqlDate().toString());
1573                 }
1574             } else {
1575                 awardedVendorInfo.append(poQuote.getPurchaseOrderQuoteAwardTimestamp().toString());
1576             }
1577             awardedVendorInfo.append("[br]");
1578 
1579             // quote status
1580             awardedVendorInfo.append("Quote Status: ");
1581             if (poQuote.getPurchaseOrderQuoteStatusCode() != null) {
1582                 poQuote.refreshReferenceObject(PurapPropertyConstants.PURCHASE_ORDER_QUOTE_STATUS);
1583                 awardedVendorInfo.append(poQuote.getPurchaseOrderQuoteStatus().getStatusDescription());
1584             } else {
1585                 awardedVendorInfo.append("N/A");
1586             }
1587             awardedVendorInfo.append("[br]");
1588 
1589             // rank
1590             awardedVendorInfo.append("Rank: ");
1591             if (poQuote.getPurchaseOrderQuoteRankNumber() != null) {
1592                 awardedVendorInfo.append(poQuote.getPurchaseOrderQuoteRankNumber());
1593             } else {
1594                 awardedVendorInfo.append("N/A");
1595             }
1596             awardedVendorInfo.append("[br][br]");
1597         }
1598 
1599         Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
1600         if (question == null) {
1601             // ask question if not already asked
1602             return performQuestionWithoutInput(mapping, form, request, response, PODocumentsStrings.CONFIRM_AWARD_QUESTION, awardedVendorInfo.toString(), OLEConstants.CONFIRMATION_QUESTION, PODocumentsStrings.CONFIRM_AWARD_RETURN, "");
1603         } else {
1604             Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
1605             if ((PODocumentsStrings.CONFIRM_AWARD_QUESTION.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) {
1606                 // set awarded date
1607                 awardedQuote.setPurchaseOrderQuoteAwardTimestamp(SpringContext.getBean(DateTimeService.class).getCurrentTimestamp());
1608 
1609                 Date currentSqlDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
1610                 document.setPurchaseOrderQuoteAwardedDate(currentSqlDate);
1611 
1612                 // PO vendor information updated with awarded vendor
1613                 document.setVendorName(awardedQuote.getVendorName());
1614                 document.setVendorNumber(awardedQuote.getVendorNumber());
1615                 Integer headID = awardedQuote.getVendorHeaderGeneratedIdentifier();
1616                 Integer detailID = awardedQuote.getVendorDetailAssignedIdentifier();
1617                 document.setVendorHeaderGeneratedIdentifier(headID);
1618                 document.setVendorDetailAssignedIdentifier(detailID);
1619 
1620                 // use PO type address to fill in vendor address
1621                 String campusCode = GlobalVariables.getUserSession().getPerson().getCampusCode();
1622                 VendorAddress pova = SpringContext.getBean(VendorService.class).getVendorDefaultAddress(headID, detailID, AddressTypes.PURCHASE_ORDER, campusCode);
1623                 document.setVendorLine1Address(pova.getVendorLine1Address());
1624                 document.setVendorLine2Address(pova.getVendorLine2Address());
1625                 document.setVendorCityName(pova.getVendorCityName());
1626                 document.setVendorStateCode(pova.getVendorStateCode());
1627                 document.setVendorPostalCode(pova.getVendorZipCode());
1628                 document.setVendorCountryCode(pova.getVendorCountryCode());
1629                 document.setVendorFaxNumber(pova.getVendorFaxNumber());
1630 
1631                 document.updateAndSaveAppDocStatus(PurapConstants.PurchaseOrderStatuses.APPDOC_IN_PROCESS);
1632 
1633                 document.setStatusChange(PurapConstants.PurchaseOrderStatuses.APPDOC_IN_PROCESS);
1634                 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(document);
1635             }
1636         }
1637 
1638         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1639     }
1640 
1641     /**
1642      * Cancels the process of obtaining quotes. Checks whether any of the quote requests have been transmitted. If none have, tries
1643      * to obtain confirmation from the user for the cancellation. If confirmation is obtained, clears out the list of Vendors from
1644      * which to obtain quotes and writes the given reason to a note on the PO.
1645      *
1646      * @param mapping  An ActionMapping
1647      * @param form     An ActionForm
1648      * @param request  The HttpServletRequest
1649      * @param response The HttpServletResponse
1650      * @return An ActionForward
1651      * @throws Exception
1652      */
1653     public ActionForward cancelQuote(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1654         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1655         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1656 
1657         for (PurchaseOrderVendorQuote quotedVendors : document.getPurchaseOrderVendorQuotes()) {
1658             if (quotedVendors.getPurchaseOrderQuoteTransmitTimestamp() != null) {
1659                 GlobalVariables.getMessageMap().putError(PurapPropertyConstants.VENDOR_QUOTES, PurapKeyConstants.ERROR_PURCHASE_ORDER_QUOTE_ALREADY_TRASNMITTED);
1660 
1661                 return mapping.findForward(OLEConstants.MAPPING_BASIC);
1662             }
1663         }
1664 
1665         String message = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_CONFIRM_CANCEL_QUOTE);
1666         Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
1667 
1668         if (question == null) {
1669 
1670             // ask question if not already asked
1671             return performQuestionWithInput(mapping, form, request, response, PODocumentsStrings.CONFIRM_CANCEL_QUESTION, message, OLEConstants.CONFIRMATION_QUESTION, PODocumentsStrings.CONFIRM_CANCEL_RETURN, "");
1672         } else {
1673             Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
1674             if ((PODocumentsStrings.CONFIRM_CANCEL_QUESTION.equals(question)) && ConfirmationQuestion.YES.equals(buttonClicked)) {
1675                 String reason = request.getParameter(OLEConstants.QUESTION_REASON_ATTRIBUTE_NAME);
1676 
1677                 if (StringUtils.isEmpty(reason)) {
1678 
1679                     return performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, PODocumentsStrings.CONFIRM_CANCEL_QUESTION, message, OLEConstants.CONFIRMATION_QUESTION, PODocumentsStrings.CONFIRM_CANCEL_RETURN, "", "", PurapKeyConstants.ERROR_PURCHASE_ORDER_REASON_REQUIRED, OLEConstants.QUESTION_REASON_ATTRIBUTE_NAME, "250");
1680                 }
1681                 document.getPurchaseOrderVendorQuotes().clear();
1682                 Note cancelNote = new Note();
1683                 cancelNote.setAuthorUniversalIdentifier(GlobalVariables.getUserSession().getPerson().getPrincipalId());
1684                 String reasonPrefix = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_CANCEL_QUOTE_NOTE_TEXT);
1685                 cancelNote.setNoteText(reasonPrefix + reason);
1686                 cancelNote.setNoteTypeCode(document.getNoteType().getCode());
1687                 cancelNote.setNotePostedTimestamp(SpringContext.getBean(DateTimeService.class).getCurrentTimestamp());
1688                 document.addNote(cancelNote);
1689 
1690                 document.updateAndSaveAppDocStatus(PurapConstants.PurchaseOrderStatuses.APPDOC_IN_PROCESS);
1691 
1692                 //being required to add notes about changing po status even though i'm not changing status
1693                 document.setStatusChange(null);
1694                 SpringContext.getBean(PurapService.class).saveDocumentNoValidation(document);
1695             }
1696         }
1697 
1698         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1699     }
1700 
1701     /**
1702      * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#cancel(org.apache.struts.action.ActionMapping,
1703      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
1704      */
1705     @Override
1706     public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1707         Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
1708         // this should probably be moved into a protected instance variable
1709         ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
1710 
1711         // logic for cancel question
1712         if (question == null) {
1713 
1714             // ask question if not already asked
1715             return this.performQuestionWithoutInput(mapping, form, request, response, OLEConstants.DOCUMENT_CANCEL_QUESTION, kualiConfiguration.getPropertyValueAsString("document.question.cancel.text"), OLEConstants.CONFIRMATION_QUESTION, OLEConstants.MAPPING_CANCEL, "");
1716         } else {
1717             Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
1718             if ((OLEConstants.DOCUMENT_CANCEL_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
1719 
1720                 // if no button clicked just reload the doc
1721                 return mapping.findForward(OLEConstants.MAPPING_BASIC);
1722             }
1723             // else go to cancel logic below
1724         }
1725 
1726         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1727         SpringContext.getBean(DocumentService.class).cancelDocument(kualiDocumentFormBase.getDocument(), kualiDocumentFormBase.getAnnotation());
1728 
1729         return returnToSender(request, mapping, kualiDocumentFormBase);
1730     }
1731 
1732     /**
1733      * @see org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#save(org.apache.struts.action.ActionMapping,
1734      *      org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
1735      */
1736     @Override
1737     public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1738         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1739         PurchaseOrderDocument po = poForm.getPurchaseOrderDocument();
1740 
1741         if (StringUtils.isNotBlank(po.getApplicationDocumentStatus()) && StringUtils.isNotBlank(po.getStatusChange()) && (!StringUtils.equals(po.getApplicationDocumentStatus(), po.getStatusChange()))) {
1742 
1743             WorkflowDocument workflowDocument = po.getDocumentHeader().getWorkflowDocument();
1744             if (ObjectUtils.isNull(workflowDocument) || workflowDocument.isInitiated() || workflowDocument.isSaved()) {
1745 
1746                 return this.askSaveQuestions(mapping, form, request, response, PODocumentsStrings.MANUAL_STATUS_CHANGE_QUESTION);
1747             }
1748         }
1749 
1750         return super.save(mapping, form, request, response);
1751     }
1752 
1753     /**
1754      * Obtains confirmation and records reasons for the manual status changes which can take place before the purchase order has
1755      * been routed. If confirmation is given, changes the status, saves, and records the given reason in an note on the purchase
1756      * order.
1757      *
1758      * @param mapping  An ActionMapping
1759      * @param form     An ActionForm
1760      * @param request  The HttpServletRequest
1761      * @param response The HttpServletResponse
1762      * @return An ActionForward
1763      */
1764     protected ActionForward askSaveQuestions(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String questionType) {
1765         KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
1766         PurchaseOrderDocument po = (PurchaseOrderDocument) kualiDocumentFormBase.getDocument();
1767         Object question = request.getParameter(OLEConstants.QUESTION_INST_ATTRIBUTE_NAME);
1768         String reason = request.getParameter(OLEConstants.QUESTION_REASON_ATTRIBUTE_NAME);
1769         ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
1770         ActionForward forward = mapping.findForward(OLEConstants.MAPPING_BASIC);
1771         String notePrefix = "";
1772 
1773         if (StringUtils.equals(questionType, PODocumentsStrings.MANUAL_STATUS_CHANGE_QUESTION) && ObjectUtils.isNull(question)) {
1774             String message = kualiConfiguration.getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_MANUAL_STATUS_CHANGE);
1775             try {
1776 
1777                 return this.performQuestionWithInput(mapping, form, request, response, questionType, message, OLEConstants.CONFIRMATION_QUESTION, questionType, "");
1778             } catch (Exception e) {
1779                 throw new RuntimeException(e);
1780             }
1781         } else {
1782             Object buttonClicked = request.getParameter(OLEConstants.QUESTION_CLICKED_BUTTON);
1783             if (question.equals(questionType) && buttonClicked.equals(ConfirmationQuestion.NO)) {
1784                 // If 'No' is the button clicked, just reload the doc
1785                 return forward;
1786             }
1787 
1788             // Build out full message.
1789             if (StringUtils.equals(questionType, PODocumentsStrings.MANUAL_STATUS_CHANGE_QUESTION)) {
1790                 Map<String, String> manuallyChangeableStatuses = new HashMap<String, String>();
1791                 manuallyChangeableStatuses.put(PurchaseOrderStatuses.APPDOC_IN_PROCESS, "In Process");
1792                 manuallyChangeableStatuses.put(PurchaseOrderStatuses.APPDOC_WAITING_FOR_VENDOR, "Waiting for Vendor");
1793                 manuallyChangeableStatuses.put(PurchaseOrderStatuses.APPDOC_WAITING_FOR_DEPARTMENT, "Waiting for Department");
1794 
1795                 String key = kualiConfiguration.getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_MANUAL_STATUS_CHANGE_NOTE_PREFIX);
1796                 String oldStatus = manuallyChangeableStatuses.get(po.getApplicationDocumentStatus());
1797                 String newStatus = manuallyChangeableStatuses.get(po.getStatusChange());
1798                 key = StringUtils.replace(key, "{0}", (StringUtils.isBlank(oldStatus) ? " " : oldStatus));
1799                 notePrefix = StringUtils.replace(key, "{1}", (StringUtils.isBlank(newStatus) ? " " : newStatus));
1800             }
1801             String noteText = notePrefix + OLEConstants.BLANK_SPACE + reason;
1802             int noteTextLength = noteText.length();
1803 
1804             // Get note text max length from DD.
1805             int noteTextMaxLength = SpringContext.getBean(DataDictionaryService.class).getAttributeMaxLength(Note.class, OLEConstants.NOTE_TEXT_PROPERTY_NAME).intValue();
1806 
1807             if (StringUtils.isBlank(reason) || (noteTextLength > noteTextMaxLength)) {
1808                 // Figure out exact number of characters that the user can enter.
1809                 int reasonLimit = noteTextMaxLength - noteTextLength;
1810 
1811                 if (ObjectUtils.isNull(reason)) {
1812                     // Prevent a NPE by setting the reason to a blank string.
1813                     reason = "";
1814                 }
1815 
1816                 try {
1817                     if (StringUtils.equals(questionType, PODocumentsStrings.MANUAL_STATUS_CHANGE_QUESTION)) {
1818 
1819                         return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, questionType, kualiConfiguration.getPropertyValueAsString(PurapKeyConstants.PURCHASE_ORDER_QUESTION_MANUAL_STATUS_CHANGE), OLEConstants.CONFIRMATION_QUESTION, questionType, "", reason, PurapKeyConstants.ERROR_PURCHASE_ORDER_REASON_REQUIRED, OLEConstants.QUESTION_REASON_ATTRIBUTE_NAME, new Integer(reasonLimit).toString());
1820                     }
1821                 } catch (Exception e) {
1822                     throw new RuntimeException(e);
1823                 }
1824             } else if (StringUtils.equals(questionType, PODocumentsStrings.MANUAL_STATUS_CHANGE_QUESTION)) {
1825                 executeManualStatusChange(po);
1826                 try {
1827                     forward = super.save(mapping, form, request, response);
1828                 } catch (Exception e) {
1829                     throw new RuntimeException(e);
1830                 }
1831             }
1832             Note newNote = new Note();
1833             newNote.setNoteText(noteText);
1834             newNote.setNoteTypeCode(OLEConstants.NoteTypeEnum.BUSINESS_OBJECT_NOTE_TYPE.getCode());
1835             kualiDocumentFormBase.setNewNote(newNote);
1836             try {
1837                 insertBONote(mapping, kualiDocumentFormBase, request, response);
1838             } catch (Exception e) {
1839                 throw new RuntimeException(e);
1840             }
1841         }
1842 
1843         return forward;
1844     }
1845 
1846     /**
1847      * Applies a manual change of status to the given purchase order document.
1848      *
1849      * @param po A PurchaseOrderDocument
1850      */
1851     protected void executeManualStatusChange(PurchaseOrderDocument po) {
1852         try {
1853             po.updateAndSaveAppDocStatus(po.getStatusChange());
1854             SpringContext.getBean(PurapService.class).saveDocumentNoValidation(po);
1855         } catch (Exception e) {
1856             throw new RuntimeException(e);
1857         }
1858     }
1859 
1860     /**
1861      * @see org.kuali.ole.module.purap.document.web.struts.PurchasingAccountsPayableActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
1862      */
1863     @Override
1864     protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase) throws WorkflowException {
1865         super.loadDocument(kualiDocumentFormBase);
1866         PurchaseOrderForm poForm = (PurchaseOrderForm) kualiDocumentFormBase;
1867         PurchaseOrderDocument po = (PurchaseOrderDocument) poForm.getDocument();
1868         po.setInternalPurchasingLimit(SpringContext.getBean(PurchaseOrderService.class).getInternalPurchasingDollarLimit(po));
1869     }
1870 
1871     /**
1872      * Adds a PurchasingItemCapitalAsset (a container for the Capital Asset Number) to the selected
1873      * item's list.
1874      *
1875      * @param mapping  An ActionMapping
1876      * @param form     The Form
1877      * @param request  An HttpServletRequest
1878      * @param response The HttpServletResponse
1879      * @return An ActionForward
1880      * @throws Exception
1881      */
1882     public ActionForward addAsset(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1883         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1884         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1885         PurchaseOrderItem item = (PurchaseOrderItem) document.getItemByLineNumber(getSelectedLine(request) + 1);
1886         //TODO: Add a new way to add assets to the system.
1887         //item.addAsset();
1888         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1889     }
1890 
1891     public ActionForward removeAlternateVendor(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1892         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1893         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1894 
1895         document.setAlternateVendorDetailAssignedIdentifier(null);
1896         document.setAlternateVendorHeaderGeneratedIdentifier(null);
1897         document.setAlternateVendorName(null);
1898         document.setAlternateVendorNumber(null);
1899 
1900         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1901     }
1902 
1903     public ActionForward createReceivingLine(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1904         PurchaseOrderForm poForm = (PurchaseOrderForm) form;
1905         PurchaseOrderDocument document = (PurchaseOrderDocument) poForm.getDocument();
1906 
1907         String basePath = getApplicationBaseUrl();
1908         String methodToCallDocHandler = "docHandler";
1909         String methodToCallReceivingLine = "initiate";
1910 
1911         //set parameters
1912         Properties parameters = new Properties();
1913         parameters.put(OLEConstants.DISPATCH_REQUEST_PARAMETER, methodToCallDocHandler);
1914         parameters.put(OLEConstants.PARAMETER_COMMAND, methodToCallReceivingLine);
1915         parameters.put(OLEConstants.DOCUMENT_TYPE_NAME, OLEConstants.FinancialDocumentTypeCodes.LINE_ITEM_RECEIVING);
1916         parameters.put("purchaseOrderId", document.getPurapDocumentIdentifier().toString());
1917 
1918         //create url
1919         String receivingUrl = UrlFactory.parameterizeUrl(basePath + "/" + "purapLineItemReceiving.do", parameters);
1920 
1921         //create forward
1922         ActionForward forward = new ActionForward(receivingUrl, true);
1923 
1924         return forward;
1925     }
1926 
1927     public ActionForward resendPoCxml(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
1928         PurchaseOrderDocument po = (PurchaseOrderDocument) ((PurchaseOrderForm) form).getDocument();
1929         SpringContext.getBean(PurchaseOrderService.class).retransmitB2BPurchaseOrder(po);
1930         return mapping.findForward(OLEConstants.MAPPING_BASIC);
1931     }
1932 
1933 }
1934