Finance Concepts
This page explains the FP&A domain concepts implemented in the engine. It's useful background for developers integrating with the API or extending the service layer.
Variance Analysis
A variance is the difference between a budgeted amount and an actual amount for a given GL account, department, and fiscal period.
variance_abs = actual - budget
variance_pct = (actual - budget) / budget x 100
Whether a variance is good or bad depends on the account type - see Favourability below.
Favourability
A cost going over budget is bad. Revenue coming in above budget is good. The engine handles both correctly using a favour_high flag on each GL account.
| Account type | favour_high |
Favourable when... |
|---|---|---|
| Revenue | true |
actual > budget (more revenue than planned) |
| COGS | false |
actual < budget (cost of goods came in under) |
| OPEX | false |
actual < budget (operating expenses under control) |
| CAPEX | false |
actual < budget (capital spend under plan) |
| Headcount | false |
actual < budget (salary/contractor cost under plan) |
The status field in variance responses is "favourable" or "unfavourable" based on this logic. It is not simply positive or negative variance - a cost account coming in -5% is favourable, while a revenue account coming in -5% is unfavourable.
Budget Versioning
The engine stores the original budget and up to three forecast revisions as separate version records. This enables three-way comparison (original vs. forecast vs. actual) without overwriting any history.
| Version | Meaning |
|---|---|
original |
The approved annual budget set at the start of the fiscal year |
forecast1 |
First intra-year revision (e.g. Q1 reforecast) |
forecast2 |
Second revision (e.g. Q2 reforecast) |
forecast3 |
Third revision (e.g. Q3 reforecast) |
All variance endpoints accept a version query parameter. Comparing forecast3 actuals against original shows how far the year moved from plan; comparing against forecast3 shows execution accuracy against the latest expectation.
GL Account Types
Accounts are typed to drive both P&L rollup structure and favourability logic.
| Type | Description | favour_high |
|---|---|---|
revenue |
Top-line income | true |
cogs |
Cost of Goods Sold - direct costs of delivering revenue | false |
opex |
Operating expenses - Sales, Marketing, G&A, R&D | false |
capex |
Capital expenditure - depreciable assets | false |
headcount |
Salaries, benefits, and contractor costs | false |
Fiscal Periods
Periods are stored as integers 1-12, decoupled from calendar months. This means the schema supports fiscal years that start in any calendar month (e.g. a company with a July fiscal year start uses period 1 = July, period 12 = June).
When loading actuals from an ERP, map your ERP's period numbering to the engine's period integers at ingest time.
Actuals Idempotency
The actuals ingest endpoint is idempotent by the combination of (fiscal_year, fiscal_period, department_id, gl_account_id). Posting the same combination twice updates the amount - it does not create a duplicate row. This makes it safe to re-run ERP export feeds without needing to truncate and reload.
Alert Threshold
The /variance/alerts endpoint returns only GL lines where the absolute variance percentage exceeds a configurable threshold (default 10%). This is useful for building exception-based monitoring: rather than reviewing every line, finance teams see only the ones that materially deviated from plan.
The threshold applies to abs(variance_pct), so it flags both over-budget costs and under-budget revenue.