Budgeting, Commitments, and Availability Control

Budget in an ERP is not a spreadsheet. It’s an enforceable control that can stop a purchase order from being created.

The vocabulary

Term Meaning
Plan Expected figures, informational, used for variance reporting
Budget Authorised spending limit, potentially enforced
Commitment Money legally promised but not yet spent (an open purchase order)
Actual Money spent (posted expense)
Available Budget − commitments − actuals
Encumbrance US/public sector term for commitment
Obligation A commitment that has become legally binding
Release Portion of an annual budget made available for a period
Supplement / return Increase / decrease of budget in-year
Carry-forward Unused budget moved to next year

Why commitments matter

Annual budget for cost centre IT:           1,200,000
Actual expenses posted to date:               800,000
Naive "available":                            400,000     ← WRONG

Open purchase orders not yet received:        350,000
Purchase requisitions approved:                80,000
─────────────────────────────────────────────────────
Actually available:                           (30,000)    ← already over

Without commitment tracking, budget control is fiction. By the time expenses post, the money is already spent. This is why the commitment is created at requisition or PO time, before any accounting entry exists.

Commitment lifecycle:

Purchase requisition approved  → commitment created         +80,000
Converted to purchase order    → commitment moves to PO      (reclassified)
Goods received                 → commitment reduced, actual created
Invoice posted                 → actual finalised
PO closed / deleted            → residual commitment released

Commitments are stored in a separate line-item table, not in the GL, because they are not accounting transactions.

Availability control

The check that runs before a spending document can be saved.

Tolerance levels on a budget:
  80% consumed  → warning message, log it
  95% consumed  → warning + email to budget owner
 100% consumed  → hard error, document cannot be saved
 110% consumed  → error, requires budget supplement

Configuration decisions:

  • What’s checked — requisitions, POs, invoices, journals, travel requests?
  • At what level — cost centre, project, WBS element, fund, GL account group?
  • Annual or periodic — can you use Q4’s budget in Q1?
  • Who can override — and is the override logged and reported?

Public sector runs this hard. Government and university ERPs (Fund Management / Public Sector Management) treat exceeding budget as legally impermissible, not merely undesirable. Commercial companies usually run warnings only.

Budget dimensions

Budgets are set at some combination of:

  Cost centre × GL account × period
  Project / WBS element × cost element
  Fund × functional area × grant × budget period    ← public sector
  Profit centre × product group
  Sales region × sales rep                          ← revenue budgets

The finer the dimension, the more accurate the control and the more maintenance pain. Most companies budget at cost centre × account group × year, and release quarterly.

Planning processes

Top-down

Management sets the total; it cascades down with allocation rules. Fast, often unrealistic.

Bottom-up

Cost centre managers submit; finance consolidates. Realistic, slow, and everyone pads their numbers.

Iterative

Top-down targets, bottom-up detail, negotiated over rounds. What actually happens.

Rolling forecast

Instead of a fixed annual budget, re-forecast 12–18 months ahead every quarter. Better in volatile markets; requires much better tooling.

Zero-based budgeting

Every line justified from zero each cycle rather than “last year + 5%”. Effective at cutting cost, exhausting to run.

Driver-based planning

Model the business, not the accounts: headcount × average salary, units × material cost, revenue × commission rate. Changes to a driver flow through automatically. This is what modern planning tools (Anaplan, Board, SAP Analytics Cloud, Oracle EPM Planning) are built for, and it’s far better than typing numbers into account cells.

Budget versions

You always need more than one:

Version 0  — Actual
Version 1  — Original approved budget (frozen, never edited)
Version 2  — Current forecast
Version 3  — Best case
Version 4  — Worst case
Version 5  — Prior year actuals (for comparison)

Version 1 must be immutable after approval. “Budget vs actual” is meaningless if the budget quietly moved. If someone needs to change it, that’s a supplement — a tracked, approved delta, not an edit.

Variance reporting

Cost centre IT, March 2026
                        Budget    Actual   Variance    %      Commitment  Available
Salaries               450,000   462,000   (12,000)  (2.7%)           0    (12,000)
Software licences      120,000    95,000    25,000   20.8%      40,000    (15,000)
Hardware                80,000    31,000    49,000   61.3%      95,000    (46,000)
Travel                  25,000    18,500     6,500   26.0%       2,000      4,500
Consulting             200,000   210,000   (10,000)  (5.0%)      60,000    (70,000)
──────────────────────────────────────────────────────────────────────────────────
Total                  875,000   816,500    58,500    6.7%     197,000   (138,500)

The “Actual” column looks like a 6.7% underspend. The “Available” column shows a 138,500 overrun. This is the report that justifies the whole commitment mechanism.

Sign convention: pick one (favourable positive, or actual-minus-budget) and apply it everywhere. Mixed conventions in one report are a guaranteed misreading.

Capital vs operating budgets

  • OpEx budget — annual, by cost centre, hits P&L
  • CapEx budget — per project/asset, multi-year, hits the balance sheet then depreciates

CapEx has its own approval flow (AFE — Authorisation for Expenditure, or capital appropriation request) with thresholds: under 50k the plant manager approves, over 5M the board does. The AFE is linked to an internal order or WBS that collects the cost and settles to an asset. See Fixed Assets.

Data model

budget_version(id, company_id, fiscal_year, code, name, status, locked_at)

budget_line(
  version_id, company_id, fiscal_year, period,      -- period NULL = annual
  cost_center_id, gl_account_id, project_id, fund_id,
  amount, currency,
  UNIQUE(version_id, fiscal_year, period, cost_center_id, gl_account_id, project_id)
)

budget_change(                                       -- supplements/returns, audited
  id, version_id, budget_line_key, delta_amount,
  reason, requested_by, approved_by, approved_at
)

commitment_line(                                     -- not in the GL
  id, company_id, source_type,                       -- PR | PO | CONTRACT | TRAVEL
  source_document, source_line,
  cost_center_id, gl_account_id, project_id,
  fiscal_year, period,
  amount_original, amount_open, currency,
  status,                                            -- OPEN | PARTIAL | CLOSED
  created_at, closed_at
)

Availability check implementation

function checkAvailability(costObject, account, period, amount):
    budget      = sum(budget_line where matching, version = approved)
                + sum(budget_change approved)
    actuals     = sum(journal_line where matching)
    commitments = sum(commitment_line.amount_open where matching)

    available   = budget - actuals - commitments
    consumed_pct = (actuals + commitments + amount) / budget

    if consumed_pct > hard_limit:   return ERROR
    if consumed_pct > warn_limit:   return WARNING
    return OK

Performance notes:

  • This runs on every requisition, PO, and invoice save. It must be fast.
  • Aggregating three tables on every check does not scale. Maintain a budget consumption summary per (cost object, account, period), updated transactionally, with a nightly rebuild-and-compare job.
  • Watch for the classic race: two users each check “available = 10,000”, both save 8,000. Serialise the check and the write on the budget key, or accept overrun and detect it after the fact — a real design choice, and public sector must take the serialised option.

Practical rules

  1. Commitments or your budget control is decorative.
  2. Freeze the approved budget version. Changes go through tracked supplements.
  3. Warn early (80%), block late (100%) — blocking at 100% with no warning creates month-end chaos.
  4. Release annual budgets by period if seasonality matters, otherwise Q1 spends the year.
  5. Every override is logged and reported to the budget owner. An unlogged override is a control failure.
  6. Reconcile: commitments open in the budget system = open PO value in purchasing. They drift; a weekly check catches it.
  7. Close stale commitments. POs left open for years hold budget hostage. Run an ageing report and a closure process.

Next