/**
   * @param includeWorkflowHeaders
   * @return
   */
  public Collection<CustomerInvoiceDocument> getAllOpenCustomerInvoiceDocuments(
      boolean includeWorkflowHeaders) {
    Collection<CustomerInvoiceDocument> invoices = new ArrayList<CustomerInvoiceDocument>();

    // retrieve the set of documents without workflow headers
    invoices = customerInvoiceDocumentDao.getAllOpen();

    // if we dont need workflow headers, then we're done
    if (!includeWorkflowHeaders) {
      return invoices;
    }

    // make a list of necessary workflow docs to retrieve
    List<String> documentHeaderIds = new ArrayList<String>();
    for (CustomerInvoiceDocument invoice : invoices) {
      documentHeaderIds.add(invoice.getDocumentNumber());
    }

    // get all of our docs with full workflow headers
    List<CustomerInvoiceDocument> docs = new ArrayList<CustomerInvoiceDocument>();
    try {
      for (Document doc :
          documentService.getDocumentsByListOfDocumentHeaderIds(
              CustomerInvoiceDocument.class, documentHeaderIds)) {
        docs.add((CustomerInvoiceDocument) doc);
      }
    } catch (WorkflowException e) {
      throw new RuntimeException("Unable to retrieve Customer Invoice Documents", e);
    }

    return docs;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getCustomerInvoiceDocumentsByBillingChartAndOrg(java.lang.String,
   *     java.lang.String)
   */
  @Override
  public List<CustomerInvoiceDocument> getCustomerInvoiceDocumentsByBillingChartAndOrg(
      String chartOfAccountsCode, String organizationCode) {
    List<String> documentHeaderIds =
        customerInvoiceDocumentDao.getCustomerInvoiceDocumentNumbersByBillingChartAndOrg(
            chartOfAccountsCode, organizationCode);

    return getCustomerInvoiceDocumentsByDocumentNumbers(documentHeaderIds);
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getAllAgingInvoiceDocumentsByProcessing(java.util.List,
   *     java.util.List, java.lang.Integer)
   */
  @Override
  public Collection<CustomerInvoiceDocument> getAllAgingInvoiceDocumentsByProcessing(
      List<String> charts, List<String> organizations, Integer invoiceAge) {
    Date invoiceBillingDateFrom = null;
    Date invoiceBillingDateTo = this.getPastDate(invoiceAge - 1);

    return customerInvoiceDocumentDao.getAllAgingInvoiceDocumentsByProcessing(
        charts, organizations, invoiceBillingDateFrom, invoiceBillingDateTo);
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getAllAgingInvoiceDocumentsByCustomerTypes(java.util.List,
   *     java.lang.Integer, java.sql.Date)
   */
  @Override
  public Collection<CustomerInvoiceDocument> getAllAgingInvoiceDocumentsByCustomerTypes(
      List<String> customerTypes, Integer invoiceAge, Date invoiceDueDateFrom) {
    Date pastDate = this.getPastDate(invoiceAge - 1);
    Date invoiceDueDateTo = KfsDateUtils.convertToSqlDate(DateUtils.addDays(pastDate, 1));
    LOG.info("invoiceDueDateTo" + invoiceDueDateTo);

    return customerInvoiceDocumentDao.getAllAgingInvoiceDocumentsByCustomerTypes(
        customerTypes, invoiceDueDateFrom, invoiceDueDateTo);
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getOpenInvoiceDocumentsByCustomerType(java.lang.String)
   */
  @Override
  public Collection<CustomerInvoiceDocument> getOpenInvoiceDocumentsByCustomerType(
      String customerTypeCode) {
    Collection<CustomerInvoiceDocument> invoices = new ArrayList<CustomerInvoiceDocument>();

    // trim and force-caps
    customerTypeCode = customerTypeCode.trim().toUpperCase();

    invoices.addAll(customerInvoiceDocumentDao.getOpenByCustomerType(customerTypeCode));
    return invoices;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getOpenInvoiceDocumentsByCustomerNumber(java.lang.String)
   */
  @Override
  public Collection<CustomerInvoiceDocument> getOpenInvoiceDocumentsByCustomerNumber(
      String customerNumber) {
    Collection<CustomerInvoiceDocument> invoices = new ArrayList<CustomerInvoiceDocument>();

    // customer number is not required to be populated, so we need to check that it's not null first
    if (StringUtils.isNotEmpty(customerNumber)) {
      // trim and force-caps the customer number
      customerNumber = customerNumber.trim().toUpperCase();
    }

    invoices.addAll(customerInvoiceDocumentDao.getOpenByCustomerNumber(customerNumber));
    return invoices;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getOpenInvoiceDocumentsByCustomerName(java.lang.String)
   */
  @Override
  public Collection<CustomerInvoiceDocument> getOpenInvoiceDocumentsByCustomerName(
      String customerName) {
    Collection<CustomerInvoiceDocument> invoices = new ArrayList<CustomerInvoiceDocument>();

    // trim and force-caps the customer name
    customerName =
        StringUtils.replace(
            customerName, KFSConstants.WILDCARD_CHARACTER, KFSConstants.PERCENTAGE_SIGN);
    customerName = customerName.trim();
    if (customerName.indexOf("%") < 0) {
      customerName += "%";
    }

    invoices.addAll(customerInvoiceDocumentDao.getOpenByCustomerName(customerName));
    return invoices;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getPrintableCustomerInvoiceDocumentsForBillingStatementByBillingChartAndOrg(java.lang.String,
   *     java.lang.String)
   */
  @Override
  public List<CustomerInvoiceDocument>
      getPrintableCustomerInvoiceDocumentsForBillingStatementByBillingChartAndOrg(
          String chartOfAccountsCode, String organizationCode) {
    List<String> documentHeaderIds =
        customerInvoiceDocumentDao
            .getPrintableCustomerInvoiceDocumentNumbersForBillingStatementByBillingChartAndOrg(
                chartOfAccountsCode, organizationCode);

    List<CustomerInvoiceDocument> customerInvoiceDocuments =
        new ArrayList<CustomerInvoiceDocument>();
    if (documentHeaderIds != null && !documentHeaderIds.isEmpty()) {
      try {
        for (Document doc :
            documentService.getDocumentsByListOfDocumentHeaderIds(
                CustomerInvoiceDocument.class, documentHeaderIds)) {
          customerInvoiceDocuments.add((CustomerInvoiceDocument) doc);
        }
      } catch (WorkflowException e) {
        throw new InfrastructureException("Unable to retrieve Customer Invoice Documents", e);
      }
    }
    return customerInvoiceDocuments;
  }
  /**
   * @see
   *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getPrintableCustomerInvoiceDocumentsByInitiatorPrincipalName(java.lang.String)
   */
  @Override
  public List<CustomerInvoiceDocument> getPrintableCustomerInvoiceDocumentsByInitiatorPrincipalName(
      String initiatorPrincipalName) {
    if (StringUtils.isBlank(initiatorPrincipalName)) {
      throw new IllegalArgumentException(
          "The parameter [initiatorPrincipalName] passed in was null or blank.");
    }

    // IMPORTANT NOTES ABOUT THIS METHOD
    //
    // This method behaves differently than the other invoice printing methods. This is
    // because there's no way from within KFS to do a direct DB call to get all the invoices
    // you want. This is because workflow holds the document initiator, and you cant guarantee
    // that in a given implementation that you have access to that other db. It could be on
    // another box in another network, and you only have web-services access to the Rice box.
    //
    // Given that, we try to minimize the resource hit of this call as much as possible. First
    // we retrieve all invoices that havent been printed (ie, dont have a print date) and that
    // are marked for the USER print queue. At any given time that should be a manageable number of
    // documents.
    //
    // Then we walk through them, retrieve the full workflow-populated version of it, and only
    // return the ones that match the initiator.
    //
    // This isnt as performant a solution as the other getPrintableCustomerInvoiceBy...
    // methods, but its the best we can do in this release, and it should be manageable.

    //
    // attempt to retrieve the initiator person specified, and puke if not found
    Principal initiator =
        KimApiServiceLocator.getIdentityService()
            .getPrincipalByPrincipalName(initiatorPrincipalName);
    if (initiator == null) {
      throw new IllegalArgumentException(
          "The parameter value for initiatorPrincipalName ["
              + initiatorPrincipalName
              + "] passed in doesnt map to a person.");
    }

    // retrieve all the ready-to-print docs in the user-queue for all users
    List<String> printableUserQueueDocNumbers =
        customerInvoiceDocumentDao.getPrintableCustomerInvoiceDocumentNumbersFromUserQueue();

    // get all the documents that might be right, but this set includes documents generated
    // by the wrong user
    List<CustomerInvoiceDocument> customerInvoiceDocumentsSuperSet =
        new ArrayList<CustomerInvoiceDocument>();
    if (printableUserQueueDocNumbers.size() > 0) {
      try {
        for (Document doc :
            documentService.getDocumentsByListOfDocumentHeaderIds(
                CustomerInvoiceDocument.class, printableUserQueueDocNumbers)) {
          customerInvoiceDocumentsSuperSet.add((CustomerInvoiceDocument) doc);
        }
      } catch (WorkflowException e) {
        throw new RuntimeException("Unable to retrieve Customer Invoice Documents", e);
      }
    } else {
      customerInvoiceDocumentsSuperSet = new ArrayList<CustomerInvoiceDocument>();
    }

    // filter only the ones initiated by the correct user
    List<CustomerInvoiceDocument> customerInvoiceDocuments =
        new ArrayList<CustomerInvoiceDocument>();
    for (CustomerInvoiceDocument superSetDocument : customerInvoiceDocumentsSuperSet) {
      if (StringUtils.equalsIgnoreCase(
          superSetDocument.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId(),
          initiator.getPrincipalId())) {
        customerInvoiceDocuments.add(superSetDocument);
      }
    }
    return customerInvoiceDocuments;
  }
 /**
  * @see
  *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getInvoiceByInvoiceDocumentNumber(java.lang.String)
  */
 @Override
 public CustomerInvoiceDocument getInvoiceByInvoiceDocumentNumber(String invoiceDocumentNumber) {
   return customerInvoiceDocumentDao.getInvoiceByInvoiceDocumentNumber(invoiceDocumentNumber);
 }
 /**
  * @see
  *     org.kuali.kfs.module.ar.document.service.CustomerInvoiceDocumentService#getInvoiceByOrganizationInvoiceNumber(java.lang.String)
  */
 @Override
 public CustomerInvoiceDocument getInvoiceByOrganizationInvoiceNumber(
     String organizationInvoiceNumber) {
   return customerInvoiceDocumentDao.getInvoiceByOrganizationInvoiceNumber(
       organizationInvoiceNumber);
 }