Skip to main content
Version: 4.0 preview

Calculation Authoring

Version
4.0 preview
Updated
View markdown

A functional description of how an admin builds calculations — the named, product-scoped formulas that produce a number (a price, a recurring price, a weight, or a min/max bound). This is the authoring/usage view: what you can express and how you build it. For how calculations are stored and evaluated, see technical/com_configbox_calculation_engine.md.

A calculation answers "given the customer's current selections, what number should this be?" It does nothing on its own — it only takes effect once assigned to a question/answer (as its price, recurring price or weight), used as a validation bound on a numeric question, referenced by another calculation, or referenced by a rule (the "Results of calculations" condition).


1. Creating a calculation

Each calculation belongs to one product and has:

  • Name — how you'll recognize and reference it (e.g. "Area price", "Volume discount factor").
  • Product — the product it applies to.
  • Type — the authoring style: Formula, Code, or Matrix (below). The type determines which editor you get.

You typically create several small calculations and compose them (one calculation can reference another), rather than one giant formula.

Picking the type comes down to the shape of the logic:

2. Where a calculation is used (how it takes effect)

A calculation only matters once it's referenced. The places an admin assigns a calculation:

  • Question → Price / Recurring Price / Weight Calculation — the question's contribution is computed by the calculation (instead of a static price).
  • Answer (Option Assignment) → Price / Recurring Price / Weight Calculation — overrides the answer's price/weight for that question with a calculation.
  • Question → Calculated Minimum / Maximum Value — a numeric/text question's allowed range is computed (e.g. "max length depends on the chosen material").
  • Inside another calculation — as a building block (the "Calculation" term/macro).
  • Inside a rule — the "Results of calculations" condition compares a calculation's result to a value (see the rule-authoring doc).

The number a calculation returns is the raw value. Currency conversion, customer-group price overrides and tax are applied automatically afterwards by the pricing layer — you author in the base currency and don't handle tax in the formula.

All the attachment points at a glance:


3. Authoring style A — Formula (visual builder)

A drag-and-drop editor where you assemble an arithmetic expression from terms. You drag terms from type tabs into the formula area, arrange them left-to-right, and group with brackets.

Verified live: the editor shows the Number box and + − * / operator buttons directly, plus tabs labelled Questions (= Element Attribute), Customer (= Customer Group), Calculations, and Functions. The Questions tab has a page filter + title search and a "Regarding Question" entry; each placed term shows an inline "or [fallback]" box; and the form lists where the calculation is in use (e.g. "Answer price calculation – 5/6/7").

Available term types (the building blocks):

  • Number — a literal value you type (e.g. 12, 0.25).
  • Operator+, , ×, ÷ and parentheses. These connect the other terms; normal arithmetic precedence applies, and brackets force grouping.
  • Element Attribute — a value taken from a question in the same product. You pick the question and which attribute:
    • Entry in … — the value the customer entered/selected (for number/slider/dropdown questions).
    • Price of … / Recurring Price of … — that question's computed price.
    • Question custom field in … — one of the question's custom fields.
    • Answer custom field in … / Global answer custom field in … — a custom field of the selected answer (assignment-level or option-level).
    • You can also reference the question this calculation is assigned to ("regarding" element), so one calculation can be reused on many questions and always read "its own" question.
    • A fallback value is used when the question has no value.
  • Calculation — the result of another calculation in the product (lets you compose; e.g. a "base area" calc reused by a "price" calc).
  • Customer Group field — a value from the current customer's group (a group custom field), so a formula can vary by customer segment.
  • Function — a function applied to its parameters (each parameter is itself a little formula you drop terms into):
    • Round — round a number (optionally to N decimal places).
    • Lowest value (min) / Highest value (max) — pick the smallest/largest of 2–4 values.
    • Custom functions — additional functions a developer has registered (see the technical doc); they appear in the Functions tab with named parameter slots.

Worked example — price = (width × height in m²) × €65, rounded to 2 decimals, where width and height are slider questions:

Round( Entry in "Width" × Entry in "Height" ÷ 1000000 × 65 , 2 )

You'd drop a Round function, and inside its first parameter build [Entry in Width] [×] [Entry in Height] [÷] [Number 1000000] [×] [Number 65], with 2 in the second parameter.

The same example as the terms you'd actually place:

Use Formula when the logic is arithmetic and benefits from being readable/reusable.


4. Authoring style B — Code (expression)

A free-text expression for when a formula is faster to type than to drag. You write normal math using:

  • Placeholders A–D — each bound (in the form) to a question; at runtime each becomes that question's entered value. (Set "Question for placeholder A/B/C/D".)
  • Macros:
    • Total / TotalRecurring — the running product total (regular / recurring).
    • QuestionSelection() — a question's entered value.
    • QuestionPrice() / QuestionPriceRecurring() — a question's price.
    • Calculation() — another calculation's result.
    • QuestionProperty(…) / RegardingQuestion(…) — attribute access / the assigned question.
  • Standard operators and parentheses.

Legacy spellings: CBX 3.x called these ElementEntry(), ElementPrice(), ElementPriceRecurring(), ElementAttribute() and RegardingElement(). The rename is a hard one — there are no aliases; the 3.5.2 update rewrote stored calc code in place, and any code arriving from outside (a customization, a hand-written import) has to be rewritten too. See migration-to-cb4/element-question-rename.md.

Worked examples:

  • Area pricing (A = width mm, B = height mm): A * B / 1000000 * 65
  • A surcharge of 25% of the order: Total * .25
  • Combine: Calculation(42) + QuestionPrice(37) * 2

The question's Price Multiplicator (set on the question) is applied to the code result, so you can keep the code per-unit and multiply by quantity at the question level.

Use Code for quick mathematical expressions, especially ones referencing totals or several questions.


5. Authoring style C — Matrix (lookup table)

A 2-D lookup table for "price depends on the combination of two inputs" (e.g. size × material, weight × zone). You define:

  • Column input and Row input, each either a Question (the customer's selection/value is the key) or another Calculation (its result is the key). (Set "…parameter type" = Question or Calculation, then pick the question/calc for rows and columns.)
  • The grid — the cell values, which you can type in or import from an .xls/.xlsx spreadsheet (handy for large tables).
  • Lookup Value (matching mode): Exact Value, Next higher value, or Next lower value — how an input that doesn't exactly hit a row/column header is matched (e.g. round up to the next size bracket).
  • Round Values to — snap the inputs to a step before matching (for numeric inputs).
  • Multipliers — the looked-up cell can be multiplied by a static multiplicator, by a question selection (a quantity question), and/or by a calculated multiplier (another calculation).

How a matrix turns its two inputs into a number:

Worked example — "Glass price" matrix: columns = "Width bracket", rows = "Thickness", cells = €/m²; lookup = Next higher value so an in-between width uses the next bracket up; multiply the cell by the "Quantity" question.

Use Matrix when pricing is naturally a table and doesn't follow a clean formula.


6. Composition, "regarding", and reuse

  • Compose small calculations: a calculation can reference others (formula "Calculation" term, code Calculation(id), or a matrix row/column input). Build a library of named pieces.
  • "Regarding" element lets one calculation be assigned to many questions/answers and always read the value/price of the question it's attached to — so you don't need a separate calc per question.
  • Calculations are product-scoped; copying a product copies its calculations and re-points all the internal references automatically.

A typical small library, composed:

7. Element attributes you can reference (quick list)

When a formula/code reads from a question, the available attributes are: the entered value, the price and recurring price, the question's custom fields, and the selected answer's custom fields (assignment-level and global-option-level). Custom-field labels come from global Configuration, so they appear under your own names.

8. Custom functions (extension)

Beyond Round/Min/Max, a developer can register additional functions (e.g. ceilTo, an external price lookup) that then appear in the Formula editor's Functions tab with named parameter slots — so admins can use them like built-ins. (How to add them: technical calc-engine doc.)

9. Practical notes

  • Calculations run on every selection change (live pricing), so keep them reasonably simple; deeply nested calc graphs cost performance.
  • Author in the base currency, ignore tax — conversion and tax happen after the result.
  • Numeric results — calculations are expected to return numbers (used as money/weight/bounds).
  • Validation bounds — a "Calculated Minimum/Maximum Value" on a question lets allowed input depend on other selections (e.g. max quantity depends on chosen package).

10. Notes for the refactor (functional observations)

  • Three authoring styles for one concept. Formula, Code and Matrix all produce "a number from selections." A refactor could unify them behind one calculation concept with interchangeable editors (visual / expression / table) rather than three separate types.
  • "Regarding" + reuse is valuable — the ability to write one calculation usable across many questions should be preserved (it's what keeps configurators maintainable).
  • Composition is a strength — calculations referencing calculations form a small dependency graph; making that graph explicit (and cycle-checked) would help.
  • Matrix is really "tabular pricing" with lookup semantics (exact/next-higher/next-lower) + multipliers + Excel import — a well-scoped feature worth keeping as a first-class option.
  • Regular vs. recurring are parallel everywhere; consider modeling "price kinds" generically.
  • Raw-number output with currency/tax applied afterwards is the right separation to keep.