Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Search for orders using abstractions

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

/// <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;

The Find method returns OrderSearchResults for the orders matching the supplied OrderSearchFilter and TOrderGroup type parameter.

Filter orders in search

OrderSearchFilter defines criteria for filtering orders in the search results:

  • CreatedFrom – The earliest creation time for returned orders (inclusive).
  • CreatedTo – The latest creation time for returned orders (inclusive).
  • MarketId – Restricts results to orders created in the specified markets.
  • ModifiedFrom – The earliest modification time for returned orders (inclusive).
  • ModifiedTo – The latest modification time for returned orders (inclusive).
  • StartingIndex – The starting index for paging through results.
  • RecordsToRetrieve – The number of records to retrieve per page.
📘

Note

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

Search results for orders

OrderSearchResults contains the matching orders in Orders (an IEnumerable<T>) and the total match count in TotalRecords.

As with other abstraction APIs, you can replace the default implementation with a custom one.

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

IOrderSearchServiceExtensions provides convenient extension methods for 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;