# Product Rules

## Foreword

It is important to understand the notion of product parameters before going in the details of product rules. Product parameters each have a list of possible values corresponding to its valid options. These possible values are represented by a fixed list that does not depend on the context (i.e. other parameters).

Concept | Definition |
---|---|

Parameter possible values | List of possible values for a parameter (dimensions, products, etc.). For example, the "handle" parameter of a product defines the list of possible handle product references that can be used for a cabinet. |

Product rule | Allows to create dependencies between two or more parameters of the same product. |

## Product Rule Definition

Product Rules are used when the **possible values of one parameter depend on the value of one or several other parameters**.

Example : some cabinet fronts have an integrated handle (handle built in the front directly). These fronts are therefore not compatible with an additional handle: the

`front`

and`handle`

parameters are correlated. More precisely, the`handle`

possible values depend on the value of parameter`front`

.

To manage this dependency, the ByMe platform datamodel implements a compatibility table between two or more parameters of the same product called a "Product Rule".

Product Rules are used by the planner for two operations:

**Apply**: when applying a new value to a parameter, product rules are checked for potential impacts on other parameters**List values**: when computing the possible values of a parameter, product rules are used for potential constraints caused by other parameters

Example 1: a user applies a front with an integrated handle. Consequently, the handle parameter is also updated with the value "null" (handle removed) thanks to a dedicated product rule.

Example 2: a user tries to change the value of the handle parameter manually. The planner identifies the front->handle product rule and reduces the list of proposed replacements to only compatible handles with the currently set front.

Product rules can be attached to a list of products, or applied to an entire application distribution. In one case or the other, there are strong attention points to be aware of:

- for a products-applied product rule: Only attach product rules to
**root products**(i.e. top products). If a product rule is attached to an assembly sub-product, the planner behavior is not guaranteed. - for an app-distribution product rule: the rule is applied to
**every**products and sub-products. Similarly as above, product rules should not be applied to assembly sub-products so make sure**no sub-product in the entire catalog**has the parameters defined in your product rule. Unless you control carefully your catalog, it is recommended to avoid this kind of rule and prefer products-applied rules.

❗ Please note that a product rule allows to set up relation between options of the same Product. Managing links between two Products, or a Product and its environment, is in the scope of Applicative Rules.

To be valid in the ByMe platform, a product rule needs to be defined by:

- An
**ID**: a unique identifier. - A
**name**: the rule name. - A
**key**: the rule key, used in some cases to override a product rule by another one. - A
**typeId**: the rule type. It defines the rule behavior, see below for a list of supported types. - A
**version**: the versioning of the rule. Some rule types support several versions, see below for details. - A list of
**parameters**: the list of parameters used in the product rule. Depending on the typeId, the parameter order can be important. - A
**compatibility table**: the table defining compatible values for each parameters in each case. - A rule scope, either
- A list of
**products**: the list of products for which the rule needs to be applied. To be left empty if using the below list of application distributions. Only apply product rules to root products as a product rule applied on product sub-levels may have undefined behaviors outside of the planner. - A list of
**application distributions**: the list of application distributions for which the rule needs to be available. To be left empty if using the above list of products.

- A list of

## Product Rule Types

The product rule typeId defines how to interpret the rule. Different types have different effects depending on the context. Below is the list of every supported type.

Note that 3DCloud only supports rules of typeId 1 and 2. In order to work with other types of rules you must use the API directly.

### type 1 - Compatibility

Triggers / Impacts | Affects possible values |
---|---|

Each rule parameter impacts all other rule parameters | NO |

A compatibility rule defines a list of compatible options, without a preferred direction. Each rule parameter impacts all other parameters of the rule.

This type of rule is only used when applying a new value to a parameter: everytime a parameter managed by the rule is modified, all the other parameters managed by the rule are updated to a compatible value. Listing the possible values is not affected by rules of this type, so each parameter can be applied any value.

**Example**

Parameters `front`

and `handle`

are linked with a compatibility rule. Those 2 parameters have their full list of possible values always available to the user (i.e. the rule does not affect the list of possible values).

When changing the value of parameter `front`

, the parameter `handle`

is updated to a compatible value, and vice versa: when changing the value of parameter `handle`

, the parameter `front`

is updated to a compatible value.

### type 2 - Chain

Chain rules exist in 2 versions:

#### version 1

⚠️ DEPRECATED VERSION

Triggers / Impacts | Affects possible values |
---|---|

Each rule parameter impacts the parameter coming directly after it | YES |

A chain rule in version 1 defines a chain of parameter impacts. Each parameter has an impact on the directly following parameter, so the order of parameters is meaningful. This particularity makes this type of rule hard to write and maintain when there are more than 2 parameters. **This version is now deprecated** and replaced by the version 2 which works in a similar way and takes full advantage of rules linking.

This type of rule is used when applying a new value to a parameter: everytime a parameter managed by the rule is modified, all parameters coming after it in the list are updated to a compatible value, in order. Listing the possible values is also affected by rules of this type, so each parameter can only be applied a value compatible with all parameters coming before it in the list. All the values of the first parameter are always available because other parameters do not impact it.

**Example**

Parameters `front`

and `handle`

are linked with a version 1 chain rule, in this order. `front`

can be applied any value as it is the first parameter in the list. `handle`

values are constrained by the current value of `front`

so only compatible values can be applied.

When changing the value of parameter `front`

, the parameter `handle`

is updated to a compatible value. When changing the value of parameter `handle`

, nothing happens as the chain of impact is front -> handle.

#### version 2

Triggers / Impacts | Affects possible values |
---|---|

All parameters except the last one have a common impact on the last parameter | YES |

A chain rule defines a list of trigger parameters (all parameters except the last one), and a single impacted parameter (the last parameter in the list). The order of parameters is meaningful to represent which is the impacted parameter.

Note: the implicit logic operator between trigger parameters is

`AND`

. It reads "if trigger 1 value is one of [A, B, C]ANDtrigger 2 value is one of [D, E, F], then valid values of the impacted parameter are [G, H]".

This type of rule is used when applying a new value to a parameter: everytime one or several trigger parameters are modified, the impacted parameter is updated to a compatible value. Listing the possible values is also affected by rules of this type, so the impacted parameter can only be applied a value compatible with all trigger parameters.

**Example**

Parameters `front`

, `height`

and `handle`

are linked with a chain rule, in this order. `handle`

is the impacted parameter as it is last in the list, and `front`

and `height`

are the triggers. `handle`

values are constrained by the current value of `front`

and `height`

so only compatible values can be applied.

When changing the value of parameter `front`

or parameter `height`

, the parameter `handle`

is updated to a compatible value. When changing the value of parameter `handle`

, nothing happens as the chain of impact is (front + height) -> handle.

### type 3 - Unconstrained Chain

Unconstrained chain rules exist in 2 versions:

#### version 1

⚠️ DEPRECATED VERSION

Triggers / Impacts | Affects possible values |
---|---|

Each rule parameter impacts the parameter coming directly after it | NO |

An unconstrained chain rule in vesion 1 defines a chain of parameter impacts. Each parameter has an impact on the directly following parameter, so the order of parameters is meaningful. This particularity makes this type of rule hard to write and maintain when there are more than 2 parameters. **This version is now deprecated** and replaced by the version 2 which works in a similar way and takes full advantage of rules linking.

This type of rule is used when applying a new value to a parameter: everytime a parameter managed by the rule is modified, all parameters coming after it in the list are updated to a compatible value, in order. Listing the possible values is not affected by rules of this type, so each parameter can be applied any value.

**Example**

Parameters `front`

and `handle`

are linked with a version 1 unconstrained chain rule, in this order. `front`

can be applied any value as it is the first parameter in the list. `handle`

can also be applied any value because this type of rule does not affect the possible values at all.

When changing the value of parameter `front`

, the parameter `handle`

is updated to a compatible value. When changing the value of parameter `handle`

, nothing happens as the chain of impact is front -> handle.

#### version 2

Triggers / Impacts | Affects possible values |
---|---|

All parameters except the last one have a common impact on the last parameter | NO |

A chain rule defines a list of trigger parameters (all parameters except the last one), and a single impacted parameter (the last parameter in the list). The order of parameters is meaningful to represent which is the impacted parameter.

Note: the implicit logic operator between trigger parameters is

`AND`

. It reads "if trigger 1 value is one of [A, B, C]ANDtrigger 2 value is one of [D, E, F], then valid values of the impacted parameter are [G, H]".

This type of rule is used when applying a new value to a parameter: everytime one or several trigger parameters are modified, the impacted parameter is updated to a compatible value. Listing the possible values is not affected by rules of this type, so each parameter can be applied any value.

**Example**

Parameters `front`

, `height`

and `handle`

are linked with an unconstrained chain rule, in this order. `handle`

is the impacted parameter as it is last in the list, and `front`

and `height`

are the triggers. All 3 parameters can be applied any value because this type of rule does not affect the possible values at all.

When changing the value of parameter `front`

or parameter `height`

, the parameter `handle`

is updated to a compatible value. When changing the value of parameter `handle`

, nothing happens as the chain of impact is (front + height) -> handle.

## Product Rule Scopes

A product rule has a scope: either a list of specific products, or a list of application distributions.

### Products scope

It is possible to define a product rule on a dedicated Product or list of Products. For example, if `width`

and `depth`

parameters are linked on a limited set of Products, the range manager can define the list of Products for which the rule is triggered.

The expected value here is the ID(s) of the product(s). As mentioned above, only attach product rules to root products.

### Application Distributions scope

Unlike Products, Product Rules do not need to be set up in a catalog. For a product rule to be deployed into a planner, it can be linked to one or more application distributions directly.

The expected value here is the ID of the application distribution.

This list and the previous specific product list are mutually exclusive. If a product rule has to be available for an entire application distribution, the product list must be empty, and vice versa.

## Product Rule Defaults

Product rules of types 2 and 3 support a default value-set for their impacted parameter. This allows for simpler product rules as you no longer have to express all the possible values for each triggering parameter.

Notes:

- this is only supported from version 2 of chain,(type 2) and unconstrained chain (type 3) rules. Versions 1 do not support it.
- compatibility rules (type 1) does not support this default value-set at all.

When using a default value-set, only add to the product rule definition the *specific* cases where the impacted parameter should behave differently. Then for all *normal* cases, just write the expected value-set of the impacted parameter in the `default`

attribute of the rule.

## Product Rule Keys

Product rules can be affected a *key*. It is a string attribute to defined on the rule, used for overriding a rule by another one.

A product rule is overriden (i.e. disabled on a product) *if and only if* it meets all of these conditions:

- its scope is on the application distribution
- its key is not
`null`

- it has the exact same key than at least 1 other rule whose scope is on the product

## Setup a product rule

### Parameter list

The first step to define a Product Rule is to list the parameters managed by this rule.

Parameters are declared by name and type and they must match valid product parameters. See the product parameters for more details.

❗ This is an important modelling constraint to take into account :

parameters representing the same concept across different products should have the same name and type, and their possible values list often be similar.

Note: if any parameter declared in a rule is **not** present on a product, the rule is not applied on this product.

Note: all parameter types are supported in product rules:

Value (integer) | Type |
---|---|

1 | real |

2 | integer |

3 | boolean |

4 | string |

5 | color (not used) |

6 | material |

7 | product |

### Compatibility table

After parameters are listed, a product rule must provide a list of compatible values for each parameter. This takes the form of a compatibility table, with as many rows as needed to represent the business logic of the product rule.

❗ The trigger parameters should have all of their possible values defined in the product rule. If a user sets a value that is not present in a product rule, the engine will not know how to change the impacted parameter(s), thus leading to an error.

**Example**

This exemple is a very typical business situation for kitchen cabinets:

- There are 47 possible fronts
- There are 29 possible handles
- The 2 bottom aluminium framed fronts are each compatible with a single model of handle
- The "6 products" is the set of integrated handle fronts - these have "none" as the compatible handle list,
- The "39 products" is the set of remaining fronts: these can accomodate any handle.

### Definition via APIs

If the range is managed by APIs, please find below all the samples needed to provide JSON product rule.

#### Product Rule Types

```
{
"ruleTypeID": 2, // Possible values are 1, 2 or 3
}
```

#### Product Rule Version

```
{
"definition": {
"version": 2,
}
}
```

#### Product Rule Options and Values

For number parameters (real or integer) in discrete variation:

```
{
"definition": {
"parameters": [
{
"paramID": "myParamName",
"paramType": 1 // or 2 if the value is an integer
}
],
"compatibilities": [
[
{
"values": [
100,
200,
1000
]
}
]
]
}
}
```

For real parameters in continuous variation:

```
{
"definition": {
"parameters": [
{
"paramID": "myParamName",
"paramType": 1
}
],
"compatibilities": [
[
{
"range": {
"maxEx": 100, // Or "max" to include value
"minEx": 10 // Or "min" to include value
}
}
]
]
}
}
```

❗ Even if max value or min value is not mandatory individually, at least one of them is mandatory.

For integer parameters in continuous variation:

```
{
"definition": {
"parameters": [
{
"paramID": "myParamName",
"paramType": 2
}
],
"compatibilities": [
[
{
"range": {
"step": 2,
"maxEx": 100, // Or "max" to include value
"minEx": 10 // Or "min" to include value
}
}
]
]
}
}
```

❗ Even if max value or min value is not mandatory individually, at least one of them is mandatory.

For booleans parameters:

```
{
"definition": {
"parameters": [
{
"paramID": "myBooleanParamName",
"paramType": 3
}
],
"compatibilities": [
[
{
"values": [
true,
false
]
}
]
]
}
}
```

For string parameters:

```
{
"definition": {
"parameters": [
{
"paramID": "myStringParamName",
"paramType": 4
}
],
"compatibilities": [
[
{
"values": [
"value 1",
"value 2"
]
}
]
]
}
}
```

For product or material parameters:

```
{
"definition": {
"parameters": [
{
"paramID": "myIdsParamName",
"paramType": 7 // Or 6 in the case of materials
}
],
"compatibilities": [
[
{
"ids": [
"myID1",
"myID2"
]
}
]
]
}
}
```

### Full Samples

Thanks to the different rule types, parameters and compatibilities it is possible to combine different configurations

#### Rule between two product parameters

This rule defines a list of 2 fronts compatibles with 2 handles (or no handle), and a second list of 2 fronts only compatible with no handle.

```
{
"name": "myRuleName",
"ruleTypeID": 2,
"id": "MyRuleID",
"key": null,
"definition": {
"version": 2,
"parameters": [
{ "paramID": "front", "paramType": 7 },
{ "paramID": "handle", "paramType": 7 }
],
"compatibilities": [
[
{ "ids": [ "MyFront_1", "MyFront_2" ] },
{ "ids": [ null, "MyHandle_A", "MyHandle_B" ] }
],
[
{ "ids": [ "MyFront_4", "MyFront_5" ] },
{ "ids": [ null ] }
]
]
}
}
```

#### Rule between a boolean and a real parameters

This rule defines a range of possible values for the left drainer grooves dimension, depending on a boolean value. If the boolean is `true`

then dimensions allowed are `[10, 400]`

. If the boolean is `false`

then the only allowed dimension is `400`

. This kind of rule is usually used to deactivate a dimension field from the user perspective on some conditions (if corresponding product is deactivated for exemple).

```
{
"name": "MyRuleName",
"ruleTypeID": 2,
"id": "MyRuleID",
"key": null,
"definition": {
"version": 2,
"parameters": [
{ "paramID": "addDrainerGrooves", "paramType": 3 },
{ "paramID": "leftDrainerGroovesWidth", "paramType": 1 }
],
"compatibilities": [
[
{ "values": [ true ] },
{ "range": { "max": 400, "min": 10 } }
],
[
{ "values": [ false ] },
{ "values": [ 400 ] }
]
]
}
}
```

#### Rule with three parameters and a default value-set

This rule defines the relationship between the worktop, the sink mounting and the sink product. It has more than 3 parameters and is a chain rule (type 2) in version 2, so the first two parameters are implicitely linked together and act as the triggers. The last parameter `sink`

is the impacted parameter.

For worktops of group `group5`

, if the sink mounting is 0 or 1 there are only 2 available sinks (`sink_123`

and `sink_456`

) and if the sink mounting is 2, only `sink_456`

is available.

For any other combinations of worktop group and sink mounting, there are 5 available sinks. This example shows how the `default`

attribute can simplify greatly a product rule as it saves from providing all combinations of trigger parameter values.

```
{
"name": "MyRuleName",
"ruleTypeID": 2,
"id": "MyRuleID",
"key": null,
"definition": {
"version": 2,
"parameters": [
{ "paramID": "worktopGroup", "paramType": 4 },
{ "paramID": "sinkMounting", "paramType": 2 },
{ "paramID": "sink", "paramType": 7 },
],
"compatibilities": [
[
{ "values": [ "group5" ] },
{ "values": [ 0, 1 ] },
{ "ids": [ "sink_123", "sink_456" ] }
],
[
{ "values": [ "group5" ] },
{ "values": [ 2 ] },
{ "ids": [ "sink_456" ] }
]
],
"default": {
{ "ids": [ "sink_123", "sink_456", "sink_789", "sink_147", "sink_258" ] }
}
}
}
```

## Troubleshooting

In case of unexpected behavior, it is possible to see different messages in the console about applied configuration.

➡️️ Please refer to troubleshooting 🔗 section for more details.