Routing strategy (context-based multi-config DOMS)
As a prerequisite, you should understand the DOMS before diving into this integration guide. If not, visit the DOMS integration guide.
Why we need it
The current Routing Configuration has a wide range of applications but falls short in certain use cases. For one, different countries may want to use different configurations for legal or economic reasons. Maybe in certain regions, the demand calls for fast deliveries, or in other regions, there is no economic incentive for features such as order split. Another example would be to treat certain ratings, like the Geodistance rating, differently for orders with line items that need pallets and thus require freight forwarding.
Basic Concepts
We have a tree-like configuration that we call RoutingStrategy. Every RoutingStrategy has a mandatory RootNode that serves as an entry point and contains the baseline routing configuration that can be extended and altered by nested nodes. A node can be active or inactive and is followed by a condition. The condition defines a node that gets evaluated if certain criteria are met and may define a condition to be checked if the criteria are not met.
Setup
Entities
RoutingStrategy
This is the entity that encompasses all configurations. There can be multiple RoutingStrategies defined but only one may be in use (denoted by the inUse
flag). It requires a localized name which can help distinguish between one strategy and another. The revision denotes which RoutingStrategy is the latest. If a new RoutingStrategy gets created it automatically gets the highest revision number.
RoutingStrategyGlobalConfiguration
RoutingStrategyNode
These are the entities containing actual routing configurations and specific rules. At least one RootNode has to be defined. A node may define a condition referencing another node. It may be active or not and in addition to that it may specify a number of time frames during which the rule is applicable. At least one ActivationTimeFrame
has to apply and the active
field has to be true. Both criteria have to be met, meaning an inactive node will always be inactive, regardless of the activationTimeFrames
field.
ActivationTimeFrame
An entity defining the valid timeframe for a node to be active (e.g. a Christmas sale). It can be either NONRECURRING
or recurring YEARLY
.
If a recurrence is set to yearly it will repeat every year after the given start date.
RoutingStrategyCondition
A condition is the fundamental part of our dynamic routing rules. It contains a rule and links to a RoutingStrategyNode
that applies if the rule gets matched. Also it may define a following condition to be evaluated if the rule does not apply. The following condition for example applies to orders with German delivery addresses. Just like a node it may also define a number of ActivationTimeFrame
s.
RoutingStrategyNodeConfig
A routing configuration defined by each RoutingStrategyNode
. Every part of this can be overwritten or extended by deeper nested RoutingStrategyNodeConfigs
. They contain the core part of the DOMS Routing functionality such as Fences
, Ratings
and an order-split/reroute configuration. However unlike before, toolkit fences and ratings now lie in the same place as their standard counterparts.
RoutingStrategyStandardFence
A fence using a predefined implementation. It’s nearly identical to the previously existing Fence
model but contains a field called type denoting that it’s a StandardFence
.
RoutingStrategyToolkitRating
A rating created using the Toolkit functionality. In addition to the existing ToolkitRating
it is required now to add a referenceId
to identify a toolkit rating because it may appear on multiple layers of the RoutingStrategy
and changes to it may affect more than one entity. Similar to its standard counterpart a required field type
is also added denoting that it’s a ToolkitRating
.
Example: RoutingStrategy with special configs for pallet
General Advice: with every API operation it is good practice to note down the
version
andid
of the entity you are manipulating/accessing as you are likely to need it in future steps. It may also be helpful to save the entire entity, especially for PUT operations.
Step 1 - Set up your RoutingStrategy using the respective endpoint
Before you get started, request a new auth token and add the headers as described in the quickstart documentation. The baseURL
variable will be https://{YOUR_TENANT_NAME}.api.fulfillmenttools.com
when using the REST API. When using GraphQL, replace the api
subdomain with graphql
.
First of all you will create a RoutingStrategyForCreation
. The absolute minimum required here is to give your strategy a localized name to distinguish it from other strategies you might create down the road. We have two options here - using the GraphQL resolver or the REST controller. We will use the name “Initial RoutingStrategy” for our English locale and leave every other field empty for now.
The following shows the mutation we want to use to create the initial routing strategy. You can copy & paste it into any GraphQL client (such as Altair) and it should work out of the box assuming you have set the Authorization headers using a valid bearer token.
If everything has worked out you should see that we have a basic routing strategy with all standard fences with active set to false and no additional configurations. However it won’t be active yet so let’s do that now.
Step 2 - Adding a Condition and Node to the existing RoutingStrategy
We want to create a new condition that applies to orders having line items with pallet articles. Let’s assume the OrderLineItem
will have a tag that looks as follows { id: ‘load-unit’, value: ‘pallet’ }
. Using that we will build a toolkit rule part that evaluates to true
if a line item with this tag.
Step 2.1 - Creating the JSONPath
The entities that will get evaluated are of the following schema:
Therefore to get a JSONPath pointing to the tag we should use the following string:
$.order.orderLineItems[?(@.tags.find(tag => tag.id === "load-unit" && value === "pallet")]
Step 2.2 - Creating the ToolkitPredicate with the JSONPath
This JSONPath will get all OrderLineItems
that have the tag that we defined with the appropriate value. Since the result we got is an array we can use the COUNT
transformer to count if we have at least one OrderLineItem
satisfying the properties. Since we only want to know if there is at least one (read: count greater equals 1) such order line item we can define the entire predicate as follows.
Step 2.3 - Creating a RoutingStrategyCondition with the ToolkitPredicate
The ToolkitRulePart
that we assemble will contain an array containing only this predicate and a ToolkitPredicateConnector
which becomes important as more predicates get added to the array. We’ll set it to ”AND”
for now. Then we create a condition containing the rule that looks as follows:
The node we want to create should have a config that applies only to orders fulfilling that condition so we should add a config that extends the existing default routing config.
Step 2.4 - Creating a RoutingStrategyNode
Now that we’ve created a ToolkitRulePart
we can create a RoutingStrategyCondition
that uses this rule. Let’s name it “Pallet routing configuration” since we will add the appropriate routing configuration to it. The RoutingStrategyNode could look as follows:
The configuration of the node contains only one rating. What this means in practice is that every configuration will be inherited from the root config (fences, ratings, reroute configuration) and only this particular fence will be overwritten.
Step 2.5 - Updating the RoutingStrategy with the new node and condition
Depending on whether you use GraphQL or not there are two ways we can update the RoutingStrategy
The following mutation adds our RoutingStrategyNode
and RoutingStrategyCondition
to the root node. However you also need to fill in the following variables:
strategyRef
- the id of our created RoutingStrategyroutingStrategyVersion
- the current version of theRoutingStrategy
as from the last responsenode
- theRoutingStrategyNode
that we just created in step 2.4condition
- theRoutingStrategyCondition
that we created in step 2.3
Step 3 - Creating an order to test the configurations
The entire purpose of MultiDOMS is to have a dynamic routing configuration that behaves differently in depending on context. So naturally we should test our configuration with two different orders.
Step 4.1 - Creating a "regular" order that should use the default configuration
First, we should test that a regular order (i.e. not satisfying the condition that we defined) will use the default configuration, meaning standard fences / ratings all set to inactive. The order could look something like this:
Step 4.2 - Creating a "special" order that should use the special configuration
Then we define an order that does meet the defined condition. It could look something like this:
To keep things simple we kept the order mostly the same except for the discriminator, which is the tags array on OrderLineItem
level. In the next step we’ll evaluate the RoutingStrategy
with these two orders.
Step 4 - Testing the RoutingStrategy evaluation
At the moment we do not offer a GraphQL Query for this yet
Using REST:
We prepare a
POST
toapi/routing/strategies/:strategyId/actions
We set the parameter
strategyId
to theid
of theRoutingStrategy
we want to testWe set the request body to JSON and send the
OrderForCreation
we want to testThe response should contain the following:
evaluatedPath
andevaluatedConfig
The
evaluatedConfig
should contain the actualRoutingStrategyNodeConfig
that would get used for routing this particular orderThe
evaluatedPath
contains information on how theevaluatedConfig
is assembled. It has no other purpose than creating transparency and helping understanding the elements that got evaluated.Take a look at the
evaluatedConfig
and take a closer look at theGeodistanceRating
If you sent the first order (without tags), the rating should be inactive with a
maxPenalty
of0
If you sent the second order (containing the tag), the rating should be active with a
maxPenalty
of1000
Repeat previous the steps for the other order as well
If everything works out as expected you can now be sure that the
RoutingStrategy
will use the correct configuration for the given examples. It is advised to do this for every single change that you do. If you’re uncertain, do not activate the RoutingStrategy until you have done this step.
Step 5 - Activate the RoutingStrategy to use it
Assuming the MultiDOMS feature is enabled on the given tenant, activating it will make the RoutingStrategy become the single source of truth for routing decisions so please skip this step until you are certain you want to use it.
The mutation we will use is activateRoutingStrategy
and requires an activateRoutingStrategyInput
which contains the routingStrategyId
and version you have copied from the last step.
The response should show that the RoutingStrategy
has now its inUse
property set to true.
Last updated