@Override
  public ActionForward insertBONote(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
    Note newNote = kualiDocumentFormBase.getNewNote();
    NoteExtendedAttribute extendedAttribute = (NoteExtendedAttribute) newNote.getExtension();

    ActionForward forward = super.insertBONote(mapping, form, request, response);

    if (newNote != kualiDocumentFormBase.getNewNote()) {
      Note addedNote =
          kualiDocumentFormBase
              .getDocument()
              .getNotes()
              .get(kualiDocumentFormBase.getDocument().getNotes().size() - 1);
      extendedAttribute.setNoteIdentifier(addedNote.getNoteIdentifier());
      addedNote.setExtension(extendedAttribute);
      SpringContext.getBean(BusinessObjectService.class).save(extendedAttribute);
      addedNote.refreshReferenceObject("extension");
    }

    return forward;
  }
  @Override
  protected void populateAdHocActionRequestCodes(KualiDocumentFormBase formBase) {
    Document document = formBase.getDocument();
    DocumentAuthorizer documentAuthorizer =
        getDocumentHelperService().getDocumentAuthorizer(document);
    Map<String, String> adHocActionRequestCodes = new HashMap<String, String>();

    if (documentAuthorizer.canSendAdHocRequests(
        document,
        KewApiConstants.ACTION_REQUEST_FYI_REQ,
        GlobalVariables.getUserSession().getPerson())) {
      adHocActionRequestCodes.put(
          KewApiConstants.ACTION_REQUEST_FYI_REQ, KewApiConstants.ACTION_REQUEST_FYI_REQ_LABEL);
    }
    if ((document.getDocumentHeader().getWorkflowDocument().isInitiated()
            || document.getDocumentHeader().getWorkflowDocument().isSaved()
            || document.getDocumentHeader().getWorkflowDocument().isEnroute())
        && documentAuthorizer.canSendAdHocRequests(
            document,
            KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ,
            GlobalVariables.getUserSession().getPerson())) {
      adHocActionRequestCodes.put(
          KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ,
          KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL);
    }
    formBase.setAdHocActionRequestCodes(adHocActionRequestCodes);
  }
 /**
  * This method is called from the createDocument and processes through all the accouting lines and
  * checks to see if they need sales tax fields
  *
  * @param kualiDocumentFormBase
  * @param baselineSourceLines
  */
 protected void handleSalesTaxRequiredAllLines(
     KualiDocumentFormBase kualiDocumentFormBase, List<AccountingLine> baselineAcctingLines) {
   AccountingDocument accoutingDocument = (AccountingDocument) kualiDocumentFormBase.getDocument();
   int index = 0;
   for (AccountingLine accountingLine : baselineAcctingLines) {
     boolean source = false;
     if (accountingLine.isSourceAccountingLine()) {
       source = true;
     }
     handleSalesTaxRequired(accoutingDocument, accountingLine, source, false, index);
     index++;
   }
 }
  /**
   * Checks the continuation account indicator and generates warnings if continuation accounts were
   * used to replace original accounts on the document.
   *
   * @see
   *     org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#loadDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
   */
  @Override
  protected void loadDocument(KualiDocumentFormBase kualiDocumentFormBase)
      throws WorkflowException {
    super.loadDocument(kualiDocumentFormBase);
    AccountsPayableDocument document =
        (AccountsPayableDocument) kualiDocumentFormBase.getDocument();

    SpringContext.getBean(AccountsPayableService.class)
        .generateExpiredOrClosedAccountWarning(document);

    SpringContext.getBean(AccountsPayableService.class).updateItemList(document);
    ((AccountsPayableFormBase) kualiDocumentFormBase).updateItemCounts();
  }
 protected boolean checkSalesTaxRequiredAllLines(
     KualiDocumentFormBase kualiDocumentFormBase, List<AccountingLine> baselineAcctingLines) {
   AccountingDocument accoutingDocument = (AccountingDocument) kualiDocumentFormBase.getDocument();
   boolean passed = true;
   int index = 0;
   for (AccountingLine accountingLine : baselineAcctingLines) {
     boolean source = false;
     if (accountingLine.isSourceAccountingLine()) {
       source = true;
     }
     passed &= checkSalesTax(accoutingDocument, accountingLine, source, false, index);
     index++;
   }
   return passed;
 }
  @Override
  @SuppressWarnings("deprecation")
  public ActionForward recall(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    ActionForward forward; // the return value

    ReasonPrompt prompt =
        new ReasonPrompt(
            KRADConstants.DOCUMENT_RECALL_QUESTION,
            Constants.NON_CANCELLING_RECALL_QUESTION_TEXT_KEY,
            Constants.NON_CANCELLING_RECALL_QUESTION,
            RiceKeyConstants.ERROR_DOCUMENT_RECALL_REASON_REQUIRED,
            KRADConstants.MAPPING_RECALL,
            NonCancellingRecallQuestion.NO,
            RiceKeyConstants.MESSAGE_RECALL_NOTE_TEXT_INTRO);
    ReasonPrompt.Response resp = prompt.ask(mapping, form, request, response);

    if (resp.forward != null) {
      // forward either to a fresh display of the question, or to one with "blank reason" error
      // message due to the previous answer,
      // or back to the document if 'return to document' (abort button) was clicked
      forward = resp.forward;
    }
    // recall to action only if the button was selected by the user
    else if (KRADConstants.DOCUMENT_RECALL_QUESTION.equals(resp.question)
        && NonCancellingRecallQuestion.YES.equals(resp.button)) {
      KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
      doProcessingAfterPost(kualiDocumentFormBase, request);
      getDocumentService().recallDocument(kualiDocumentFormBase.getDocument(), resp.reason, false);
      // we should return to the portal to avoid problems with workflow routing changes to the
      // document.
      // This should eventually return to the holding page, but currently waiting on KCINFR-760.
      forward = mapping.findForward(KRADConstants.MAPPING_PORTAL);
    } else {
      // they chose not to recall so return them back to document
      forward = mapping.findForward(RiceConstants.MAPPING_BASIC);
    }

    return forward;
  }
  @Override
  public void process(final HttpServletRequest request, final HttpServletResponse response)
      throws IOException, ServletException {
    // indicates that we are running in legacy KNS context
    LegacyUtils.beginLegacyContext();
    try {
      if (LOG.isInfoEnabled()) {
        LOG.info(
            new StringBuffer("Started processing request: '")
                .append(request.getRequestURI())
                .append("' w/ query string: '")
                .append(request.getQueryString())
                .append("'"));
      }

      try {
        strutsProcess(request, response);
      } catch (FileUploadLimitExceededException e) {
        ActionForward actionForward =
            processException(request, response, e, e.getActionForm(), e.getActionMapping());
        processForwardConfig(request, response, actionForward);
      } finally {
        KNSGlobalVariables.setKualiForm(null);
      }

      try {
        ActionForm form = WebUtils.getKualiForm(request);

        if (form != null && form instanceof KualiDocumentFormBase) {
          String docId = ((KualiDocumentFormBase) form).getDocId();
          if (docId != null) {
            MDC.put(MDC_DOC_ID, docId);
          }
        }

        String refreshCaller = request.getParameter(KRADConstants.REFRESH_CALLER);
        if (form != null
            && KualiDocumentFormBase.class.isAssignableFrom(form.getClass())
            && !KRADConstants.QUESTION_REFRESH.equalsIgnoreCase(refreshCaller)) {
          KualiDocumentFormBase docForm = (KualiDocumentFormBase) form;
          Document document = docForm.getDocument();
          String docFormKey = docForm.getFormKey();

          UserSession userSession =
              (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);

          if (WebUtils.isDocumentSession(document, docForm)) {
            getSessionDocumentService()
                .setDocumentForm(docForm, userSession, request.getRemoteAddr());
          }

          Boolean exitingDocument = (Boolean) request.getAttribute(KRADConstants.EXITING_DOCUMENT);

          if (exitingDocument != null && exitingDocument.booleanValue()) {
            // remove KualiDocumentFormBase object from session and
            // table.
            getSessionDocumentService()
                .purgeDocumentForm(
                    docForm.getDocument().getDocumentNumber(),
                    docFormKey,
                    userSession,
                    request.getRemoteAddr());
          }
        }

        if (LOG.isInfoEnabled()) {
          LOG.info(
              new StringBuffer("Finished processing request: '")
                  .append(request.getRequestURI())
                  .append("' w/ query string: '")
                  .append(request.getQueryString())
                  .append("'"));
        }

      } finally {
        // MDC docId key is set above, and also during super.process() in the call to
        // processActionForm
        MDC.remove(MDC_DOC_ID);
      }
    } finally {
      LegacyUtils.endLegacyContext();
    }
  }
 /**
  * Do initialization for a new credit card receipt
  *
  * @see
  *     org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#createDocument(org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase)
  */
 @Override
 protected void createDocument(KualiDocumentFormBase kualiDocumentFormBase)
     throws WorkflowException {
   super.createDocument(kualiDocumentFormBase);
   ((CreditCardReceiptDocument) kualiDocumentFormBase.getDocument()).initiateDocument();
 }
  protected ActionForward askQuestionsAndPerformReopenPurchaseOrder(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    LOG.debug("askQuestionsAndPerformDocumentAction started.");
    KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
    AccountsPayableDocumentBase apDoc =
        (AccountsPayableDocumentBase) kualiDocumentFormBase.getDocument();
    Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
    String questionType = PODocumentsStrings.REOPEN_PO_QUESTION;
    String confirmType = PODocumentsStrings.CONFIRM_REOPEN_QUESTION;
    String messageType = PurapKeyConstants.PURCHASE_ORDER_MESSAGE_REOPEN_DOCUMENT;
    String operation = "Reopen ";

    try {
      ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);

      // Start in logic for confirming the proposed operation.
      if (ObjectUtils.isNull(question)) {
        String key =
            kualiConfiguration.getPropertyValueAsString(
                PurapKeyConstants.PURCHASE_ORDER_QUESTION_DOCUMENT);
        String message = StringUtils.replace(key, "{0}", operation);
        return this.performQuestionWithoutInput(
            mapping,
            form,
            request,
            response,
            questionType,
            message,
            KFSConstants.CONFIRMATION_QUESTION,
            questionType,
            "");
      } else {
        Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
        if (question.equals(questionType) && buttonClicked.equals(ConfirmationQuestion.NO)) {
          // If 'No' is the button clicked, just reload the doc
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
        } else if (question.equals(confirmType)
            && buttonClicked.equals(SingleConfirmationQuestion.OK)) {
          // This is the case when the user clicks on "OK" in the end; redirect to the preq doc
          return mapping.findForward(KFSConstants.MAPPING_BASIC);
        }
      }

      PurchaseOrderDocument po = apDoc.getPurchaseOrderDocument();
      if (!po.isPendingActionIndicator()
          && PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED.equals(
              po.getApplicationDocumentStatus())) {
        /*
         * Below if-else code block calls PurchaseOrderService methods that will throw ValidationException objects if errors
         * occur during any process in the attempt to perform its actions. Assume, if these return successfully, that the
         * PurchaseOrderDocument object returned from each is the newly created document and that all actions in the method
         * were run correctly. NOTE: IF BELOW IF-ELSE IS EDITED THE NEW METHODS CALLED MUST THROW ValidationException OBJECT
         * IF AN ERROR IS ADDED TO THE GlobalVariables
         */
        po = initiateReopenPurchaseOrder(po, kualiDocumentFormBase.getAnnotation());

        if (!GlobalVariables.getMessageMap().hasNoErrors()) {
          throw new ValidationException("errors occurred during new PO creation");
        }

        if (StringUtils.isNotEmpty(messageType)) {
          KNSGlobalVariables.getMessageList().add(messageType);
        }
        return this.performQuestionWithoutInput(
            mapping,
            form,
            request,
            response,
            confirmType,
            kualiConfiguration.getPropertyValueAsString(messageType),
            PODocumentsStrings.SINGLE_CONFIRMATION_QUESTION,
            questionType,
            "");
      } else {
        return this.performQuestionWithoutInput(
            mapping,
            form,
            request,
            response,
            confirmType,
            "Unable to reopen the PO at this time due to the incorrect PO status or a pending PO change document.",
            PODocumentsStrings.SINGLE_CONFIRMATION_QUESTION,
            questionType,
            "");
      }

    } catch (ValidationException ve) {
      throw ve;
    }
  }
  /**
   * Builds and asks questions which require text input by the user for a payment request or a
   * credit memo.
   *
   * @param mapping An ActionMapping
   * @param form An ActionForm
   * @param request The HttpServletRequest
   * @param response The HttpServletResponse
   * @param questionType A String used to distinguish which question is being asked
   * @param notePrefix A String explaining what action was taken, to be prepended to the note
   *     containing the reason, which gets written to the document
   * @param operation A one-word String description of the action to be taken, to be substituted
   *     into the message. (Can be an empty String for some messages.)
   * @param messageKey A (whole) key to the message which will appear on the question screen
   * @param questionsAndCallbacks A TreeMap associating the type of question to be asked and the
   *     type of callback which should happen in that case
   * @param messagePrefix The most general part of a key to a message text to be retrieved from
   *     ConfigurationService, Describes a collection of questions.
   * @param redirect An ActionForward to return to if done with questions
   * @return An ActionForward
   * @throws Exception
   */
  protected ActionForward askQuestionWithInput(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response,
      String questionType,
      String notePrefix,
      String operation,
      String messageKey,
      TreeMap<String, PurQuestionCallback> questionsAndCallbacks,
      String messagePrefix,
      ActionForward redirect)
      throws Exception {
    KualiDocumentFormBase kualiDocumentFormBase = (KualiDocumentFormBase) form;
    AccountsPayableDocumentBase apDocument =
        (AccountsPayableDocumentBase) kualiDocumentFormBase.getDocument();

    String question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);
    String reason = request.getParameter(KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME);
    String noteText = "";

    ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
    String firstQuestion = questionsAndCallbacks.firstKey();
    PurQuestionCallback callback = null;
    Iterator questions = questionsAndCallbacks.keySet().iterator();
    String mapQuestion = null;
    String key = null;

    // Start in logic for confirming the close.
    if (question == null) {
      key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, firstQuestion);
      String message = StringUtils.replace(key, "{0}", operation);

      // Ask question if not already asked.
      return this.performQuestionWithInput(
          mapping,
          form,
          request,
          response,
          firstQuestion,
          message,
          KFSConstants.CONFIRMATION_QUESTION,
          questionType,
          "");
    } else {
      // find callback for this question
      while (questions.hasNext()) {
        mapQuestion = (String) questions.next();

        if (StringUtils.equals(mapQuestion, question)) {
          callback = questionsAndCallbacks.get(mapQuestion);
          break;
        }
      }
      key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, mapQuestion);

      Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);
      if (question.equals(mapQuestion) && buttonClicked.equals(ConfirmationQuestion.NO)) {
        // If 'No' is the button clicked, just reload the doc

        String nextQuestion = null;
        // ask another question if more left
        if (questions.hasNext()) {
          nextQuestion = (String) questions.next();
          key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, nextQuestion);

          return this.performQuestionWithInput(
              mapping,
              form,
              request,
              response,
              nextQuestion,
              key,
              KFSConstants.CONFIRMATION_QUESTION,
              questionType,
              "");
        } else {

          return mapping.findForward(KFSConstants.MAPPING_BASIC);
        }
      }
      // Have to check length on value entered.
      String introNoteMessage = notePrefix + KFSConstants.BLANK_SPACE;

      // Build out full message.
      noteText = introNoteMessage + reason;
      int noteTextLength = noteText.length();

      // Get note text max length from DD.
      int noteTextMaxLength =
          SpringContext.getBean(DataDictionaryService.class)
              .getAttributeMaxLength(Note.class, KFSConstants.NOTE_TEXT_PROPERTY_NAME)
              .intValue();
      if (StringUtils.isBlank(reason) || (noteTextLength > noteTextMaxLength)) {
        // Figure out exact number of characters that the user can enter.
        int reasonLimit = noteTextMaxLength - noteTextLength;
        if (reason == null) {
          // Prevent a NPE by setting the reason to a blank string.
          reason = "";
        }

        return this.performQuestionWithInputAgainBecauseOfErrors(
            mapping,
            form,
            request,
            response,
            mapQuestion,
            key,
            KFSConstants.CONFIRMATION_QUESTION,
            questionType,
            "",
            reason,
            PurapKeyConstants.ERROR_PAYMENT_REQUEST_REASON_REQUIRED,
            KFSConstants.QUESTION_REASON_ATTRIBUTE_NAME,
            new Integer(reasonLimit).toString());
      }
    }

    // make callback
    if (ObjectUtils.isNotNull(callback)) {
      AccountsPayableDocument refreshedApDocument = callback.doPostQuestion(apDocument, noteText);
      kualiDocumentFormBase.setDocument(refreshedApDocument);
    }
    String nextQuestion = null;
    // ask another question if more left
    if (questions.hasNext()) {
      nextQuestion = (String) questions.next();
      key = getQuestionProperty(messageKey, messagePrefix, kualiConfiguration, nextQuestion);

      return this.performQuestionWithInput(
          mapping,
          form,
          request,
          response,
          nextQuestion,
          key,
          KFSConstants.CONFIRMATION_QUESTION,
          questionType,
          "");
    }

    return redirect;
  }
  @SuppressWarnings("unchecked")
  @Override
  // Overriding this because KraTransactionalDocumentActionBase assumes the authorizer is of type
  // KcDocumentAuthorizerBase
  protected void populateAuthorizationFields(KualiDocumentFormBase formBase) {
    if (formBase.isFormDocumentInitialized()) {
      Document document = formBase.getDocument();
      Person user = GlobalVariables.getUserSession().getPerson();
      DocumentPresentationController documentPresentationController =
          KNSServiceLocator.getDocumentHelperService().getDocumentPresentationController(document);
      DocumentAuthorizer documentAuthorizer =
          getDocumentHelperService().getDocumentAuthorizer(document);
      Set<String> documentActions = documentPresentationController.getDocumentActions(document);
      documentActions = documentAuthorizer.getDocumentActions(document, user, documentActions);

      if (getDataDictionaryService()
          .getDataDictionary()
          .getDocumentEntry(document.getClass().getName())
          .getUsePessimisticLocking()) {
        documentActions =
            getPessimisticLockService().getDocumentActions(document, user, documentActions);
      }

      Set<String> editModes = new HashSet<String>();
      if (!documentAuthorizer.canOpen(document, user)) {
        editModes.add(AuthorizationConstants.EditMode.UNVIEWABLE);
      } else if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT)) {
        editModes.add(AuthorizationConstants.EditMode.FULL_ENTRY);
      } else {
        editModes.add(AuthorizationConstants.EditMode.VIEW_ONLY);
      }
      if (hasPermission("KC-IP", "Edit Institutional Proposal")) {
        editModes.add(MODIFY_IP);
      }
      Map editMode = this.convertSetToMap(editModes);
      if (getDataDictionaryService()
          .getDataDictionary()
          .getDocumentEntry(document.getClass().getName())
          .getUsePessimisticLocking()) {
        editMode = getPessimisticLockService().establishLocks(document, editMode, user);
      }

      // We don't want to use KNS way to determine can edit document overview
      // It should be the same as can edit
      if (editMode.containsKey(AuthorizationConstants.EditMode.FULL_ENTRY)) {
        if (!documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW)) {
          documentActions.add(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW);
        }
      } else {
        if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW)) {
          documentActions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW);
        }
      }

      if (editMode.containsKey(AuthorizationConstants.EditMode.VIEW_ONLY)
          && !editMode.containsKey(MODIFY_IP)
          && documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RELOAD)) {
        documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RELOAD);
      }
      formBase.setDocumentActions(convertSetToMap(documentActions));
      formBase.setEditingMode(editMode);
    }
  }