This is a technical module that implements pre-defined Calculations that consist of Calculation Blocks used to compute different values based on various Odoo models. It works similar to Automated Actions however the main difference is that it returns result as a set of value that should be evaluated further in other Odoo modules.
Calculation
Each calculation consist of Calculation Lines which defines what will happen when calculation process will reach it.
Each Calculation Line has the following settings:
- Sequence. Positional order of the block in the calculation chain. Calculation blocks are processed in order from the lowest to the highest sequence number.
- Condition. Python expression that must be complied to run this line.
- Calculation Block that will be evaluated.
Table of contents
There are different cases when you need to calculate some values based on data that is located in different models. These values computation flow depends on different parameters and user should be able to configure them without having to have too much technical knowledge.
For example you need to calculate a car insurance premiums base on the following information:
- Driver's age. This data is located in the "Partners" model.
- Car engine displacement and power. This data is located in the "Cars" model.
- Region where an insurance is issued. This data is located in the "Insurance Offices" model.
- Current promo actions. This data is stored in the "Promos" model.
Here are some formula examples:
Formula A
If Driver's age is Between 18 and 21 AND Car BHP<=200HP then: Premium = BasePremium + (BasePremium * (1 + (Driver's Age -18)/10)) ) + AgeSurcharge + CarBHP* RegionalCoefficient
Formula B
If Driver's age is More than 21 then:
Premium = BasePremiumCurrentPromoDiscount + CarBHPRegionalCoefficient*CurrentPromoDiscount
However those formulas have a tendency to frequent changes and there should be an easy way to compose and update them without any coding and too much technical knowledge.
Activate the "Developer Mode".
To configure a Calculation
Go to "Settings/Technical/Calculations/Calculation" and create a new Calculation:
Name. Readable name of the Calculation.
Reference. This is a unique reference of the Calculation that will
be used in expressions. Must contain
CAPITAL_LETTERS_NUMBERS_EG_1_AND_UNDERSCORES_ONLY
Model. Base model used by the Calculation. Same as "model" keyword
in server actions.
Variables. List of pre-defined variables that will be populated to
the Calculation Blocks. Python expressions can be used same as in server
actions. Example (model = res.partner)
CITY_NAME = record.city_id.name SALE_TOTAL = record.sale_order_ids.amount_total DISCOUNT_PERCENT = 10
Blocks. List of calculation blocks and conditions to be met to
trigger them. Example (order, block, condition) 10, "Apply Discount",
SALE_TOTAL > 10000 and CITY_NAME.upper() == "NEW YORK"
To configure a Calculation Block
Go to "Settings/Technical/Calculations/Calculation Blocks" and create a new Calculation Block:
Name. Readable name of the Calculation Block.
Reference. This is a unique reference of the Calculation that will
be used in expressions. Must contain
CAPITAL_LETTERS_NUMBERS_EG_1_AND_UNDERSCORES_ONLY
Expression. Python expression. Must assign a value to the built-in
RESULT variable. Example:
discount_multiplier = (100-DISCOUNT_PERCENT)/100 RESULT["final_price"] = SALE_TOTAL * discount_multiplier Built-in variables
Following global and built-in variables are accessible from any expression:
RESULT: dictionary with values. Holds the current result of the
Calculation process as it is available at the moment of the expression
evaluation. You can also get the RESULT as it is available at the the
particular Calculation Block output. Those values are accessible using
CALCULATION_BLOCK_REFERENCE.RESULT
You must take care of which values are being stored there. In case of any value incompatibility and exception will be raised.
Calculation Block references are accessible globally within the Calculation Block
You can also define global variables. This variables are not connected to any specific calculation and are shared between all of them. They can be used as default parameters in case a value is not defined on the calculation level. Important! if you are using model properties in global variable values (eg record.partner_id.name) you must ensure that the model you are using such variables in has those properties. Global variable values are overridden by calculation defined values and by values propagated from code.
To trigger a calculation you need to call the "calculate(reference, records, **kwargs)" function of the "base.calculation" model and pass a Calculation reference, records and initial variable values as kwargs.
Example:
records_to_process = self.env["res.partner"].browse([1,3,4]) initial_values = {"DISCOUNT_PERCENT": 25, "DISCOUNT_POLICY": "maximum_discount"} result = selv.env["base.calculation"].calculate("SALES_DISCOUNT", records_to_process, **initial_values) This call will evaluate the "Compute Sales Order Discount"(ref="SALES_DISCOUNT") Calculation and assign the result to the "result" value.
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed feedback.
Do not contact contributors directly about support or help with technical issues.
- Cetmix
This module is part of the cetmix/calculation-engine project on GitHub.
You are welcome to contribute.


