Loading

Keeping Totals Correct

Defining a calculation does not by itself make anything happen. Each datastore that should calculate needs a table rule, and the timing matters.

The two rules

On the datastore, add a table rule with the action Run PHP Function.

  • Same-row formulas — function AMformula_rule, running before the save, because the values it produces are part of the record being written.
  • Rollups — function AMformula_rollupRule, running after the save, because it totals rows that must already be stored.

Both names are typed in by hand and are not validated when you save the rule, so a typo simply means nothing calculates. Check spelling first when a new definition appears to do nothing.

Where to attach the rollup rule

This is the step most often got wrong. A rollup is defined on the parent, but the total goes stale when a child changes. So the child datastore also needs a rule, so that adding, editing or deleting a line updates the invoice it belongs to. A calculation that works on creation but not on edit is almost always this.

Evaluation order

Where a datastore has several definitions they run in the sequence set by Order, lowest first. A line with net, then tax calculated from net, then gross adding the two, only works if each has a lower Order than the one that consumes it. Number them 10, 20, 30 rather than 1, 2, 3 so you can insert one later without renumbering.

Order applies within a single datastore. The relationship between a child and its parent is handled by the rule timing, not by Order.

The recalculation task

Table rules cannot catch changes that arrive by other routes — a bulk import, data extraction writing straight into a lines datastore, a correction applied directly to the database, a restored backup. The recalculation task is the safety net. It reads the audit trail for changed child rows, maps them back to their parents, and recalculates those parents.

It ships disabled. Enable it in Scheduled Tasks once your calculations are working, and run it overnight. If it is regularly correcting things, a table rule is missing somewhere — add the rule rather than running the sweep more often. After a large import, trigger it manually rather than waiting.

When a number looks wrong

Calculations fail quietly by design: a bad definition leaves its target column untouched and logs the reason, rather than writing a wrong number or blocking the save. That means a broken calculation looks like nothing happening.

  • Nothing calculates at all — the table rule, its function name, or its timing. Then check the definition is Enabled.
  • Works on creation, not on edit — the rule is attached to the header but not the lines.
  • The column keeps its old value — the definition could not be evaluated. Look in the error log for a renamed column, a misspelled function or unbalanced brackets.
  • The result is empty — a division by zero, or an input that is empty rather than zero.
  • Close but not exact — rounding. Decide which figure is authoritative, usually the rounded line, and total that column.
  • Wrong after an import — imports do not fire table rules. Run the recalculation task.