DOMS toolkit
The DOMS Toolkit allows creating customized routing rules
Introduction
The DOMS toolkit helps users define factors which should be considered when making the decision for the best fulfillment location.
The system allows to define fences and ratings:
Fences: Exclude facilities from order routing according to the fences selected
Ratings: Weigh facilities against each other according to the ratings selected
Please go to the Developer Docs for more information on managing the DOMS via routing plans REST API.
Toolkit fences
ToolkitFence fields in detail
Click to see what each field does
entity1
This describes the entity type for the left-hand side. In case of conditional rules this is the entity that gets evaluated first.
entity2
This describes the entity type for the right-hand side. In case of conditional rules this is the entity that gets evaluated second (or never), but more to that later.
active
Whether this fence is active or not
name
The name, has to be unique
nameLocalized
An object containing the localized names for different languages
description -[optional]
An optional description to say what the fence has to do. Although optional, it is strongly recommended that you do give it a meaningful description.
descriptionLocalized -[optional]
An object containing the localized descriptions for different languages
order
A number determining whether the fence should be executed before or after different fences. Lower numbers have precedence over higher numbers.
Rules for toolkit fences
There are two rule types which can be defined:
Conditional rule
Use "rule" to set up a conditional rule. Can be used for comparing each side against a fixed value (e.g., order line item quantity > 3). Incompatible with using the comparisonRule field. Conditional rules test a certain property of an entity (Order, Facility, Listing) against a predefined static value.
Steps for defining a conditional rule
operator
What the positive evaluation of the left hand side means for the execution of the fence as a whole. For now, there is only the equality-operator.
leftPart - ToolkitRulePart
The first part that is evaluated. Its evaluation result determines whether the right part gets evaluated.
rightPart - ToolkitRulePart
The second part that is evaluated if the first evaluation passes. Its evaluation result determines the final outcome of the fence.
How to define a ToolkitRulePart
A ToolkitRulePart consists of an array of predicates and a connector that determines how they are connected together.
predicateConnector
OR will make the rule part true if any of the predicates evaluate to true. AND will only make the expression true if all predicates evaluate to true.
predicates
An array of one or more ToolkitPredicates. A predicate consists of the following fields:
propertyPath
entityOperator
expectedValue
transformation (optional)
transformationArgs (optional, depends on transformation used)
How to define a ToolkitPredicate
You have to define at least one predicate. In the following we'll explain what each field is used for.
propertyPath
A JSONPath defining the property to look at.
entityOperator
The operators determine how a property of an entity should be compared against a given value. They can be divided up into two groups: Single value entity operators and array entity operators.
Single value entity operators
These operators can only be used for single values, not for arrays, such as VALUE_EQUALS
VALUE_EQUALS-> actual value equals expected value (e.g. 2 == 2)VALUE_NOT_EQUALS-> actual value unequals expected value (e.g. 2 != 3)VALUE_CONTAINS-> actual value contains expected value (e.g. "HELLO WORLD" contains "HELLO")VALUE_NOT_CONTAINS-> actual value does not contain expected value (e.g. "HELLO WORLD" does not contain "HI")LESS_THAN-> actual value less than expected value (e.g. 2 < 3)LESS_EQUALS-> actual value less than or equals expected value (e.g. 2 <= 3, 3 <= 3)GREATER_THAN-> actual value greater than expected value (e.g. 3 > 2)GREATER_EQUALS-> actual value greater than or equals expected value (e.g. 3 >= 2, 2 >= 2)
Array entity operators
These operators can only be used for arrays, not for single values. They can be grouped into three categories: ANY, EVERY, NONE. Within each category, either any, every or no value has meet the criteria. The condition may be anything of the aforementioned single value entity operators. Here are some examples on how this may look:
ANY_VALUE_EQUALSEVERY_VALUE_GREATER_EQUALS(which is equivalent toNO_VALUE_LESS_THAN)NO_VALUE_CONTAINS(which is equivalent toEVERY_VALUE_NOT_CONTAINS)
ANY, EVERY and NONE
ANY
Requires that at least one element of the array satisfies the following condition. It is not required that more than one element match but if the array is empty this condition will NOT be fulfilled.
EVERY
Requires that every element of the array satisfies the following condition. If the array is empty, this condition will be true because there is no element that does not fulfill the condition.
NONE
Requires that no element satisfies the following condition, meaning that every element does not satisfy the condition. This condition will always be fulfilled, unless there is an element that satisfies the condition, including for empty arrays.
Single value operators vs array operators
If your actual value is an array, you have to use an array operator. When is that the case? - If you use a wildcard operator (* or ?()) you get an array of elements (such as $.orderLineItems[*]). However, if you do use a transformer (such as COUNT to get the number of elements or SUM to add the quantities of each OrderLineItem), then you will get a single value and must use a single value operator.
transformation -[optional]
transformationArgs -[optional]
The args for the transformation, if required.
expectedValue
The expected value the property should match Examples:
2- anumber"WAREHOUSE"- astring"2024-02-19T16:16:38.107Z"- adate-string
Comparison rule
Use "comparisonRule" to set up a comparison rule. Comparison rules compare a certain property of the left-hand side (Order) to a certain property of the right-hand side (Order, Facility, Listing). Incompatible with using the rule field.
An example of this could be an order with products of a certain brand demanding a facility tagged with the same brand.
Steps for defining a comparison rule
predicateConnector
OR will make the rule part true if any of the predicates evaluate to true. AND will only make the expression true if all predicates evaluate to true.
predicates
An array of one or more ToolkitComparisonPredicates.
How to define a ToolkitComparisonPredicate?
rightPropertyPath
A string containing a JSONPath for the right side entity.
leftPropertyPath
A string containing a JSONPath for the right side entity.
entityOperator
One of the following:
LEFT_CONTAINS_RIGHT- the left hand side should contain all values from the right hand sideRIGHT_CONTAINS_LEFT- the right hand side should contain all values from the left hand sideALL_MATCHES- the arrays of values should be exactly equalNO_MATCHES- Values should be disjoint, even when comparing a list with a single value (blacklist case)
leftTransformation -[optional]
The transformation for the left hand side.
leftTransformationArgs -[optional]
The transformation arguments for the left transformation, if required.
rightTransformation -[optional]
The transformation for the right hand side.
rightTransformationArgs -[optional]
The transformation arguments for the right transformation, if required.
Toolkit ratings
Toolkit ratings follow nearly exact same syntax as toolkit fences with a few key differences:
order: since all ratings get evaluated either way the order field does not exist for ratingsmaxPenalty: the penalty which determines the weight of the rating in comparison to other ratings
Introduction to JSONPath
It always begins with $ referring to the entity, followed by a path to the nested property. (e.g. $.orderLineItems[*].quantity) Used in:
Steps for using a JSON path to define rules
$.tenantOrderId->$refers to the order entity whiletenantOrderIdrefers to the tenantOrderId. The.indicates that tenantOrderId is a nested property ofOrder$.orderLineItems[*].article-> Gets the articles from all orderLineItems, resulting in an array$.orderLineItems[?(@.quantity > 3)].article-> Same as last time but only gets the articles from OrderLineItems with a quantity greater than 3
To sum up we can say the following: nested properties can be accessed using the . while nested array properties such as orderLineItems, tags or stickers can be accessed using the array brackets [ and ] with an asterisk * to indicate a wildcard.
If you want to be more specific, instead of a wildcard * you can use the ?() syntax. Inside the parentheses (, ) you can then define an arbitrary expression using the @ symbol to refer to the entity being tested.
If you are for instance on an OrderLineItem such as in our example, the @ refers to the OrderLineItem that is just being evaluated. You can then access all of its nested attributes and test for an arbitrary condition. This could be the quantity as in our previous example but it could also be more complex such as the following expression:
$.orderLineItems[?(@.tags.find(tag => tag.id === 'color' && tag.value === 'red'))].article
This gets us the articles of all OrderLineItems that have at least one tag of type color with the value red.
Note: It is recommended though to keep your expressions as simple as they can possibly be without compromising on their functionality to avoid mistakes leading to misbehavior of the fence/rating.
The JSONPath documentation can be found here
A helpful tool for testing JSONPath expressions can be found here
Introduction to transformers
Transformers allow to modify the input of a ToolkitPredicate before it gets evaluated. This can serve multiple purposes, maybe you only want to look at the number of elements, get the total price of all OrderLineItems or just want to consider the beginning of the tenantOrderId.
These are the transformations currently available in the platform.
SUM: sums the number values of each element - requires an array of elementsCOUNT: counts the number of elements - requires an array of elementsSUBSTRING: gets a substring of a value, requiresstartandendparametersLAST: gets the lastnchars of a string - requiredlengthparameter
Count transformation
Applies to orders with 10 OrderLineItems or more.
Sum transformation
Applies to orders where all OrderLineItems in sum have a total quantity of 100.
Substring transformation
Applies to orders where any OrderLineItem has a tenantArticleId that begins with "Coca".
Last chars transformation
Applies to orders where any OrderLineItem has a tenantArticleId that ends with "Christmas Special"
Introduction to time specifications
It is possible to define a time specification as an expected value, enabling dynamic comparisons during routing processes. For example, a timestamp stored in a customAttribute can be compared against the current time using predefined expressions.
{today}represents the current day, based on the system's configured time zone. This expression is used to refer to a date value (e.g.2025-08-07).{now}represents the current timestamp, calculated in UTC+0. This expression is used to refer to a specific timestamp (e.g.2025-08-07T18:00:00.000Z).
This functionality, for example, allows routing logic to determine whether an item is eligible for release to sales, based on time-based conditions.
When using the "entityOperator": "EQUALS" for timestamp comparisons, be aware that it includes minutes and seconds. This may lead to unintended mismatches unless the timestamps are precisely aligned.
Last updated