Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

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

Order processing

Describes the APIs for order processing in Optimizely Commerce Connect 13 including validating line items in the cart, applying discounts and updating prices, adjusting inventories, and processing payments.

Processing of purchase orders and related items is based on classes and methods in the EPiServer.Commerce.Order and EPiServer.Commerce.Marketing namespaces.

These are the key interfaces:

  • EPiServer.Commerce.Order.IOrderGroupExtensions
  • EPiServer.Commerce.Order.IInventoryProcessor. See Updating inventory and Adjusting inventory.
  • EPiServer.Commerce.Order.ILineItemValidator. See Validating line item.
  • EPiServer.Commerce.Order.IPaymentProcessor. See Processing payments.
  • EPiServer.Commerce.Order.IPaymentPlanProcessor. See Processing payment plans.
  • EPiServer.Commerce.Order.IPaymentPlanExtensions. See Processing payment plan extensions.
  • EPiServer.Commerce.Order.IPlacedPriceProcessor. See Updating placed price.
  • EPiServer.Commerce.Order.IFulfillmentWarehouseProcessor
  • EPiServer.Commerce.Order.IPurchaseOrderProcessor . See Processing purchase orders.
  • EPiServer.Commerce.Order.IPurchaseOrderExtensions. See Processing purchase order extensions.
  • EPiServer.Commerce.Order.IShipmentProcessor. See Processing shipments.
  • EPiServer.Commerce.Order.IShipmentProcessorExtensions. See Processing shipment extensions.
  • EPiServer.Commerce.Order.IShipmentExtensions. See Processing shipment extensions.
  • EPiServer.Commerce.Marketing.IPromotionEngine. See Applying discount.

All example code below passes dependencies to the extension methods, so that you can easily unit test your applications.

Validation issues

When performing different actions on an IOrderGroup, issues can cause modifications to line items. These warnings and errors are represented in the class EPiServer.Commerce.Order.ValidationIssue. Most processing tasks take a parameter with an Action<ILineItem, ValidationIssue>, which allows the caller to collect this information so a message about the issue can be displayed to the user.

Validate line items

Validating the status of line item is useful to make sure the product is active, within the valid date range, and that the catalog entry is available in the current market.

Example: Validating line items in a cart and checking for validation issues.

var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
    var lineItemValidator = ServiceLocator.Current.GetInstance<ILineItemValidator>();
    var contactId = PrincipalInfo.CurrentPrincipal.GetContactId();
    var cart = orderRepository.LoadCart(contactId, "Default");
    var validationIssues = new Dictionary<ILineItem, ValidationIssue>();
    
    //Check all line items on cart
    cart.ValidateOrRemoveLineItems((item, issue) => validationIssues.Add(item, issue), lineItemValidator);
    
    //Check one lineitem
    var lineItem = cart.GetAllLineItems().First();
    if (!lineItemValidator.Validate(lineItem, cart.Market, (item, issue) => validationIssues.Add(item, issue)))
      {
        //Check validationIssues for problems
      }

Update placed price

Updating placed price is useful when a shopper has an item in the cart for an extended period of time. It is recommended to add validation to check if the product price has changed, and if needed update the price.

Example: Checking and updating placed price for line items.

var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
    var placedPriceProcessor = ServiceLocator.Current.GetInstance<IPlacedPriceProcessor>();
    var contactId = PrincipalInfo.CurrentPrincipal.GetContactId();
    var cart = orderRepository.LoadCart(contactId, "Default");
    var validationIssues = new Dictionary<ILineItem, ValidationIssue>();
    
    //Update all placed prices on the cart
    cart.UpdatePlacedPriceOrRemoveLineItems(PrincipalInfo.CurrentPrincipal.GetCustomerContact(),
      (item, issue) => validationIssues.Add(item, issue), placedPriceProcessor);
    
    //Update line item placed price
    var lineItem = cart.GetAllLineItems().First();
    lineItem.UpdatePlacedPrice(PrincipalInfo.CurrentPrincipal.GetCustomerContact(), cart.Market,
      cart.Currency,(item, issue) => validationIssues.Add(item, issue), placedPriceProcessor);
    
    //Update line item placed price
    var lineItem = cart.GetAllLineItems().First();
    placedPriceProcessor.UpdatePlacedPrice(lineItem, PrincipalInfo.CurrentPrincipal.GetCustomerContact(),
      cart.Market, cart.Currency,(item, issue) => validationIssues.Add(item, issue));

Apply discounts

Applying discounts will run the promotion engine to evaluate and apply discounts to the IOrderGroup. If certain discounts require coupons, it is important to add coupons to the IOrderForm before running ApplyDiscounts.

Example: Checking for discounts on items in a cart.

var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
    var promotionEngine = ServiceLocator.Current.GetInstance<IPromotionEngine>();
    var contactId = PrincipalInfo.CurrentPrincipal.GetContactId();
    var cart = orderRepository.LoadCart(contactId, "Default");
    
    //run apply discounts on the cart
    var rewardDescriptions = cart.ApplyDiscounts(promotionEngine, new PromotionEngineSettings());
    
    //run apply discounts on the cart
    var rewardDescriptions = promotionEngine.Run(cart, new PromotionEngineSettings());

Process payments

Process payments allow the configured payments to be processed through their respective payment providers.

Example: Running the payment processor for a cart.

var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
    var paymentProcessor = ServiceLocator.Current.GetInstance<IPaymentProcessor>();
    var orderGroupCalculator = ServiceLocator.Current.GetInstance<IOrderGroupCalculator>();
    var contactId = PrincipalInfo.CurrentPrincipal.GetContactId();
    var cart = orderRepository.LoadCart(contactId, "Default");
    
    
    //Process payments for the cart
    cart.ProcessPayments(paymentProcessor, orderGroupCalculator);

Update inventory

UpdateInventory checks that a sufficient inventory quantity exists for the selected shipment warehouse. This method also updates the line item with the available quantity or, if none are available, removes it.

Example: Updating inventory information for a cart.

var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
    var inventoryProcessor = ServiceLocator.Current.GetInstance<IInventoryProcessor>();
    var contactId = PrincipalInfo.CurrentPrincipal.GetContactId();
    var cart = orderRepository.LoadCart(contactId, "Default");
    var validationIssues = new Dictionary<ILineItem, ValidationIssue>();
    
    //Update Inventory on cart
    cart.UpdateInventoryOrRemoveLineItems((item, issue) => validationIssues.Add(item, issue), inventoryProcessor);
    
    //Update inventory on shipment line items
    var shipment = cart.GetFirstShipment();
    inventoryProcessor.UpdateInventoryOrRemoveLineItem(shipment, (item, issue) => validationIssues.Add(item, issue));

Adjust inventory

AdjustInventory adjusts the inventory for each line item and removes it if no inventory exists. This operation is done in sequence for each shipment in an IOrderGroup, or for a specific shipment if the IInventoryProcessor method is called directly.

The behavior changes based on the value of the IOrderGroup OrderStatus property. If calling the IInventoryProcessor directly, you should pass the status of the shipment's parent IOrderGroup:

  • Completed – Makes permanent the reservation of inventory, decrementing available quantity.
  • Canceled – Cancels the reservation of inventory, incrementing available quantity.
  • InProgress || AwaitingExchange – Reserves inventory to fulfill the shipment.

In addition, the value of IShipment.OrderShipmentStatus may override the behavior for a specific shipment.

  • Shipped – Same behavior as OrderStatus.Completed but is applied regardless of the value of IOrderGroup.OrderStatus.
  • Cancelled – Same behavior as OrderStatus.Cancelled but is applied regardless of the value of IOrderGroup.OrderStatus.

Example: Adjusting inventory information for a line items in a cart.

var orderRepository = ServiceLocator.Current.GetInstance<IOrderRepository>();
    var inventoryProcessor = ServiceLocator.Current.GetInstance<IInventoryProcessor>();
    var contactId = PrincipalInfo.CurrentPrincipal.GetContactId();
    var cart = orderRepository.LoadCart(contactId, "Default");
    var validationIssues = new Dictionary<ILineItem, ValidationIssue>();
    
    //Adjust Inventory on cart
    cart.AdjustInventoryOrRemoveLineItems((item, issue) => validationIssues.Add(item, issue), inventoryProcessor);
    
    //Adjust inventory on shipment line items
    var shipment = cart.GetFirstShipment();
    inventoryProcessor.AdjustInventoryOrRemoveLineItems(shipment, cart.OrderStatus, (item, issue) => validationIssues.Add(item, issue));

Process purchase orders

IPurchaseOrderProcessor contains functionality for putting and releasing orders on hold, canceling orders, and starting order processing.

Example: Using HoldOrder() to put a purchase order on hold.

IOrderRepository orderRepository;
    IPurchaseOrderProcessor purchaseOrderProcessor;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    purchaseOrderProcessor.HoldOrder(purchaseOrder);



**Example:** Using ReleaseOrder() to release a purchase order from hold.



    IOrderRepository orderRepository;
    IPurchaseOrderProcessor purchaseOrderProcessor;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    purchaseOrderProcessor.ReleaseOrder(purchaseOrder);

Example: Using CancelOrder() to cancel a purchase order.

IOrderRepository orderRepository;
    IPurchaseOrderProcessor purchaseOrderProcessor;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    purchaseOrderProcessor.CancelOrder(purchaseOrder);

Example: Using ProcessOrder() to start processing a purchase order.

IOrderRepository orderRepository;
    IPurchaseOrderProcessor purchaseOrderProcessor;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    purchaseOrderProcessor.ProcessOrder(purchaseOrder);

Process purchase order extensions

IPurchaseOrderExtensions extends the functionality provided with IPurchaseOrderProcessor.

Example: Using IsPaid() to determine if a purchase order is paid.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var isPaid = purchaseOrder.IsPaid();

Example: Using CanBeCancelled() to determine if purchase order can be cancelled.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var canBeCancelled = purchaseOrder.CanBeCancelled();

Example: Using CanBePutOnHold() to determine if purchase order can be put on hold.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var canBeHold = purchaseOrder.CanBePutOnHold();

Example: Using HasAwaitingStockReturns() to determine if purchase order has any awaiting stock returns.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var awaitingStockReturns = purchaseOrder.HasAwaitingStockReturns();

Example: Using HasAwaitingReturnCompletable() to determine if purchase order has any awaiting return completable.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var awaitingReturnCompletable = purchaseOrder.HasAwaitingReturnCompletable();

Example: Using GetActiveReturnForms() to get a purchase order's active return forms (moved from DefaultReturnPurchaseOrderCalculator).

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var activeReturnForms = purchaseOrder.GetActiveReturnForms();

Example: Using CanReleaseShipment() to determine if a shipment can be released.

IOrderRepository orderRepository;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var canReleaseShipment = purchaseOrder.CanReleaseShipment(shipment);

Example: Using CanCancelShipment() to determine if a shipment can be cancelled.

IOrderRepository orderRepository;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var canCancelShipment = purchaseOrder.CanCancelShipment(shipment);

Example: Using CanReturnShipment() to determine if a shipment can be returned.

IOrderRepository orderRepository;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var canReturnShipment = purchaseOrder.CanReturnShipment(shipment);

Example: Using CanCompleteShipment() to determine if a shipment can be completed.

IOrderRepository orderRepository;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    var canCompleteShipment = purchaseOrder.CanCompleteShipment(shipment);

Process shipments

IShipmentProcessor contains functionality for canceling, completing, and realising shipments, and adding them to and from warehouse picklists.

Example: Using CancelShipment() to cancel a shipment.

IOrderRepository orderRepository;
    IShipmentProcessor shipmentProcessor;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    shipmentProcessor.CancelShipment(purchaseOrder, shipment);

Example: Using CompleteShipment() to complete a shipment.

IOrderRepository orderRepository;
    IShipmentProcessor shipmentProcessor;
    IList<Ishipment> shipments;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    shipmentProcessor.CompleteShipment(purchaseOrder, shipments);

Example: Using ReleaseShipment() to release a shipment.

IOrderRepository orderRepository;
    IShipmentProcessor shipmentProcessor;
    IList<Ishipment> shipments;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    shipmentProcessor.ReleaseShipment(purchaseOrder, shipments);

Example: Using AddShipmentToPicklist() to add a shipment to a picklist.

IOrderRepository orderRepository;
    IShipmentProcessor shipmentProcessor;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var pickListId = 1;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    shipmentProcessor.AddShipmentToPicklist(purchaseOrder, shipment, pickListId);

Example: Using RemoveShipmentFromPicklist() to remove a shipment from a picklist.

IOrderRepository orderRepository;
    IShipmentProcessor shipmentProcessor;
    IShipment shipment;
    
    (…)
    var orderGroupId = 123;
    var purchaseOrder = orderRepository.Load<PurchaseOrder>(orderGroupId);
    shipmentProcessor.RemoveShipmentFromPicklist(purchaseOrder, shipment);

Process shipment extensions

IShipmentProcessorExtensions extends the functionality provided with IShipmentProcessor.

Example: Using CompleteShipment() to complete a shipment.

IShipmentProcessor shipmentProcessor; 
    IPurchaseOrder purchaseOrder;
    IShipment shipment;
    
    (…)
    shipmentProcessor.CompleteShipment(purchaseOrder, shipment);

Example: Using ReleaseShipment() to release a shipment.

IShipmentProcessor shipmentProcessor; 
    IPurchaseOrder purchaseOrder;
    IShipment shipment;
    
    (…)
    shipmentProcessor.ReleaseShipment(purchaseOrder, shipment);

Example: Using CanBePacked() in IShipmentExtensions to determine if a shipment can be packed.

IShipment shipment;
    
    (…)
    var canBePacked = shipment.CanBePacked();

Process payment plans

IPaymentPlanProcessor contains functionality for canceling payment plans.

Example: Using CancelPaymentPlan() to cancel a payment plan.

IOrderRepository orderRepository;
    IPaymentPlanProcessor paymentPlanProcessor;
    (…)
    var orderGroupId = 123;
    var paymentPlan = orderRepository.Load<PaymentPlan>(orderGroupId);
    paymentPlanProcessor.CancelPaymentPlan(paymentPlan);

Process payment plan extensions

IPaymentPlanExtensions conatins functionality for checking payment and cancellation of payment plans.

Example: Using IsPaid() to determine if a payment plan is paid.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var paymentPlan = orderRepository.Load<PaymentPlan>(orderGroupId);
    var isPaid = paymentPlan.IsPaid();

Example: Using CanBeCancelled() to determine if a payment plan can be cancelled.

IOrderRepository orderRepository;
    (…)
    var orderGroupId = 123;
    var paymentPlan = orderRepository.Load<PaymentPlan>(orderGroupId);
    var canBeCancelled = paymentPlan.CanBeCancelled();

Use APIs instead of CartHelper for order checkout

The IOrderRepository API replaces the legacy functionality provided with the CartHelper activity workflow. The following provides some guidelines on how to use the API instead.

The legacy cart checkout workflow contained activities that can be called separately by the APIs.

  • ProcessPaymentActivity – Previously used for processing payments added to a cart. Use IOrderGroupExtensions.ProcessPayments instead.
  • CalculateTotalsActivity – Previously used for calculating order totals. Use IOrderGroupExtensions.GetTotals() instead.
  • AdjustInventoryActivity – Previously used for adjusting line item inventories. Use IOrderGroupExtensions.AdjustInventoryOrRemoveLineItems() instead.
  • RecordPromotionUsageActivity – Previously used to calculate and save promotion usage. Use IOrderGroupExtensions.ApplyDiscounts() instead.
  • Use IOrderRepository.SaveAsPurchaseOrder() to save a cart as a purchase order.