Guides

Sales Collections

Sales Collections work in the same way as Product Collections do. They enable you to organise Sales into specific collections.

Also, as with Product Collections & Customer Collections, you can create Dynamic collections.

Dynamic collections are used to display information based off commonly desired specific criteria. There are a number of dynamic sales collections which come with Merchello out of the box and serve as a great example of how to create a dynamic collection.

The out of the box dynamic collections are:

  • Unpaid invoices
  • Partially paid invoices
  • Paid invoices
  • Unfulfilled orders
  • Open orders
  • Fulfilled orders

Below is the code for the Unpaid Invoices dynamic collection, which you can use as a reference to create your own and also, part of the Merchello.config where you register your dynamic collection.

/// <summary>
    /// The unpaid invoice collection provider.
    /// </summary>
    [EntityCollectionProvider("A8120A01-E9BF-4204-ADDD-D9553F6F24FE", "454539B9-D753-4C16-8ED5-5EB659E56665", 
        "Unpaid Invoice Collection", "A dynamic collection queries for unpaid invoices", true, 
        "merchelloProviders/unpaidInvoiceCollection")]
    internal class DynamicUnpaidInvoiceCollectionProvider : CachedQueryableEntityCollectionProviderBase<IInvoice>
    {
        /// <summary>
        /// The <see cref="InvoiceService"/>.
        /// </summary>
        private readonly InvoiceService _invoiceService;

        /// <summary>
        /// Initializes a new instance of the <see cref="DynamicUnpaidInvoiceCollectionProvider"/> class.
        /// </summary>
        /// <param name="merchelloContext">
        /// The merchello context.
        /// </param>
        /// <param name="collectionKey">
        /// The collection key.
        /// </param>
        public DynamicUnpaidInvoiceCollectionProvider(IMerchelloContext merchelloContext, Guid collectionKey)
            : base(merchelloContext, collectionKey)
        {
            _invoiceService = (InvoiceService)merchelloContext.Services.InvoiceService;
        }

        /// <summary>
        /// Checks if the invoice exists in the collection
        /// </summary>
        /// <param name="entity">
        /// The entity.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        protected override bool PerformExists(IInvoice entity)
        {
            return entity.InvoiceStatusKey.Equals(Constants.DefaultKeys.InvoiceStatus.Unpaid);
        }

        /// <summary>
        /// The perform get paged entities.
        /// </summary>
        /// <param name="page">
        /// The page.
        /// </param>
        /// <param name="itemsPerPage">
        /// The items per page.
        /// </param>
        /// <param name="sortBy">
        /// The sort by.
        /// </param>
        /// <param name="sortDirection">
        /// The sort direction.
        /// </param>
        /// <returns>
        /// The <see cref="Page{IInvoice}"/>.
        /// </returns>
        protected override Page<IInvoice> PerformGetPagedEntities(long page, long itemsPerPage, string sortBy = "", SortDirection sortDirection = SortDirection.Ascending)
        {
            var keyPage = this.PerformGetPagedEntityKeys(page, itemsPerPage, sortBy, sortDirection);
            return _invoiceService.GetPageFromKeyPage(keyPage, () => _invoiceService.GetByKeys(keyPage.Items));
        }

        /// <summary>
        /// Gets a page of keys associated with invoices with an unpaid status
        /// </summary>
        /// <param name="page">
        /// The page.
        /// </param>
        /// <param name="itemsPerPage">
        /// The items per page.
        /// </param>
        /// <param name="sortBy">
        /// The sort by.
        /// </param>
        /// <param name="sortDirection">
        /// The sort direction.
        /// </param>
        /// <returns>
        /// The <see cref="Page{Guid}"/>.
        /// </returns>
        protected override Page<Guid> PerformGetPagedEntityKeys(
            long page,
            long itemsPerPage,
            string sortBy = "",
            SortDirection sortDirection = SortDirection.Ascending)
        {
            var query =
                Query<IInvoice>.Builder.Where(x => x.InvoiceStatusKey == Constants.DefaultKeys.InvoiceStatus.Unpaid);

            return _invoiceService.GetPagedKeys(query, page, itemsPerPage, sortBy, sortDirection);
        }

        /// <summary>
        /// The perform get paged entity keys.
        /// </summary>
        /// <param name="args">
        /// The args.
        /// </param>
        /// <param name="page">
        /// The page.
        /// </param>
        /// <param name="itemsPerPage">
        /// The items per page.
        /// </param>
        /// <param name="sortBy">
        /// The sort by.
        /// </param>
        /// <param name="sortDirection">
        /// The sort direction.
        /// </param>
        /// <returns>
        /// The <see cref="Page{Guid}"/>.
        /// </returns>
        protected override Page<Guid> PerformGetPagedEntityKeys(
            Dictionary<string, object> args,
            long page,
            long itemsPerPage,
            string sortBy = "",
            SortDirection sortDirection = SortDirection.Ascending)
        {
            if (!args.ContainsKey("searchTerm")) return PerformGetPagedEntityKeys(page, itemsPerPage, sortBy, sortDirection);
            
            return
                    this._invoiceService.GetInvoiceKeysMatchingInvoiceStatus(
                        args["searchTerm"].ToString(),
                        Constants.DefaultKeys.InvoiceStatus.Unpaid,
                        page,
                        itemsPerPage,
                        sortBy,
                        sortDirection);
        }

        /// <summary>
        /// The perform get paged entity keys not in collection.
        /// </summary>
        /// <param name="page">
        /// The page.
        /// </param>
        /// <param name="itemsPerPage">
        /// The items per page.
        /// </param>
        /// <param name="sortBy">
        /// The sort by.
        /// </param>
        /// <param name="sortDirection">
        /// The sort direction.
        /// </param>
        /// <returns>
        /// The <see cref="Page{Guid}"/>.
        /// </returns>
        protected override Page<Guid> PerformGetPagedEntityKeysNotInCollection(
            long page,
            long itemsPerPage,
            string sortBy = "",
            SortDirection sortDirection = SortDirection.Ascending)
        {
            var query =
               Query<IInvoice>.Builder.Where(x => x.InvoiceStatusKey != Constants.DefaultKeys.InvoiceStatus.Unpaid);

            return _invoiceService.GetPagedKeys(query, page, itemsPerPage, sortBy, sortDirection);
        }

        /// <summary>
        /// The perform get paged entity keys not in collection.
        /// </summary>
        /// <param name="args">
        /// The args.
        /// </param>
        /// <param name="page">
        /// The page.
        /// </param>
        /// <param name="itemsPerPage">
        /// The items per page.
        /// </param>
        /// <param name="sortBy">
        /// The sort by.
        /// </param>
        /// <param name="sortDirection">
        /// The sort direction.
        /// </param>
        /// <returns>
        /// The <see cref="Page{Guid}"/>.
        /// </returns>
        protected override Page<Guid> PerformGetPagedEntityKeysNotInCollection(
            Dictionary<string, object> args,
            long page,
            long itemsPerPage,
            string sortBy = "",
            SortDirection sortDirection = SortDirection.Ascending)
        {
            if (!args.ContainsKey("searchTerm")) return PerformGetPagedEntityKeysNotInCollection(page, itemsPerPage, sortBy, sortDirection);


            return
                this._invoiceService.GetInvoiceKeysMatchingTermNotInvoiceStatus(
                    args["searchTerm"].ToString(),
                    Constants.DefaultKeys.InvoiceStatus.Unpaid,
                    page,
                    itemsPerPage,
                    sortBy,
                    sortDirection);
        }
    }
<tree id="sales" title="Sales" icon="icon-receipt-dollar" routePath="merchello/merchello/saleslist/manage" visible="true" sortOrder="2">
        <childSettings>
            <!--
                Sets the order where self managed entity collection providers (like Unpaid invoices) are listed in the tree.
                If set to true, the resolved collections will be listed before the user defined collections.  False will list them
                after.
            -->
            <setting alias="selfManagedProvidersBeforeStaticProviders" value="true" />
        </childSettings>
        <selfManagedEntityCollectionProviders>
            <!--
                attribute: key - the provider key defined in the EntityCollectionProviderAttribute decorating the EntityCollectionProvider
                attribute: icon - is the icon displayed in the tree
                attribute: visible - indicates whether or not the collection should provider should create a tree node
                attribute: ref - not actually used, it is only here so that they can be managed more easily
               -->
            <entityCollectionProvider key="A8120A01-E9BF-4204-ADDD-D9553F6F24FE" icon="icon-bills" visible="true" ref="Unpaid invoices" />
            <entityCollectionProvider key="82015B97-11E8-4E57-8258-A59E1D378E04" icon="icon-bills" visible="true" ref="Partially paid invoices" />
            <entityCollectionProvider key="072E0671-31BE-41E4-8CF9-4AEEC6CC5BC6" icon="icon-bills" visible="true" ref="Paid invoices" />
            <entityCollectionProvider key="5FD6E5EB-0B7C-41A4-B863-7AEC31BE84C0" icon="icon-truck" visible="true" ref="Unfulfilled orders" />
            <entityCollectionProvider key="A9A288F3-DA98-4712-9E90-F9F909F2C26A" icon="icon-truck" visible="true" ref="Open orders" />
            <entityCollectionProvider key="68B57648-7550-4702-8223-C5574B7C0604" icon="icon-truck" visible="true" ref="Fulfilled orders" />
        </selfManagedEntityCollectionProviders>
    </tree>