/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.ar.document.dataaccess.impl; import java.sql.Date; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.ojb.broker.query.Criteria; import org.apache.ojb.broker.query.Query; import org.apache.ojb.broker.query.QueryByCriteria; import org.apache.ojb.broker.query.QueryFactory; import org.apache.ojb.broker.query.ReportQueryByCriteria; import org.kuali.kfs.module.ar.ArConstants; import org.kuali.kfs.module.ar.ArPropertyConstants; import org.kuali.kfs.module.ar.businessobject.CustomerInvoiceDetail; import org.kuali.kfs.module.ar.document.CustomerInvoiceDocument; import org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb; import org.kuali.rice.krad.util.ObjectUtils; public class CustomerInvoiceDocumentDaoOjb extends PlatformAwareDaoBaseOjb implements CustomerInvoiceDocumentDao { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CustomerInvoiceDocumentDaoOjb.class); @Override public List<String> getPrintableCustomerInvoiceDocumentNumbersFromUserQueue() { Criteria criteria = new Criteria(); criteria.addEqualTo("printInvoiceIndicator", ArConstants.PrintInvoiceOptions.PRINT_BY_USER); criteria.addIsNull("printDate"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); // Why use the OJB reports approach here, rather than a list of CustomerInvoiceDocuments? // // This was done because even if we had the invoice documents, we then need to do a proper document load // via the documentService, which loads up the workflow information as well and properly prepares the document. // // Therefore, at this stage, there's no reason to load entire documents, all we need are document numbers. And with // OJB, this is how you get just a collection of a single column's value out. Given the performance issues associated // with live reporting like this, the attempt was made to minimize the resource usage. ReportQueryByCriteria rqbc = QueryFactory.newReportQuery(CustomerInvoiceDocument.class, new String[] { "documentNumber" }, criteria, false); Iterator<Object[]> iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); List<String> invoiceNumbers = new ArrayList<String>(); while (iter.hasNext()) { invoiceNumbers.add((String)iter.next()[0]); } return invoiceNumbers; } @Override public List<String> getPrintableCustomerInvoiceDocumentNumbersByProcessingChartAndOrg(String chartOfAccountsCode, String organizationCode) { if (StringUtils.isBlank(chartOfAccountsCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank chartOfAccountsCode parameter."); } if (StringUtils.isBlank(organizationCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank organizationCode parameter."); } // Why use the OJB reports approach here, rather than a list of CustomerInvoiceDocuments? // // This was done because even if we had the invoice documents, we then need to do a proper document load // via the documentService, which loads up the workflow information as well and properly prepares the document. // // Therefore, at this stage, there's no reason to load entire documents, all we need are document numbers. And with // OJB, this is how you get just a collection of a single column's value out. Given the performance issues associated // with live reporting like this, the attempt was made to minimize the resource usage. // select i.fdoc_nbr // from ar_doc_hdr_t h inner join ar_inv_doc_t i // on h.fdoc_nbr = i.fdoc_nbr // where h.prcs_fin_coa_cd = ? and h.prcs_org_cd = ? Criteria criteria = new Criteria(); criteria.addEqualTo("accountsReceivableDocumentHeader.processingChartOfAccountCode", chartOfAccountsCode); criteria.addEqualTo("accountsReceivableDocumentHeader.processingOrganizationCode", organizationCode); criteria.addEqualTo("printInvoiceIndicator", ArConstants.PrintInvoiceOptions.PRINT_BY_PROCESSING_ORG); criteria.addIsNull("printDate"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); ReportQueryByCriteria rqbc = QueryFactory.newReportQuery(CustomerInvoiceDocument.class, new String[] { "documentNumber" }, criteria, false); Iterator<Object[]> iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); List<String> invoiceNumbers = new ArrayList<String>(); while (iter.hasNext()) { invoiceNumbers.add((String)iter.next()[0]); } return new ArrayList<String>(invoiceNumbers); } @Override public List<String> getPrintableCustomerInvoiceDocumentNumbersByBillingChartAndOrg(String chartOfAccountsCode, String organizationCode) { if (StringUtils.isBlank(chartOfAccountsCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank chartOfAccountsCode parameter."); } if (StringUtils.isBlank(organizationCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank organizationCode parameter."); } // Why use the OJB reports approach here, rather than a list of CustomerInvoiceDocuments? // // This was done because even if we had the invoice documents, we then need to do a proper document load // via the documentService, which loads up the workflow information as well and properly prepares the document. // // Therefore, at this stage, there's no reason to load entire documents, all we need are document numbers. And with // OJB, this is how you get just a collection of a single column's value out. Given the performance issues associated // with live reporting like this, the attempt was made to minimize the resource usage. Criteria criteria = new Criteria(); criteria.addEqualTo("billByChartOfAccountCode", chartOfAccountsCode); criteria.addEqualTo("billedByOrganizationCode", organizationCode); criteria.addEqualTo("printInvoiceIndicator", ArConstants.PrintInvoiceOptions.PRINT_BY_BILLING_ORG); criteria.addIsNull("printDate"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); ReportQueryByCriteria rqbc = QueryFactory.newReportQuery(CustomerInvoiceDocument.class, new String[] { "documentNumber" }, criteria, false); Iterator<Object[]> iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); List<String> invoiceNumbers = new ArrayList<String>(); while (iter.hasNext()) { invoiceNumbers.add((String)iter.next()[0]); } return new ArrayList<String>(invoiceNumbers); } /** * Very similar to above except lacks check for print invoice indicator and print date. * * @see org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao#getPrintableCustomerInvoiceDocumentNumbersForBillingStatementByBillingChartAndOrg(java.lang.String, java.lang.String) */ @Override public List<String> getPrintableCustomerInvoiceDocumentNumbersForBillingStatementByBillingChartAndOrg(String chartOfAccountsCode, String organizationCode) { if (StringUtils.isBlank(chartOfAccountsCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank chartOfAccountsCode parameter."); } if (StringUtils.isBlank(organizationCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank organizationCode parameter."); } // Why use the OJB reports approach here, rather than a list of CustomerInvoiceDocuments? // // This was done because even if we had the invoice documents, we then need to do a proper document load // via the documentService, which loads up the workflow information as well and properly prepares the document. // // Therefore, at this stage, there's no reason to load entire documents, all we need are document numbers. And with // OJB, this is how you get just a collection of a single column's value out. Given the performance issues associated // with live reporting like this, the attempt was made to minimize the resource usage. Criteria criteria = new Criteria(); criteria.addEqualTo("billByChartOfAccountCode", chartOfAccountsCode); criteria.addEqualTo("billedByOrganizationCode", organizationCode); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); ReportQueryByCriteria rqbc = QueryFactory.newReportQuery(CustomerInvoiceDocument.class, new String[] { "documentNumber" }, criteria, false); Iterator<Object[]> iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); List<String> invoiceNumbers = new ArrayList<String>(); while (iter.hasNext()) { invoiceNumbers.add((String)iter.next()[0]); } return new ArrayList<String>(invoiceNumbers); } @Override public List<String> getCustomerInvoiceDocumentNumbersByProcessingChartAndOrg(String chartOfAccountsCode, String organizationCode) { if (StringUtils.isBlank(chartOfAccountsCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank chartOfAccountsCode parameter."); } if (StringUtils.isBlank(organizationCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank organizationCode parameter."); } // Why use the OJB reports approach here, rather than a list of CustomerInvoiceDocuments? // // This was done because even if we had the invoice documents, we then need to do a proper document load // via the documentService, which loads up the workflow information as well and properly prepares the document. // // Therefore, at this stage, there's no reason to load entire documents, all we need are document numbers. And with // OJB, this is how you get just a collection of a single column's value out. Given the performance issues associated // with live reporting like this, the attempt was made to minimize the resource usage. // select i.fdoc_nbr // from ar_doc_hdr_t h inner join ar_inv_doc_t i // on h.fdoc_nbr = i.fdoc_nbr // where h.prcs_fin_coa_cd = ? and h.prcs_org_cd = ? Criteria criteria = new Criteria(); criteria.addEqualTo("accountsReceivableDocumentHeader.processingChartOfAccountCode", chartOfAccountsCode); criteria.addEqualTo("accountsReceivableDocumentHeader.processingOrganizationCode", organizationCode); ReportQueryByCriteria rqbc = QueryFactory.newReportQuery(CustomerInvoiceDocument.class, new String[] { "documentNumber" }, criteria, false); Iterator<Object[]> iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); List<String> invoiceNumbers = new ArrayList<String>(); while (iter.hasNext()) { invoiceNumbers.add((String)iter.next()[0]); } return new ArrayList<String>(invoiceNumbers); } @Override public List<String> getCustomerInvoiceDocumentNumbersByBillingChartAndOrg(String chartOfAccountsCode, String organizationCode) { if (StringUtils.isBlank(chartOfAccountsCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank chartOfAccountsCode parameter."); } if (StringUtils.isBlank(organizationCode)) { throw new IllegalArgumentException("The method was called with a Null or Blank organizationCode parameter."); } // Why use the OJB reports approach here, rather than a list of CustomerInvoiceDocuments? // // This was done because even if we had the invoice documents, we then need to do a proper document load // via the documentService, which loads up the workflow information as well and properly prepares the document. // // Therefore, at this stage, there's no reason to load entire documents, all we need are document numbers. And with // OJB, this is how you get just a collection of a single column's value out. Given the performance issues associated // with live reporting like this, the attempt was made to minimize the resource usage. Criteria criteria = new Criteria(); criteria.addEqualTo("billByChartOfAccountCode", chartOfAccountsCode); criteria.addEqualTo("billedByOrganizationCode", organizationCode); ReportQueryByCriteria rqbc = QueryFactory.newReportQuery(CustomerInvoiceDocument.class, new String[] { "documentNumber" }, criteria, false); Iterator<Object[]> iter = getPersistenceBrokerTemplate().getReportQueryIteratorByQuery(rqbc); List<String> invoiceNumbers = new ArrayList<String>(); while (iter.hasNext()) { invoiceNumbers.add((String)iter.next()[0]); } return new ArrayList<String>(invoiceNumbers); } @Override public Collection getAllOpen() { Criteria criteria = new Criteria(); criteria.addEqualTo("openInvoiceIndicator", true); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); QueryByCriteria qbc = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); Collection customerinvoicedocuments = getPersistenceBrokerTemplate().getCollectionByQuery(qbc); List invoiceList = new ArrayList(customerinvoicedocuments); return invoiceList; } @Override public Collection getOpenByCustomerNumber(String customerNumber) { // select i.* // from ar_doc_hdr_t h inner join ar_inv_doc_t i // on h.fdoc_nbr = i.fdoc_nbr // where h.cust_nbr = ? // OJB deals with the inner join automatically, because we have it setup with // accountsReceivableDocumentHeader as a ReferenceDescriptor to Invoice. Criteria criteria = new Criteria(); criteria.addEqualTo("accountsReceivableDocumentHeader.customerNumber", customerNumber==null?customerNumber:customerNumber.toUpperCase()); criteria.addEqualTo("openInvoiceIndicator", "true"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); QueryByCriteria qbc = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); Collection customerinvoicedocuments = getPersistenceBrokerTemplate().getCollectionByQuery(qbc); List invoiceList = new ArrayList(customerinvoicedocuments); return invoiceList; } @Override public Collection getOpenByCustomerNameByCustomerType(String customerName, String customerTypeCode) { // select i.* // from ar_doc_hdr_t h inner join ar_inv_doc_t i // on h.fdoc_nbr = i.fdoc_nbr // inner join ar_cust_t c // on h.cust_nbr = c.cust_nbr // where c.cust_nm like ? and c.cust_typ_cd = ? Criteria criteria = new Criteria(); criteria.addLike("accountsReceivableDocumentHeader.customer.customerName", customerName); criteria.addEqualTo("accountsReceivableDocumentHeader.customer.customerTypeCode", customerTypeCode); criteria.addEqualTo("openInvoiceIndicator", "true"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); QueryByCriteria qbc = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); Collection customerinvoicedocuments = getPersistenceBrokerTemplate().getCollectionByQuery(qbc); List invoiceList = new ArrayList(customerinvoicedocuments); return invoiceList; } @Override public Collection getOpenByCustomerName(String customerName) { // select i.* // from ar_doc_hdr_t h inner join ar_inv_doc_t i // on h.fdoc_nbr = i.fdoc_nbr // inner join ar_cust_t c // on h.cust_nbr = c.cust_nbr // where c.cust_nm like ? Criteria criteria = new Criteria(); criteria.addLike("accountsReceivableDocumentHeader.customer.customerName", customerName); criteria.addEqualTo("openInvoiceIndicator", "true"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); QueryByCriteria qbc = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); Collection customerinvoicedocuments = getPersistenceBrokerTemplate().getCollectionByQuery(qbc); List invoiceList = new ArrayList(customerinvoicedocuments); return invoiceList; } @Override public Collection getOpenByCustomerType(String customerTypeCode) { // select i.* // from ar_doc_hdr_t h inner join ar_inv_doc_t i // on h.fdoc_nbr = i.fdoc_nbr // inner join ar_cust_t c // on h.cust_nbr = c.cust_nbr // where c.cust_typ_cd = ? // OJB deals with the inner join automatically, because we have it setup with // accountsReceivableDocumentHeader as a ReferenceDescriptor to Invoice, and Customer // as a referencedescriptor to accountsReceivableDocumentHeader. Criteria criteria = new Criteria(); criteria.addEqualTo("accountsReceivableDocumentHeader.customer.customerTypeCode", customerTypeCode); criteria.addEqualTo("openInvoiceIndicator", "true"); criteria.addEqualTo("documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); QueryByCriteria qbc = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); Collection customerinvoicedocuments = getPersistenceBrokerTemplate().getCollectionByQuery(qbc); List invoiceList = new ArrayList(customerinvoicedocuments); return invoiceList; } /** * @see org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao#getInvoiceByOrganizationInvoiceNumber(java.lang.String) */ @Override public CustomerInvoiceDocument getInvoiceByOrganizationInvoiceNumber(String organizationInvoiceNumber) { Criteria criteria = new Criteria(); criteria.addEqualTo("organizationInvoiceNumber", organizationInvoiceNumber); return (CustomerInvoiceDocument) getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria)); } /** * @see org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao#getInvoiceByInvoiceDocumentNumber(java.lang.String) */ @Override public CustomerInvoiceDocument getInvoiceByInvoiceDocumentNumber(String documentNumber) { Criteria criteria = new Criteria(); criteria.addEqualTo("documentNumber", documentNumber); return (CustomerInvoiceDocument) getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria)); } /** * @see org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao#getAllAgingInvoiceDocumentsByBilling(java.util.List, java.util.List, java.sql.Date, java.sql.Date) */ @Override public Collection<CustomerInvoiceDocument> getAllAgingInvoiceDocumentsByBilling(List<String> charts, List<String> organizations, Date invoiceBillingDateFrom, Date invoiceBillingDateTo) { Criteria criteria = this.getAllAgingInvoiceDocumentsCriteria(StringUtils.EMPTY, invoiceBillingDateFrom, invoiceBillingDateTo); if(ObjectUtils.isNotNull(charts)){ criteria.addIn(ArPropertyConstants.CustomerInvoiceDocumentFields.BILL_BY_CHART_OF_ACCOUNT_CODE, charts); } if(ObjectUtils.isNotNull(organizations)){ criteria.addIn(ArPropertyConstants.CustomerInvoiceDocumentFields.BILLED_BY_ORGANIZATION_CODE, organizations); } criteria.addIsNull(ArPropertyConstants.AGING_REPORT_SENT_TIME); Query query = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); return getPersistenceBrokerTemplate().getCollectionByQuery(query); } /** * @see org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao#getAllAgingInvoiceDocumentsByProcessing(java.util.List, java.util.List, java.sql.Date, java.sql.Date) */ @Override public Collection<CustomerInvoiceDocument> getAllAgingInvoiceDocumentsByProcessing(List<String> charts, List<String> organizations, Date invoiceBillingDateFrom, Date invoiceBillingDateTo) { Criteria criteria = this.getAllAgingInvoiceDocumentsCriteria(StringUtils.EMPTY, invoiceBillingDateFrom, invoiceBillingDateTo); if(ObjectUtils.isNotNull(charts) && !charts.isEmpty()){ criteria.addIn(ArPropertyConstants.CustomerInvoiceDocumentFields.PROCESSING_CHART_OF_ACCOUNT_CODE, charts); } if(ObjectUtils.isNotNull(organizations) && !organizations.isEmpty()){ criteria.addIn(ArPropertyConstants.CustomerInvoiceDocumentFields.PROCESSING_ORGANIZATION_CODE, organizations); } criteria.addIsNull(ArPropertyConstants.AGING_REPORT_SENT_TIME); Query query = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); return getPersistenceBrokerTemplate().getCollectionByQuery(query); } /** * @see org.kuali.kfs.module.ar.document.dataaccess.CustomerInvoiceDocumentDao#getAllAgingInvoiceDocumentsByAccounts(java.util.List, java.util.List, java.sql.Date, java.sql.Date) */ @Override public Collection<CustomerInvoiceDocument> getAllAgingInvoiceDocumentsByAccounts(List<String> charts, List<String> accounts, Date invoiceBillingDateFrom, Date invoiceBillingDateTo) { Collection<CustomerInvoiceDocument> customerInvoiceDocuments = new ArrayList<CustomerInvoiceDocument>(); Criteria criteria = this.getAllAgingInvoiceDocumentsCriteria(ArPropertyConstants.CUSTOMER_INVOICE_DOCUMENT + ".", invoiceBillingDateFrom, invoiceBillingDateTo); if(ObjectUtils.isNotNull(charts)){ criteria.addIn(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE, charts); } if(ObjectUtils.isNotNull(accounts)){ criteria.addIn(KFSPropertyConstants.ACCOUNT_NUMBER, accounts); } criteria.addIsNull(ArPropertyConstants.AGING_REPORT_SENT_TIME); Query query = QueryFactory.newQuery(CustomerInvoiceDetail.class, criteria); Collection<CustomerInvoiceDetail> customerInvoiceDetails = getPersistenceBrokerTemplate().getCollectionByQuery(query); Set<String> invoiceDocumentNumbers = new HashSet<String>(); for(CustomerInvoiceDetail detail : customerInvoiceDetails){ CustomerInvoiceDocument customerInvoiceDocument = detail.getCustomerInvoiceDocument(); String documentNumber = customerInvoiceDocument.getDocumentNumber(); if(!invoiceDocumentNumbers.contains(documentNumber)){ customerInvoiceDocuments.add(customerInvoiceDocument); invoiceDocumentNumbers.add(documentNumber); } } return customerInvoiceDocuments; } /** * get selection criteria for aging invoice document */ protected Criteria getAllAgingInvoiceDocumentsCriteria(String prefix, Date invoiceDueDateFrom, Date invoiceDueDateTo) { Criteria criteria = new Criteria(); if(ObjectUtils.isNotNull(invoiceDueDateFrom)){ criteria.addGreaterOrEqualThan(ArPropertyConstants.CustomerInvoiceDocumentFields.INVOICE_DUE_DATE, invoiceDueDateFrom); } if(ObjectUtils.isNotNull(invoiceDueDateTo)){ criteria.addLessThan(ArPropertyConstants.CustomerInvoiceDocumentFields.INVOICE_DUE_DATE, invoiceDueDateTo); } criteria.addEqualTo(prefix + ArPropertyConstants.CustomerInvoiceDocumentFields.OPEN_INVOICE_INDICATOR, true); criteria.addEqualTo(prefix + "documentHeader.financialDocumentStatusCode", KFSConstants.DocumentStatusCodes.APPROVED); return criteria; } @Override public Collection<CustomerInvoiceDocument> getAllAgingInvoiceDocumentsByCustomerTypes(List<String> customerTypes, Date invoiceDueDateFrom, Date invoiceDueDateTo) { LOG.info("invoiceDueDateFrom :::::" + invoiceDueDateFrom); LOG.info("invoiceDueDateTo ::::::::" + invoiceDueDateTo); Criteria criteria = this.getAllAgingInvoiceDocumentsCriteria(StringUtils.EMPTY, invoiceDueDateFrom, invoiceDueDateTo); if(ObjectUtils.isNotNull(customerTypes)){ criteria.addIn(ArPropertyConstants.CustomerInvoiceDocumentFields.CUSTOMER_TYPE_CODE, customerTypes); } Query query = QueryFactory.newQuery(CustomerInvoiceDocument.class, criteria); return getPersistenceBrokerTemplate().getCollectionByQuery(query); } }