@Override
  public boolean validate(AttributedDocumentEvent event) {
    boolean valid = true;

    GlobalVariables.getMessageMap().clearErrorPath();

    TravelEntertainmentDocument document = (TravelEntertainmentDocument) event.getDocument();
    boolean entertainmentHostAttached = false;
    List<Note> notes = document.getNotes();
    for (Note note : notes) {
      if (ObjectUtils.isNotNull(note.getAttachment())
          && TemConstants.AttachmentTypeCodes.ATTACHMENT_TYPE_ENT_HOST_CERT.equals(
              note.getAttachment().getAttachmentTypeCode())) {
        entertainmentHostAttached = true;
        break;
      }
    }

    // if host is not as payee than entertainment host certification is required ; otherwise not
    if (!document.getHostAsPayee() && !entertainmentHostAttached) {
      valid = addError();
    }

    return valid;
  }
 protected void addNotes(
     String documentNumber,
     List<SubObjectCode> listOfSubObjects,
     String messageKey,
     PersistableBusinessObject noteParent,
     Note noteTemplate) {
   for (int i = 0; i < listOfSubObjects.size(); i += getNumSubObjectsPerNote()) {
     try {
       String subAccountString =
           createSubObjectChunk(listOfSubObjects, i, i + getNumSubObjectsPerNote());
       if (StringUtils.isNotBlank(subAccountString)) {
         String noteTextTemplate = kualiConfigurationService.getPropertyValueAsString(messageKey);
         String noteText = MessageFormat.format(noteTextTemplate, subAccountString);
         Note note =
             noteService.createNote(
                 noteTemplate, noteParent, GlobalVariables.getUserSession().getPrincipalId());
         note.setNoteText(noteText);
         note.setNotePostedTimestampToCurrent();
         noteService.save(note);
       }
     } catch (Exception e) {
       LOG.error("Unable to create/save notes for document " + documentNumber, e);
       throw new RuntimeException("Unable to create/save notes for document " + documentNumber, e);
     }
   }
 }
  /**
   * @see
   *     org.kuali.rice.krad.service.DocumentService#disapproveDocument(org.kuali.rice.krad.document.Document,
   *     java.lang.String)
   */
  @Override
  public Document disapproveDocument(Document document, String annotation) throws Exception {
    checkForNulls(document);

    Note note = createNoteFromDocument(document, annotation);
    // if note type is BO, override and link disapprove notes to Doc Header
    if (document.getNoteType().equals(NoteType.BUSINESS_OBJECT)) {
      note.setNoteTypeCode(NoteType.DOCUMENT_HEADER.getCode());
      note.setRemoteObjectIdentifier(document.getDocumentHeader().getObjectId());
    }
    document.addNote(note);

    // SAVE THE NOTE
    // Note: This save logic is replicated here and in KualiDocumentAction, when to save (based on
    // doc state) should be moved
    //      into a doc service method
    getNoteService().save(note);

    prepareWorkflowDocument(document);
    getWorkflowDocumentService()
        .disapprove(document.getDocumentHeader().getWorkflowDocument(), annotation);
    UserSessionUtils.addWorkflowDocument(
        GlobalVariables.getUserSession(), document.getDocumentHeader().getWorkflowDocument());
    removeAdHocPersonsAndWorkgroups(document);
    return document;
  }
  /** @see org.kuali.rice.krad.service.DocumentService */
  @Override
  public void sendNoteRouteNotification(Document document, Note note, Person sender)
      throws WorkflowException {
    AdHocRouteRecipient routeRecipient = note.getAdHocRouteRecipient();

    // build notification request
    Person requestedUser = this.getPersonService().getPersonByPrincipalName(routeRecipient.getId());
    String senderName = sender.getFirstName() + " " + sender.getLastName();
    String requestedName = requestedUser.getFirstName() + " " + requestedUser.getLastName();

    String notificationText =
        kualiConfigurationService.getPropertyValueAsString(
            RiceKeyConstants.MESSAGE_NOTE_NOTIFICATION_ANNOTATION);
    if (StringUtils.isBlank(notificationText)) {
      throw new RuntimeException(
          "No annotation message found for note notification. Message needs added to application resources with key:"
              + RiceKeyConstants.MESSAGE_NOTE_NOTIFICATION_ANNOTATION);
    }
    notificationText =
        MessageFormat.format(
            notificationText, new Object[] {senderName, requestedName, note.getNoteText()});

    List<AdHocRouteRecipient> routeRecipients = new ArrayList<AdHocRouteRecipient>();
    routeRecipients.add(routeRecipient);

    workflowDocumentService.sendWorkflowNotification(
        document.getDocumentHeader().getWorkflowDocument(),
        notificationText,
        routeRecipients,
        KRADConstants.NOTE_WORKFLOW_NOTIFICATION_REQUEST_LABEL);

    // clear recipient allowing an notification to be sent to another person
    note.setAdHocRouteRecipient(new AdHocRoutePerson());
  }
  /**
   * @see
   *     org.kuali.rice.krad.service.DocumentService#createNoteFromDocument(org.kuali.rice.krad.document.Document,
   *     java.lang.String)
   */
  @Override
  public Note createNoteFromDocument(Document document, String text) {
    Note note = new Note();

    note.setNotePostedTimestamp(getDateTimeService().getCurrentTimestamp());
    note.setNoteText(text);
    note.setNoteTypeCode(document.getNoteType().getCode());

    PersistableBusinessObject bo = document.getNoteTarget();
    // TODO gah! this is awful
    Person kualiUser = GlobalVariables.getUserSession().getPerson();
    if (kualiUser == null) {
      throw new IllegalStateException("Current UserSession has a null Person.");
    }
    return bo == null ? null : getNoteService().createNote(note, bo, kualiUser.getPrincipalId());
  }
 private void linkNoteRemoteObjectId(Note note, PersistableBusinessObject noteTarget) {
   String objectId = noteTarget.getObjectId();
   if (StringUtils.isBlank(objectId)) {
     throw new IllegalStateException(
         "Attempted to link a Note with a PersistableBusinessObject with no object id");
   }
   note.setRemoteObjectIdentifier(noteTarget.getObjectId());
 }
  @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;
  }
 protected void addMaintenanceLockedNotes(
     String documentNumber,
     Map<SubObjectCode, String> lockedSubObjects,
     String messageKey,
     PersistableBusinessObject noteParent,
     Note noteTemplate) {
   for (Map.Entry<SubObjectCode, String> entry : lockedSubObjects.entrySet()) {
     try {
       SubObjectCode subObjCd = entry.getKey();
       String subObjectString =
           subObjCd.getUniversityFiscalYear()
               + " - "
               + subObjCd.getChartOfAccountsCode()
               + " - "
               + subObjCd.getAccountNumber()
               + " - "
               + subObjCd.getFinancialObjectCode()
               + " - "
               + subObjCd.getFinancialSubObjectCode();
       if (StringUtils.isNotBlank(subObjectString)) {
         String noteTextTemplate = kualiConfigurationService.getPropertyValueAsString(messageKey);
         String noteText =
             MessageFormat.format(noteTextTemplate, subObjectString, entry.getValue());
         Note note =
             noteService.createNote(
                 noteTemplate, noteParent, GlobalVariables.getUserSession().getPrincipalId());
         note.setNoteText(noteText);
         note.setNotePostedTimestampToCurrent();
         noteService.save(note);
       }
     } catch (Exception e) {
       LOG.error("Unable to create/save notes for document " + documentNumber, e);
       throw new RuntimeException("Unable to create/save notes for document " + documentNumber, e);
     }
   }
 }
  protected void addNoteAfterProcessingAgencyStagingExpense(
      MaintenanceDocument document, List<ErrorMessage> errors) {

    Principal kfsSystemUser =
        getIdentityService().getPrincipalByPrincipalName(KFSConstants.SYSTEM_USER);
    String errorText = getMessageAsString(errors);

    if (!StringUtils.isEmpty(errorText)) {
      // check maxLength on a Note and truncate if necessary
      Integer maxLength =
          getDataDictionaryService()
              .getAttributeMaxLength(Note.class, KRADConstants.NOTE_TEXT_PROPERTY_NAME);
      if (errorText.length() > maxLength) {
        LOG.warn("Adding a truncated error text to Note due to space limitations. Original text:");
        LOG.warn(errorText);
        errorText = errorText.substring(0, maxLength);
      }

      final Note newNote = getDocumentService().createNoteFromDocument(document, errorText);
      newNote.setAuthorUniversalIdentifier(kfsSystemUser.getPrincipalId());
      document.addNote(newNote);
      getNoteService().save(newNote);
    }
  }
  // mjmc
  // *************************************************************************************************
  private PurchaseOrderDocument copyNotesAndAttachmentsToPO(
      RequisitionDocument reqDoc, PurchaseOrderDocument poDoc) {

    purapService.saveDocumentNoValidation(poDoc);
    List<Note> notes = (List<Note>) reqDoc.getNotes();
    int noteLength = notes.size();
    if (noteLength > 0) {
      for (Note note : notes) {
        try {
          Note copyingNote =
              SpringContext.getBean(DocumentService.class)
                  .createNoteFromDocument(poDoc, note.getNoteText());
          purapService.saveDocumentNoValidation(poDoc);
          copyingNote.setNotePostedTimestamp(note.getNotePostedTimestamp());
          copyingNote.setAuthorUniversalIdentifier(note.getAuthorUniversalIdentifier());
          copyingNote.setNoteTopicText(note.getNoteTopicText());
          Attachment originalAttachment =
              SpringContext.getBean(AttachmentService.class)
                  .getAttachmentByNoteId(note.getNoteIdentifier());
          NoteExtendedAttribute noteExtendedAttribute = (NoteExtendedAttribute) note.getExtension();
          if (originalAttachment != null
              || (ObjectUtils.isNotNull(noteExtendedAttribute)
                  && noteExtendedAttribute.isCopyNoteIndicator())) {
            if (originalAttachment != null) {
              Attachment newAttachment =
                  SpringContext.getBean(AttachmentService.class)
                      .createAttachment(
                          (PersistableBusinessObject) copyingNote,
                          originalAttachment.getAttachmentFileName(),
                          originalAttachment.getAttachmentMimeTypeCode(),
                          originalAttachment.getAttachmentFileSize().intValue(),
                          originalAttachment.getAttachmentContents(),
                          originalAttachment.getAttachmentTypeCode()); // new Attachment();

              if (ObjectUtils.isNotNull(originalAttachment)
                  && ObjectUtils.isNotNull(newAttachment)) {
                copyingNote.addAttachment(newAttachment);
              }
            }

            poDoc.addNote(copyingNote);
          }

        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    }
    purapService.saveDocumentNoValidation(poDoc);
    return poDoc;
  } //  mjmc end
 private Note truncateNoteTextTo800(Note note) {
   if (note.getNoteText().length() > 800) {
     note.setNoteText(note.getNoteText().substring(0, 799));
   }
   return note;
 }
Пример #12
0
  /**
   * This method is used to send emails to the agency
   *
   * @param invoices
   */
  @Override
  public void sendInvoicesViaEmail(List<ContractsGrantsInvoiceDocument> invoices)
      throws AddressException, MessagingException {
    LOG.debug("sendInvoicesViaEmail() starting.");

    Properties props = getConfigProperties();

    // Get session
    Session session = Session.getInstance(props, null);
    for (ContractsGrantsInvoiceDocument invoice : invoices) {
      List<InvoiceAddressDetail> invoiceAddressDetails = invoice.getInvoiceAddressDetails();
      for (InvoiceAddressDetail invoiceAddressDetail : invoiceAddressDetails) {
        if (ArConstants.InvoiceTransmissionMethod.EMAIL.equals(
            invoiceAddressDetail.getInvoiceTransmissionMethodCode())) {

          // KFSTI-48 Refactor to retrieve the note through noteService
          Note note = noteService.getNoteByNoteId(invoiceAddressDetail.getNoteId());

          if (ObjectUtils.isNotNull(note)) {

            MimeMessage message = new MimeMessage(session);

            // From Address
            String sender =
                parameterService.getParameterValueAsString(
                    ContractsGrantsInvoiceEmailReportsBatchStep.class,
                    ArConstants.CG_INVOICE_FROM_EMAIL_ADDRESS);
            message.setFrom(new InternetAddress(sender));
            // To Address
            CustomerAddress customerAddress = invoiceAddressDetail.getCustomerAddress();
            String recipients = customerAddress.getCustomerEmailAddress();
            if (StringUtils.isNotEmpty(recipients)) {
              InternetAddress[] recipientAddress = {new InternetAddress(recipients)};
              message.addRecipients(Message.RecipientType.TO, recipientAddress);
            } else {
              LOG.warn("No recipients indicated.");
            }

            // The Subject
            String subject =
                parameterService.getParameterValueAsString(
                    ContractsGrantsInvoiceEmailReportsBatchStep.class,
                    ArConstants.CG_INVOICE_EMAIL_SUBJECT);
            String bodyText =
                parameterService.getParameterValueAsString(
                    ContractsGrantsInvoiceEmailReportsBatchStep.class,
                    ArConstants.CG_INVOICE_EMAIL_BODY);
            Map<String, String> map = new HashMap<String, String>();
            getEmailParameterList(map, invoice, customerAddress);
            subject = replaceValuesInString(subject, map);
            bodyText = replaceValuesInString(bodyText, map);
            message.setSubject(subject);
            if (StringUtils.isEmpty(subject)) {
              LOG.warn("Empty subject being sent.");
            }

            // Now the message body.
            // create and fill the first message part
            MimeBodyPart body = new MimeBodyPart();
            body.setText(bodyText);

            // create and fill the second message part
            MimeBodyPart attachment = new MimeBodyPart();
            // Use setText(text, charset), to show it off !
            // create the Multipart and its parts to it
            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(body);
            try {
              ByteArrayDataSource ds =
                  new ByteArrayDataSource(
                      note.getAttachment().getAttachmentContents(), "application/pdf");
              attachment.setDataHandler(new DataHandler(ds));
              attachment.setFileName(note.getAttachment().getAttachmentFileName());
              multipart.addBodyPart(attachment);
            } catch (IOException ex) {
              LOG.error("problem during AREmailServiceImpl.sendInvoicesViaEmail()", ex);
            }

            // add the Multipart to the message
            message.setContent(multipart);

            // Finally, send the message!
            Transport.send(message);
          }
        }
      }
      invoice.setMarkedForProcessing(ArConstants.INV_RPT_PRCS_SENT);
      documentService.updateDocument(invoice);
    }
  }
  /**
   * @see
   *     org.kuali.kfs.sys.document.validation.Validation#validate(org.kuali.kfs.sys.document.validation.event.AttributedDocumentEvent)
   */
  @SuppressWarnings("rawtypes")
  @Override
  public boolean validate(AttributedDocumentEvent event) {
    final Person currentUser = GlobalVariables.getUserSession().getPerson();
    TemSourceAccountingLine line = null;
    if (event instanceof UpdateAccountingLineEvent) {
      line =
          (TemSourceAccountingLine) ((UpdateAccountingLineEvent) event).getUpdatedAccountingLine();
    } else {
      line = (TemSourceAccountingLine) ((AccountingLineEvent) event).getAccountingLine();
    }
    List<String> holdErrors = new ArrayList<String>();
    holdErrors.addAll(GlobalVariables.getMessageMap().getErrorPath());
    GlobalVariables.getMessageMap().clearErrorPath();
    TravelDocument travelDocument = (TravelDocument) event.getDocument();

    final boolean canUpdate =
        isAtTravelNode(event.getDocument().getDocumentHeader().getWorkflowDocument())
            || isAdvancePaymentMethodException(
                event.getDocument(),
                line); // Are we at the travel node?  If so, there's a chance that accounting lines
                       // changed; if they did, that
    // was a permission granted to the travel manager so we should allow it.  Also, if we're at
    // PaymentMethod and the line is an advance accounting line, that's allowed to

    boolean valid = true;
    String errorPath = TemPropertyConstants.NEW_SOURCE_ACCTG_LINE;
    for (TemSourceAccountingLine sourceLine :
        (List<TemSourceAccountingLine>) travelDocument.getSourceAccountingLines()) {
      if (line.equals(sourceLine)) {
        errorPath =
            "document."
                + TemPropertyConstants.SOURCE_ACCOUNTING_LINE
                + "["
                + travelDocument.getSourceAccountingLines().indexOf(line)
                + "]";
        break;
      }
    }

    // Test added accounting lines for null values and if there is an access change.
    valid = getTravelDocumentService().validateSourceAccountingLines(travelDocument, false);

    if ((!travelDocument
            .getAppDocStatus()
            .equalsIgnoreCase(TemConstants.TRAVEL_DOC_APP_DOC_STATUS_INIT))
        && (!travelDocument
            .getAppDocStatus()
            .equalsIgnoreCase(TemConstants.TravelAuthorizationStatusCodeKeys.IN_PROCESS))
        && (!travelDocument
            .getAppDocStatus()
            .equalsIgnoreCase(TemConstants.TravelAuthorizationStatusCodeKeys.CHANGE_IN_PROCESS))) {
      if (!line.getAccount()
              .getAccountFiscalOfficerUser()
              .getPrincipalId()
              .equals(currentUser.getPrincipalId())
          && !canUpdate) {
        GlobalVariables.getMessageMap()
            .putError(
                KFSPropertyConstants.ACCOUNT_NUMBER,
                TemKeyConstants.ERROR_TA_FISCAL_OFFICER_ACCOUNT,
                line.getAccountNumber());
        return false;
      }
    }
    GlobalVariables.getMessageMap().addToErrorPath(errorPath);

    // skip accounting line validation for TA
    if (!(event.getDocument() instanceof TravelAuthorizationDocument)) {
      if (ObjectUtils.isNotNull(line.getObjectTypeCode())) {
        // check to make sure they're the same
        List<AccountingDistribution> list =
            getAccountingDistributionService().buildDistributionFrom(travelDocument);
        List<AccountingLineDistributionKey> distributionList =
            new ArrayList<AccountingLineDistributionKey>();
        List<String> expectedObjectCodes = new ArrayList<String>();
        for (AccountingDistribution dist : list) {
          distributionList.add(
              new AccountingLineDistributionKey(dist.getObjectCode(), dist.getCardType()));
          expectedObjectCodes.add(dist.getObjectCode());
        }
        final String expectedObjectCodesString = StringUtils.join(expectedObjectCodes, ", ");

        if (!distributionList.contains(
            new AccountingLineDistributionKey(line.getFinancialObjectCode(), line.getCardType()))) {
          GlobalVariables.getMessageMap()
              .putError(
                  TravelAuthorizationFields.FIN_OBJ_CD,
                  TemKeyConstants.ERROR_TEM_ACCOUNTING_LINES_OBJECT_CODE_CARD_TYPE,
                  line.getFinancialObjectCode(),
                  line.getCardType(),
                  expectedObjectCodesString);
          valid &= false;
        }
      }
    }

    if (line.getAmount().isLessEqual(KualiDecimal.ZERO) && !travelDocument.getBlanketTravel()) {
      GlobalVariables.getMessageMap()
          .putError(
              KFSPropertyConstants.AMOUNT,
              KFSKeyConstants.ERROR_CUSTOM,
              "Amount must be greater than zero.");
      valid &= false;
    }

    if (valid) {
      // Fly America validation
      TravelDocument document = (TravelDocument) event.getDocument();
      List<TemExpense> allExpenses = new ArrayList<TemExpense>();
      allExpenses.addAll(document.getImportedExpenses());
      allExpenses.addAll(document.getActualExpenses());
      if (allExpenses.size() > 0) {
        boolean hasAttachment = false;
        boolean showFlyAmerica = false;
        for (Note note : document.getNotes()) {
          if (note.getAttachment() != null) {
            hasAttachment = true;
            break;
          }
        }
        boolean isCGEnabled =
            getParameterService()
                .getParameterValueAsBoolean(
                    KFSConstants.CoreModuleNamespaces.CHART,
                    KFSConstants.RouteLevelNames.ACCOUNT,
                    KFSConstants.ChartApcParms.ACCOUNT_FUND_GROUP_DENOTES_CG);
        if (isCGEnabled) {
          for (TemExpense expense : allExpenses) {
            if (expense.getExpenseTypeCode().equals(TemConstants.ExpenseTypes.AIRFARE)) {
              Map<String, Object> fieldValues = new HashMap<String, Object>();
              fieldValues.put(KRADPropertyConstants.CODE, TemConstants.ExpenseTypes.AIRFARE);
              fieldValues.put(KRADPropertyConstants.NAME, expense.getTravelCompanyCodeName());
              TravelCompanyCode travelCompany =
                  getBusinessObjectService().findByPrimaryKey(TravelCompanyCode.class, fieldValues);
              if (travelCompany != null && travelCompany.isForeignCompany()) {
                String financialObjectCode =
                    expense.getExpenseTypeObjectCode() != null
                        ? expense.getExpenseTypeObjectCode().getFinancialObjectCode()
                        : null;
                if (travelDocument instanceof TravelAuthorizationDocument
                    && expense instanceof ActualExpense) {
                  if (document.getTripType() != null) {
                    financialObjectCode = document.getTripType().getEncumbranceObjCode();
                  }
                }
                if (financialObjectCode != null
                    && financialObjectCode.equals(line.getFinancialObjectCode())) {
                  String cg =
                      getParameterService()
                          .getParameterValueAsString(
                              KFSConstants.CoreModuleNamespaces.CHART,
                              KFSConstants.RouteLevelNames.ACCOUNT,
                              KFSConstants.ChartApcParms.ACCOUNT_CG_DENOTING_VALUE);
                  if (line.getAccount() == null) {
                    line.refreshReferenceObject(KFSPropertyConstants.ACCOUNT);
                  }
                  if (line.getAccount().getSubFundGroup() == null) {
                    line.refreshReferenceObject(KFSPropertyConstants.SUB_FUND_GROUP);
                  }
                  if (line.getAccount().getSubFundGroup().getFundGroupCode().equals(cg)) {
                    showFlyAmerica = true;
                  }
                }
              }
            }
          }
        }

        // Fly America error has been triggered, determine what accounting line to show it on.
        if (showFlyAmerica && !hasAttachment) {
          boolean newLine = true;
          for (TemSourceAccountingLine sourceLine :
              (List<TemSourceAccountingLine>) travelDocument.getSourceAccountingLines()) {
            if (line.equals(sourceLine)) {
              newLine = false;
            }
          }
          // if line is a new accounting line or a current one being saved/submitted in the
          // document.
          // figure out where the new accounting line will be added and set the error to that line #
          if (newLine) {
            GlobalVariables.getMessageMap().clearErrorPath();

            int newIndex =
                document
                        .getSourceAccountingLine(document.getSourceAccountingLines().size() - 1)
                        .getSequenceNumber()
                    + 1;
            errorPath =
                "document." + TemPropertyConstants.SOURCE_ACCOUNTING_LINE + "[" + newIndex + "]";
            GlobalVariables.getMessageMap().addToErrorPath(errorPath);
          }

          GlobalVariables.getMessageMap()
              .putError(
                  KFSPropertyConstants.ACCOUNT_NUMBER, TemKeyConstants.ERROR_ACCOUNTING_LINE_CG);
        }
      }
    }

    GlobalVariables.getMessageMap().clearErrorPath();
    GlobalVariables.getMessageMap().getErrorPath().addAll(holdErrors);

    return valid;
  }