/**
  * This method calculates the total credits for the customers.
  *
  * @param cgMapByCustomer
  * @param knownCustomers
  */
 private void calculateTotalCreditsForCustomers(
     Map<String, List<ContractsGrantsInvoiceDocument>> cgMapByCustomer,
     Map<String, ContractsAndGrantsAgingReport> knownCustomers) {
   Set<String> customerIds = cgMapByCustomer.keySet();
   KualiDecimal credits = KualiDecimal.ZERO;
   for (String customer : customerIds) {
     ContractsAndGrantsAgingReport agingReportDetail =
         pickContractsGrantsAgingReportDetail(knownCustomers, customer);
     List<ContractsGrantsInvoiceDocument> cgDocs = cgMapByCustomer.get(customer);
     if (ObjectUtils.isNotNull(cgDocs) && !cgDocs.isEmpty()) {
       credits = KualiDecimal.ZERO;
       for (ContractsGrantsInvoiceDocument cgDoc : cgDocs) {
         Collection<CustomerCreditMemoDocument> creditDocs =
             customerCreditMemoDocumentService.getCustomerCreditMemoDocumentByInvoiceDocument(
                 cgDoc.getDocumentNumber());
         if (ObjectUtils.isNotNull(creditDocs) && !creditDocs.isEmpty()) {
           for (CustomerCreditMemoDocument cm : creditDocs) {
             for (CustomerCreditMemoDetail cmDetail : cm.getCreditMemoDetails()) {
               credits = credits.add(cmDetail.getCreditMemoItemTotalAmount());
             }
           }
         }
       }
     }
     agingReportDetail.setTotalCredits(credits);
     totalCredits = totalCredits.add(credits);
   }
 }
 /** @return a List of the CustomerInvoiceDetails associated with a given Account Number */
 @SuppressWarnings("unchecked")
 public Collection<ContractsGrantsInvoiceDocument> filterContractsGrantsDocsAccordingToAward(
     Collection<ContractsGrantsInvoiceDocument> contractsGrantsInvoiceDocs,
     String awardDocumentNumber,
     java.sql.Date awardEndDate,
     String fundManager) {
   if (ObjectUtils.isNotNull(contractsGrantsInvoiceDocs)
       && !contractsGrantsInvoiceDocs.isEmpty()) {
     for (Iterator iter = contractsGrantsInvoiceDocs.iterator(); iter.hasNext(); ) {
       boolean considerAwardDocNumber =
           (ObjectUtils.isNotNull(awardDocumentNumber)
                   && !StringUtils.isEmpty(awardDocumentNumber))
               ? false
               : true;
       boolean considerFundMngr =
           (ObjectUtils.isNotNull(fundManager) && !StringUtils.isEmpty(fundManager))
               ? false
               : true;
       boolean considerAwardEndDate = (ObjectUtils.isNotNull(awardEndDate)) ? false : true;
       ContractsGrantsInvoiceDocument document = (ContractsGrantsInvoiceDocument) iter.next();
       considerAwardDocNumber =
           !considerAwardDocNumber
               ? awardDocumentNumber.equals(document.getAward().getAwardDocumentNumber())
               : considerAwardDocNumber;
       considerAwardEndDate =
           !considerAwardEndDate
               ? awardEndDate.getTime() == document.getAward().getAwardEndingDate().getTime()
               : considerAwardEndDate;
       considerFundMngr =
           !considerFundMngr
               ? fundManager.equals(
                   document.getAward().getAwardPrimaryFundManager().getPrincipalId())
               : considerFundMngr;
       if (!(considerAwardDocNumber && considerFundMngr && considerAwardEndDate)) {
         iter.remove();
       }
     }
   }
   return contractsGrantsInvoiceDocs;
 }
 protected void getEmailParameterList(
     Map<String, String> primaryKeys,
     ContractsGrantsInvoiceDocument invoice,
     CustomerAddress customerAddress) {
   String[] orgCode =
       invoice
           .getAward()
           .getAwardPrimaryFundManager()
           .getFundManager()
           .getPrimaryDepartmentCode()
           .split("-");
   Map<String, Object> key = new HashMap<String, Object>();
   key.put(KFSPropertyConstants.ORGANIZATION_CODE, orgCode[0].trim());
   key.put(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, orgCode[1].trim());
   Organization org = businessObjectService.findByPrimaryKey(Organization.class, key);
   primaryKeys.put(
       "grantNumber", returnProperStringValue(invoice.getAward().getProposal().getGrantNumber()));
   primaryKeys.put("proposalNumber", returnProperStringValue(invoice.getProposalNumber()));
   primaryKeys.put("invoiceNumber", returnProperStringValue(invoice.getDocumentNumber()));
   primaryKeys.put(
       "customerName", returnProperStringValue(customerAddress.getCustomer().getCustomerName()));
   primaryKeys.put(
       "addressName", returnProperStringValue(customerAddress.getCustomerAddressName()));
   primaryKeys.put(
       "name",
       returnProperStringValue(
           invoice.getAward().getAwardPrimaryFundManager().getFundManager().getName()));
   primaryKeys.put(
       "title",
       returnProperStringValue(
           invoice.getAward().getAwardPrimaryFundManager().getAwardFundManagerProjectTitle()));
   if (ObjectUtils.isNotNull(org)) {
     primaryKeys.put("department", returnProperStringValue(org.getOrganizationName()));
   }
   primaryKeys.put(
       "phone",
       returnProperStringValue(
           invoice.getAward().getAwardPrimaryFundManager().getFundManager().getPhoneNumber()));
   primaryKeys.put(
       "email",
       returnProperStringValue(
           invoice.getAward().getAwardPrimaryFundManager().getFundManager().getEmailAddress()));
 }
 /**
  * This method calculates the payment amount for the customers.
  *
  * @param cgDocs
  * @param begin
  * @param end
  * @return
  */
 private KualiDecimal calculatePaymentAmountForCustomer(
     Collection<ContractsGrantsInvoiceDocument> cgDocs, java.sql.Date begin, java.sql.Date end) {
   KualiDecimal invoiceAmt = KualiDecimal.ZERO;
   if (ObjectUtils.isNotNull(cgDocs) && !cgDocs.isEmpty()) {
     for (ContractsGrantsInvoiceDocument cgDoc : cgDocs) {
       if (ObjectUtils.isNotNull(cgDoc.getBillingDate())) {
         if (ObjectUtils.isNotNull(begin)) {
           if (cgDoc.getBillingDate().compareTo(begin) >= 0
               && cgDoc.getBillingDate().compareTo(end) <= 0) {
             invoiceAmt = invoiceAmt.add(cgDoc.getPaymentAmount());
           }
         } else {
           if (cgDoc.getBillingDate().compareTo(end) <= 0) {
             invoiceAmt = invoiceAmt.add(cgDoc.getPaymentAmount());
           }
         }
       }
     }
   }
   return invoiceAmt;
 }
  /**
   * This method prepare the report model object to display on jsp page.
   *
   * @param invoices
   * @param results
   */
  protected void populateReportDetails(
      List<ContractsGrantsInvoiceDocument> invoices, List results) {
    for (ContractsGrantsInvoiceDocument invoice : invoices) {
      ContractsGrantsAgingOpenInvoicesReport detail = new ContractsGrantsAgingOpenInvoicesReport();
      // Document Type
      detail.setDocumentType(
          invoice.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
      // Document Number
      detail.setDocumentNumber(invoice.getDocumentNumber());
      // Document Description
      String documentDescription = invoice.getDocumentHeader().getDocumentDescription();
      if (ObjectUtils.isNotNull(documentDescription)) {
        detail.setDocumentDescription(documentDescription);
      } else {
        detail.setDocumentDescription("");
      }
      // Billing Date
      detail.setBillingDate(invoice.getBillingDate());
      // Due Date
      detail.setDueApprovedDate(invoice.getInvoiceDueDate());
      // Document Payment Amount
      detail.setDocumentPaymentAmount(
          invoice.getFinancialSystemDocumentHeader().getFinancialDocumentTotalAmount());
      // Unpaid/Unapplied Amount
      detail.setUnpaidUnappliedAmount(
          customerInvoiceDocumentService.getOpenAmountForCustomerInvoiceDocument(invoice));
      detail.setFinalInvoice(
          !ObjectUtils.isNull(invoice.getInvoiceGeneralDetail())
                  && invoice.getInvoiceGeneralDetail().isFinalBillIndicator()
              ? KFSConstants.ParameterValues.STRING_YES
              : KFSConstants.ParameterValues.STRING_NO);
      // set agency number, proposal number, account number
      if (!ObjectUtils.isNull(invoice.getInvoiceGeneralDetail())
          && !ObjectUtils.isNull(invoice.getInvoiceGeneralDetail().getProposalNumber())) {
        detail.setProposalNumber(invoice.getInvoiceGeneralDetail().getProposalNumber().toString());
      }

      // Set Agency Number
      ContractsAndGrantsBillingAgency cgAgency =
          this.getAgencyByCustomer(
              invoice.getAccountsReceivableDocumentHeader().getCustomerNumber());
      if (ObjectUtils.isNotNull(cgAgency)) {
        detail.setAgencyNumber(cgAgency.getAgencyNumber());
      }

      // Set Account number
      List<CustomerInvoiceDetail> details = invoice.getSourceAccountingLines();
      String accountNum =
          (CollectionUtils.isNotEmpty(details) && ObjectUtils.isNotNull(details.get(0)))
              ? details.get(0).getAccountNumber()
              : "";
      detail.setAccountNumber(accountNum);
      results.add(detail);
    }
  }
  /**
   * 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);
    }
  }
  /**
   * This method performs the lookup and returns a collection of lookup items
   *
   * @param lookupForm
   * @param kualiLookupable
   * @param resultTable
   * @param bounded
   * @return
   */
  @Override
  public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
    Collection<BusinessObject> displayList;

    // Call search method to get results - always use unbounded to get the entire set of results.

    displayList =
        (Collection<BusinessObject>) getSearchResultsUnbounded(lookupForm.getFieldsForLookup());

    List pkNames =
        getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
    List returnKeys = getReturnKeys();
    Person user = GlobalVariables.getUserSession().getPerson();

    // Iterate through result list and wrap rows with return url and action urls
    for (BusinessObject element : displayList) {
      LOG.debug("Doing lookup for " + element.getClass());

      ReferralToCollectionsLookupResult result = ((ReferralToCollectionsLookupResult) element);
      List<String> invoiceAttributesForDisplay = result.getInvoiceAttributesForDisplay();

      BusinessObjectRestrictions businessObjectRestrictions =
          getBusinessObjectAuthorizationService().getLookupResultRestrictions(result, user);
      // add list of awards to sub Result rows
      List<ResultRow> subResultRows = new ArrayList<ResultRow>();
      for (ContractsGrantsInvoiceDocument invoice : result.getInvoices()) {

        List<Column> subResultColumns = new ArrayList<Column>();
        InvoiceAccountDetail firstInvoiceAccountDetail = new InvoiceAccountDetail();

        // Set first invoice account detail
        if (CollectionUtils.isNotEmpty(invoice.getAccountDetails())) {
          firstInvoiceAccountDetail = invoice.getAccountDetails().get(0);
        }

        for (String propertyName : invoiceAttributesForDisplay) {
          if (propertyName.equalsIgnoreCase(KFSPropertyConstants.ACCOUNT_NUMBER)) {
            Account account =
                SpringContext.getBean(AccountService.class)
                    .getByPrimaryId(
                        firstInvoiceAccountDetail.getChartOfAccountsCode(),
                        firstInvoiceAccountDetail.getAccountNumber());
            subResultColumns.add(
                setupResultsColumn(account, propertyName, businessObjectRestrictions));
          } else {
            subResultColumns.add(
                setupResultsColumn(invoice, propertyName, businessObjectRestrictions));
          }
        }

        ResultRow subResultRow = new ResultRow(subResultColumns, "", "");
        subResultRow.setObjectId(((PersistableBusinessObjectBase) invoice).getObjectId());
        subResultRows.add(subResultRow);
      }

      // Create main customer header row
      Collection<Column> columns = getColumns(element, businessObjectRestrictions);
      HtmlData returnUrl =
          getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
      ReferralToCollectionsResultRow row =
          new ReferralToCollectionsResultRow(
              (List<Column>) columns,
              subResultRows,
              returnUrl.constructCompleteHtmlTag(),
              getActionUrls(element, pkNames, businessObjectRestrictions));
      resultTable.add(row);
    }

    return displayList;
  }