Aggregator rules for Odoo
The operations within Odoo are achieved via Aggregators that use output keys with special syntax that make use of Odoo features.
The Konfoo module is pre-configured for creating Sale Order Lines, Products and BOMs (the most widely used use-case). See the configuration section below for how to reconfigure this.
Metadata reserved keys
Options available in the aggregator metadata block:
meta:
# looks up via `default_code` by default, can be configured in settings
template_product: "MYPRODUCT-001"
# when set to true will prefix the default product by parent record name
# for instance the Sale Order name the product is placed on after configuration
# default: true
use_parent_name_prefix: false
# delimiter used when use_parent_name_prefix is set to true
# default: " "
product_name_delimiter: ": "
# when this option is set and the newly configured product yields a value
# on the given field (`default_code`) then use the existing product
# instead of creating a new one
use_if_exists: default_code
# when set to true update the existing product
# instead of just re-using the existing product
update_if_exists: false
Aggregator rules
Odoo-specific key-syntax that can be used in aggregator rules:
- Assignment with a lookup:
some_record_id := my.model.reference_code: some lookup value
- Assignment from a locally created model:
some_field := a_field_on_the_rules_model: rule_name- Note that you can only reference models created by rules that operate in the same
domainand are created for the same instance of that particular domain.
- Assignment of a value computed in the aggregator
some_field: 1234
There are also some field names that are reserved and handled specially to facilitate Odoo functionality:
model- specifies which Odoo model to instantiate with this ruletemplate- (optional) specifies which Odoo model instance to copy as a basis when instatiating an object from this rule- Note that the
templatekey is usually paired with a lookup syntax (see examples below). While this is not mandatory it is generally the practical way of using this feature.
- Note that the
command- This is the operation Can be one of:create,read,write,rpc.create- This is the typical use-case. The record formodelis created with the values output by the rule.read- The objects limited byrecordsare read and stored in memory, accessible by this rule’s ID.write- The values created by the rule are written to objects limited byrecords.rpc- The objects limited byrecordsare looked up and the RPC method defined bymethodis called on them.
records- This facilitates Odoosearchlookups via a typical Odoo domain filter and is used together withcommand.method- This is the RPC method to call whencommandis set torpc.
Internal stuff:
__id__- This is the aggregator rule ID and is set by Konfoo. This allows other rules to refer to the output of another rule.__instance__- This is the Konfoo model instance ID. This allows differentiating between rule outputs of the same rule on multiple instances of the same data model.
Configuration
Konfoo always allows you to create instances of the following models:
mrp.bom.linemrp.routing.workcenterproduct.product
You can allow additional models in the Konfoo module under Technical → Allowed models.

Examples
Basic BOM line
Consider an aggregator like this:
rules:
- trafos:
domain: Light
require:
- self.product
- self.quantity
- util::lights_unit_is_continuous(self.product)
model: mrp.bom.line
product_id := product.product.default_code: TRAFO-0100
product_uom_id := uom.uom.name: pcs
product_qty: (expr) round(to_float(self.quantity) / 6.0 + 0.5)
From the output of this aggregator the Odoo module will:
- Know based on
modelvalue that this rule must create a newmrp.bom.lineinstance - Knows to look up the value for
product_idfromproduct.productusing Odoo DOM[('default_code', '=', 'TRAFO-0100')] - Knows to look up the value for
product_uom_idfromuom.uomby[('name', '=', 'pcs')] - Knows to set
product_qtyvalue to the value computed by the aggregator
Creating a new product
This example creates a new product.product instance based on a template product, sets some custom attributes and then uses it on a BOM line.
rules:
- window_glass_product:
domain: Window
require:
- self.material
- self.width
- self.height
model: product.product
template := product.product.default_code: GLASS-TEMPLATE
default_code: (expr) `GLASS-W${self.width}-H${self.height}`
product_width: (expr) self.width
product_height: (expr) self.height
- window:
domain: Window
require:
- self.material
- self.unit
- self.width
- self.height
model: mrp.bom.line
product_id := id: window_glass_product
product_uom_id := uom.uom.name: (expr) self.unit
product_qty: (expr) self.width * self.height
The first rule (window_glass_product) will:
- Create an instance of
product.product, but it will copy it from a product that hasdefault_codeset to'GLASS-TEMPLATE' - Override
default_codewith a computed value - Set the custom fields
product_widthandproduct_heightto the computed values
The second rule (window) will:
- Set
product_idvalue to the product generated in the previous rule for this instance ofWindow - Set
product_uom_idandproduct_qtyvalues just as in the previous example
RPC advanced example
rules:
- execute_rpc_to_create_product:
domain: MyModel
model: some.model
command: rpc
method: create_complex_product_hierarcy
require:
- self.code in [(), "1", "2"]
- self.another_param
records: (search) [('code', '=', '1234'), ('parent_id', '=', False)]
custom_values: (expr) util::compute_custom_values()
- use_created_product:
domain: MyModel
model: mrp.bom.line
require:
- self.code in [(), "1", "2"]
- self.another_param
product_id := id: execute_rpc_to_create_product
product_qty: 1