Formulas and Rollups
A datastore can carry values the platform works out rather than somebody typing them. There are two kinds.
Where to find it
Architect Panel → ERP - Setup:
- Calculated Fields — formulas and rollups, as a flat typed list
Architect Panel → Automation:
- Tasks — the recalculation task, which ships disabled
Formula and rollup
- Formula — arithmetic over other columns of the same row. Quantity multiplied by unit price.
- Rollup — an aggregate over a child table. The sum of line values across an invoice’s lines.
A definition names the table and target column, its kind, and then either an expression or the aggregate, source table, link, field and filter.
Why server-side matters
Arithmetic used to happen only in the browser, on line-item grids. A value computed in the browser is a value the user can change, nothing recomputed it on save, and nothing could aggregate it.
That is adequate for a display total and not adequate for anything you bill from.
Five aggregates
Sum, count, average, minimum and maximum. Count is the one that works without naming a source field, since it is counting rows rather than adding values.
The expression language is small on purpose
Arithmetic over columns, with a whitelisted set of functions: rounding, absolute value, floor, ceiling, a three-argument conditional, and a coalesce taking any number of arguments.
That is deliberately less than a general language, and the smallness is the feature.
There is no path to executing code
Expressions are tokenised, compiled against a fixed operator table and the whitelisted functions, and evaluated by a loop. A stored expression cannot reach PHP or SQL. Rollups build their query from validated identifiers with every value bound.
Worth knowing, because two older field types in the platform do evaluate authored code, and this deliberately repeats neither.
A failure leaves the field alone
The behaviour to understand before relying on this. An unknown column, a malformed expression or an unknown function writes an error to the log and leaves the target field untouched. It is not set to zero, and the save is not blocked.
The reasoning is that a wrong number silently written to a money column is the worst outcome, and blocking every save on a configuration typo is the second worst. The field keeps its previous value and the error is in the log.
Which means: check the log. A field that quietly stopped updating looks exactly like one whose inputs have not changed.
Division by zero produces nothing
The field is skipped rather than set to zero or an error — matching how a database behaves rather than how PHP does.
Round money explicitly
Evaluation is in floating point, and the module does not guess a scale. Wrap money expressions in a rounding function to two places and make the target column a fixed-decimal type.
Skipping this produces totals that are a penny out, occasionally, in a way that is very tedious to trace.
Recalculation is a task, and it ships disabled
A scheduled task exists to recompute stored rows in batch. It is installed switched off, so turning it on is a decision — and one worth making, because otherwise a definition changed today does not reach records saved yesterday.
Worked example
An invoice line carries a formula rounding quantity times unit price to two places, into a fixed-decimal column. The invoice header carries a rollup summing those line values, filtered to non-cancelled lines. A definition typo was found in the error log rather than in an incorrect invoice, because the field had kept its previous value.
Recommendations
- Round money explicitly and use fixed-decimal columns.
- Watch the error log — a failed calculation is silent by design.
- Enable the recalculation task deliberately if you change definitions.
- Filter rollups so cancelled or draft children do not count.