HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Search for orders using abstractions

Describes how to search for orders using abstractions in Optimizely Customized Commerce.

IOrderSearchService, available in the EPiServer.Commerce.Order namespace, retrieves historical data for IOrderGroup. You can for example search for IOrderGroup (ICart, IPurchaseOrder, IPaymentPlan), apply filters, and modify search results.

/// <summary>
     /// Finds orders with a specific <see cref="OrderSearchFilter"/> for a specific <typeparamref name="TOrderGroup"/>.
     /// </summary>
     /// <typeparam name="TOrderGroup">The given order type for filter.</typeparam>
     /// <param name="filter">The search filter.</param>
     /// <returns>The order search results.</returns>
            OrderSearchResults Find(OrderSearchFilter filter) where TOrderGroup : class, IOrderGroup;

This API finds orders with a specific OrderSearchFilter for a specific TOrderGroup, then returns OrderSearchResults.

Filter orders in search

OrderSearchFilter has a criteria set for filtering orders in the search results.

  • CreatedFrom. Specifies the time that returned orders were created after.
  • CreatedTo. Specifies the time that returned orders were created before.
  • MarketId. Specifies that only orders created in identified markets should be returned.
  • ModifiedFrom. Specifies the time that returned orders were modified after.
  • ModifiedTo. Specifies the time that returned orders were modified before.
  • StartingIndex. Gets or sets the starting index.
  • RecordsToRetrieve. Gets or sets the number of records to retrieve.

📘

Note

The search is inclusive; begin and end values are included for datetime filters (CreatedFrom, CreatedTo, ModifiedFrom, ModifiedTo).

Search results for orders

OrderSearchResults contains a collection of orders found IEnumerable Orders and the number of records found int TotalRecords.

As with other abstraction APIs, you can modify this API using a custom implementation.

using EPiServer.Framework;
    using EPiServer.ServiceLocation;
    using Mediachase.Commerce.Orders;
    using Mediachase.Commerce.Orders.Search;
    using Mediachase.MetaDataPlus.Extensions;
    using System;
    using System.Linq;
    
    namespace EPiServer.Commerce.Order.Internal
      {
        /// <summary>
        /// This class is intended to be used internally by EPiServer.
        /// We do not support any backward compatibility on this.
        /// 
        /// Default implementation of .
        /// </summary>
        [ServiceConfiguration(ServiceType = typeof(IOrderSearchService), Lifecycle = ServiceInstanceScope.Singleton)]
        public class DefaultOrderSearchService : IOrderSearchService
          {
            private readonly ICartSearchService _cartSearch;
    
            public DefaultOrderSearchService(ICartSearchService cartSearch)
              {
                Validator.ThrowIfNull(nameof(cartSearch), cartSearch);
                _cartSearch = cartSearch;
              }
    
            public virtual OrderSearchResults Find(OrderSearchFilter filter) where TOrderGroup : class, IOrderGroup
              {
                Validator.ThrowIfNull(nameof(filter), filter);
                var type = typeof(TOrderGroup);
                if (IsCart(type))
                  {
                    var carts = _cartSearch.FindCarts(filter.CreatedFrom, filter.CreatedTo,
                                filter.MarketId, filter.StartingIndex ?? 0,
                                filter.RecordsToRetrieve ?? int.MaxValue,
                                out int totalRecords).OfType();
                    return new OrderSearchResults(carts, totalRecords);
                  }
    
                string sqlMetaWhereClause = $@"(META.Created BETWEEN '{(filter.CreatedFrom ?? DateTime.MinValue.TruncateToSqlDateTimeRange()).ToString("s")}' 
                                                                 AND '{(filter.CreatedTo ?? DateTime.MaxValue.TruncateToSqlDateTimeRange()).ToString("s")}')";
    
                sqlMetaWhereClause += $@" AND (META.Modified BETWEEN '{(filter.ModifiedFrom ?? DateTime.MinValue.TruncateToSqlDateTimeRange()).ToString("s")}' 
                                                                 AND '{(filter.ModifiedTo ?? DateTime.MaxValue.TruncateToSqlDateTimeRange()).ToString("s")}')";
    
                var parameters = new OrderSearchParameters() { SqlMetaWhereClause = sqlMetaWhereClause};
    
                if (!string.IsNullOrEmpty(filter.MarketId))
                  {
                    parameters.SqlWhereClause = $"MarketId = '{filter.MarketId}'";
                  }
    
                var options = new OrderSearchOptions
                  {
                    StartingRecord = filter.StartingIndex ?? 0,
                    RecordsToRetrieve = filter.RecordsToRetrieve ?? int.MaxValue
                  };
    
                if (IsPurchaseOrder(type))
                  {
                    options.Classes.Add(OrderContext.Current.PurchaseOrderMetaClass.Name);
                    var orders = OrderContext.Current.FindPurchaseOrders(parameters, options, out int totalRecords).OfType();
                    return new OrderSearchResults(orders, totalRecords);
                  }
    
                if (IsPaymentPlan(type))
                  {
                    options.Classes.Add(OrderContext.Current.PaymentPlanMetaClass.Name);
                    var paymentplans = OrderContext.Current.FindPaymentPlans(parameters, options, out int totalRecords).OfType();
                    return new OrderSearchResults(paymentplans, totalRecords);
                  }
    
                throw new InvalidOperationException($"The type {typeof(TOrderGroup)} is not supported.");
              }
    
            private static bool IsCart(Type type)
              {
                return typeof(ICart).IsAssignableFrom(type);
              }
    
            private static bool IsPurchaseOrder(Type type)
              {
                return typeof(IPurchaseOrder).IsAssignableFrom(type);
              }
    
            private static bool IsPaymentPlan(Type type)
              {
                return typeof(IPaymentPlan).IsAssignableFrom(type);
              }
          }
      }

Extension methods

You can also use IOrderSearchServiceExtensions to provide convenient extension methods when working with IOrderSearchService.

  • FindCarts
  • FindPurchaseOrders
  • FindPaymentPlans
var orderFilter = new OrderSearchFilter
      {
        CreatedFrom = DateTime.UtcNow.AddDays(-365),
        CreatedTo = DateTime.UtcNow
      };
    var orderSearchService = ServiceLocator.Current.GetInstance<IOrderSearchService>()
    var searchResult = orderSearchService.FindPurchaseOrders(orderFilter);
    var orders = searchResult.Orders;
    var totalRecords = searchResult.TotalRecords;