This content is archived. See latest version here


This document describes the multiple inventory locations concept in EPiServer Commerce. You can define multiple inventory locations in the system. These are any place that has inventory that you want to track, whether that is a warehouse you are using for your shipping, individual stores, a factory, or whatever meets your needs. You could even include any trucks you have driving around delivering orders.

Currently only shipping from one central warehouse location is supported. If you have multiple shipping sources but you do not want to customize Commerce, then you can still track overall inventory in Commerce but you will have to figure out your shipment fulfillment logistics from your individual shipment locations on your own outside of Commerce.

In-store pickup from any store location is provided, which can handle any number of locations that are defined as places for pickup (but not for fulfillment). In our definitions these are Fulfillment Centers from which you can ship, and Pickup Locations to which a customer can come to pick up an order. Without customizing Commerce you can only have one Fulfillment Center, but you can have as many Pickup Locations as you like.

Why are there limitations? Simply because we do not know your business like you do. Some business logic to support fulfillment from multiple locations is provided in the sample code. However every business has its own approach to its fulfillment practices and no logic we can come up with will support more than a few situations at a time.

Fulfillment technical details

The changes to support multiple locations cross infrastructural code hidden in the assemblies, new services, and logic that is visible in the workflows. The infrastructural changes will not matter to most customers, although they may affect some existing customized installations. Depending on what you are doing you may be able to implement your needs directly in the workflows or by replacing the services.


The core business logic for inventory and shipping is implemented in the Workflows. The key places to look for these are:

  • Cart Workflows:
    • GetFulfillmentWarehouseActivity,
    • AdjustInventoryActivity,
    • ShipmentSplitActivity
  • OrderGroupActivities:
    • OrderGroupActivityBase
  • PurchaseOrderActivities:
    • AdjustInstoreInventoryActivity,
    • CheckInstoreInventoryActivity,
    • HandoffActivityBase

There is no implementation for multiple fulfillment centers out of the box. If you wish to have multiple fulfillment centers, you will need to:

  1. Disable the current lockout (required), and
  2. Implement custom warehouse selection logic (required), and possibly
  3. Implement custom inventory management logic (optional).

The modifications required for each of these are detailed below.

Disable the lockout

The first of these is simple. The default installation is designed to raise an exception for certain operations when there are multiple warehouses flagged as fulfillment centers. This exception is raised in the OrderGroupActivities\OrderGroupActivitiyBase workflow, in the CheckMultiWarehouse() method. The method is called from multiple locations (e.g. AdjustInventoryActivity.cs, AdjustInstoreInventoryActivity.cs at the time of this writing) so it is easier to clear the contents rather than removing all references. To allow multiple fulfillment warehouses you can replace the existing method with the following:

protected virtual void CheckMultiWarehouse(){}

or add whatever consistency checks meet your needs.

Custom warehouse selection

The second part is the major piece of the implementation, and cannot be described in depth since the actual logic is going to be dependent entirely on the needs of a particular business. This guide will only cover the places in the system where an implementation may need to override the default logic.

The main piece of business logic you will need to replace is found in this workflow, in the GetFulfillmentWarehouseForLineItem() method. In the default implementation it does little more than find the default warehouse (see line 87). You will need to replace this with your custom logic.

As workflow inherits from OrderGroupActivity, you already have an OrderGroup and its data available for all calculations and logic. In order to determine your list of warehouses and information about their available inventory, you will need to access two new service interfaces that have been added for release 7. These are the IWarehouseRepository and IWarehouseInventoryService. These can be instanced in code via the following:


Refer to Warehouse/Inventory Services below for further details. The current interfaces should be straightforward to use, although you may need to expand upon their functionality if you need additional information (e.g. geolocation) to determine your fulfillment warehouse selection.

ShipmentSplitActivity also has a reference to warehouses that may be of interest. Currently when a new split shipment is created, it is marked as sourcing from the same warehouse as its first line item. This works for a single fulfillment warehouse and in-store pickup, but may not function as desired for a more complicated multi-warehouse solution. Please examine the SplitForm() method and determine whether this will work for your custom solution and adjust it if not.

Custom inventory management (optional)

The existing Commerce workflows are able to manage the inventory in your individual warehouses out of the box, as long as your custom warehouse selection logic assigns the correct warehouse for each line item. However if you need to change the actual processing logic for inventory, such as changing how backorders and preorders are handled or to trigger external processes to balance inventories between warehouses as inventories get low, then you will need to change the logic in AdjustInventoryActivity to suit your needs. The main method in which to do so is AdjustStockItemQuantity().

The default implementation of the in-store pickup feature handles the store inventories out of the box, but you may also want to consider additional inventory handling here such as to resupply store inventory. The handling for in-store pickup inventories is found in AdjustInstoreInventoryActivity and CheckInstoreInventoryActivity. The former is probably the correct place to modify this for most implementations, but you can consider adjusting the latter instead.

Note also that the HandoffActivityBase activity includes support for in-store pickup. It is not necessary to change this, but if you choose to disable all in-store pickup functionality then you should consider removing the code from this as well. These include the PickupWarehouseInShipmentProperty dependency and PickupWarehouseInShipment property and these need simply be deleted.

Warehouse/inventory services

Many of the functions for accessing warehouse and inventory data have been moved into services which can be replaced in your implementation. In general we do not think that you will want to replace these as the default implementations work with the existing EPiServer Commerce controls and database as-is. However if it makes sense for your solution then it is an option. This could be useful if you want to encapsulate the current implementation to provide more methods (e.g. to support geolocation-based fulfillment logic) or if you wish to replace them entirely to manage your inventory with a new or external system.

If you do wish to implement custom inventory integration, there are 2 main services to consider:

methods for accessing the warehouse definitions
methods for accessing the actual inventory numbers for catalog entries at the various warehouses

If you are heading down this route, you should review the interfaces for the required properties and methods. The particulars are documented in the method signatures and should be self-explanatory in terms of the expected input and output values. What you need to do depends on the scope of your changes and will have to be considered on a case by case basis.

Note that the recommended model for managing inventory data across separate ERP and EPiServer Commerce systems is to update Commerce on a scheduled basis and allow Commerce to track inventory internally in the time between updates. Allowing Commerce to manage its own inventory will provide the best performance in almost all situations. The main issue from a business standpoint is if inventory is being sold (or otherwise removed) independently of Commerce, in which case you will need to find some way to reconcile orders, either by updating Commerce on the fly or by an appropriate backorder process.

You will need to consider carefully the pros and cons of the various approaches (for instance development costs for integrations, and whether is worth incurring the higher latency costs of communicating with your ERP directly so that you have perfectly accurate numbers at all times). When you review these interfaces, please note that some of the interfaces may be switched to use business objects instead of ID fields in the future.

Last updated: Oct 21, 2014