Aggregators
Konfoo provides a general purpose aggregator framework for generating of all sorts of outputs based on the initial configuration.
Some common use-cases:
- Bill of materials
- Estimates (time, cost, etc)
- Summaries
- Work instructions
Aggregators are described as a set of rules that all can be applied to some Domain Entity in the configuration state.
Each aggregator accepts the following root level keys:
options
- Options for the aggregator:name
- optional, default:null
path
- required, used to access the aggregator results by 3rd partiesstrip_empty
- optional, enables the feature to strip rule outputs that are designated "empty"
meta
- Provides options to send per-configuration metadata to 3rd party systemsrules
- List of Aggregator Rules
To add the aggregator to your Konfoo project you must include it in the aggregators
section in your main domain definition file:
options:
aggregators:
- bom.yml
The example below illustrates a bill of materials ruleset for calculating the amount of clay needed to make the Mug
from previous chapters.
# General options for this aggregator
options:
name: Bill of materials # optional, default: null
path: bom # required
# `path` is used in the output url: <konfoo-host>/agg/bom/<session>
# `------------------------------------------------ยดยดยด
# Takes a list of rule output object fields
# If the output object has any such field and
# and the value on the field is () or 0 the rule's output is discarded
strip_empty:
- product_qty
# Metadata - usually to provide extra information to 3rd party software
meta:
template_product: KONFOO-TEMPLATE
name: |
(expr)
if root.fields.project_name != () {
`MUG-{root.fields.height}-{root.fields.diameter}`
} else { () }
a_static_value: 42
# The actual aggregator rules
rules:
- amount_of_clay:
domain: Mug
require:
- self.height
- self.diameter
product_code: CLAY-001
unit: g
product_qty: |
(expr) clay_calculations::calculate_mug_clay(self.height, self.diameter)
- clay_for_handle:
domain: Mug
require:
- self.has_handle
product_code: CLAY-001
unit: g
product_qty: (expr) clay_calculations::calculate_handle_clay(self.height)
The above aggregator would then yield the following structure from the aggregator endpoint:
(e.g. by curl https://<konfoo-host>/agg/bom/<configuration-id>
)
{
"data": [
{
"__id__": "amount_of_clay",
"product_code": "CLAY-001",
"product_qty": 390,
"unit": "g"
},
{
"__id__": "clay_for_handle",
"product_code": "CLAY-001",
"product_qty": 78,
"unit": "g"
}
],
"meta": {
"product_name": "MUG-440-120",
"a_static_value": 42
},
"name": "Bill of materials"
}
Aggregator rules
Rules for defining aggregator rules:
- Every rule entry has a few reserved keywords:
domain
- Domain Entity name this rule is for, defaults to theroot
Domain Entityrequire
- List of expressions that must evaluate to a "truthy" value for this rule to be evaluatedcustom
- Allows overriding the output of the rule by returning an Map object yourself
- This does not require
(expr)
prefix - Any other fields besides the reserved ones are ignored when custom is present
- Every other key in the rule object is exported to output
- If a value for a key is prefixed by
(expr)
it is considered code and is evaluated when the aggregated result is requested - The evaluated expression is expected to return a value, but that is not enforced (null is OK)
- Every rule in the
rules
list is executed sequentially - Every key in the rule is evaluated in order of declaration
- Each rule is executed with it's own fresh scope - meaning variables defined in a previous key are available in the next
- Rule is only executed if every expression in
require
evaluates to a "truthy" value - Rules are expanded for every instance of the Domain Entity set
domain
- meaning one rule could be executed multiple times if there are multiple instances of a Domain Entity in the configuration - Every rule has access to the same script modules and APIs as compute functions
- The
self
constant refers to the specific Domain Entity instance the rule is currently being evaluated for
Let's look at one of the rules from the above example more closely:
rules:
# This is the ID of the rule.
# One rule could have multiple results in the aggregated object and this
# provides a trace back to from which rule the object originated from.
# This value is always present on the "__id__" field in the output.
- amount_of_clay:
domain: Mug # References the Domain Entity this rule deals with; default: root model
# Here we require that `height` and `diameter` fields of Mug are set
require:
- self.height
- self.diameter
# These two are static string values
product_code: CLAY-001
unit: g
# This value is calculated by a function in a script module
product_qty: |
(expr) clay_calculations::calculate_mug_clay(self.height, self.diameter)