Back to ER Diagram
Budget Management

Budget Management & Commitment Tracking

Complete documentation of budget allocation, commitment tracking from approved Purchase Orders, spending from invoices, and variance analysis for financial control and planning.

PostgreSQL
9 Tables
Schema: planning
Multi-Dimensional

Budget Structure Overview

Budgets track financial allocations and spending across multiple dimensions. Each budget tracks three key amounts: allocated budget, committed (from approved POs), and spent (from paid invoices).

Budget Utilization Example

IT Department - Q1 2024 - Total Budget: $100,000
$35K Spent
$25K Committed
$40K Available
Spent (Invoice Paid)
Committed (PO Approved)
Available
3
Budget Types
3
Period Types
4
Transaction Types
Multi
Dimensions

Budget Types

OPERATIONAL

Day-to-day operating expenses. Typically monthly or quarterly budgets for recurring costs like supplies, services, and maintenance.

CAPITAL

Capital expenditure budgets for assets, equipment, and infrastructure. Usually annual with special approval workflows.

PROJECT

Project-specific budgets tied to a defined scope and timeline. Tracks spending against project milestones.

Period Types

  • ANNUAL - Full fiscal year
  • QUARTERLY - Q1, Q2, Q3, Q4
  • MONTHLY - Each month

Database Schema

planning.budgets

  • id - UUID primary key
  • company_id - Company scope
  • fiscal_year - Budget year
  • budget_type - OPERATIONAL, CAPITAL, PROJECT
  • department_id - Department allocation
  • cost_center_id - Cost center allocation
  • project_id - Project allocation
  • category_id - Item category allocation
  • gl_account_id - GL account allocation
  • budget_amount - Total allocated budget
  • committed_amount - Amount from approved POs
  • spent_amount - Amount from paid invoices
  • available_amount - Calculated remaining
  • period_type - ANNUAL, QUARTERLY, MONTHLY
  • period_number - Quarter/month number
  • status - DRAFT, APPROVED

planning.budget_line_items

  • id - UUID primary key
  • budget_id - Parent budget reference
  • transaction_type - COMMITMENT, RELEASE, SPEND, ADJUSTMENT
  • transaction_date
  • reference_type - PR, PO, INVOICE, ADJUSTMENT
  • reference_id - UUID of source document
  • reference_number - Document number
  • amount - Transaction amount (positive or negative)
  • description - Transaction description

planning.budget_change_requests

Budget change/revision requests

  • id - UUID primary key
  • request_number - Unique change request reference
  • budget_id - Target budget being modified
  • requested_by - User who initiated the change
  • change_type - INCREASE, DECREASE, REALLOCATION, SUPPLEMENTARY
  • current_amount - Budget amount before change
  • requested_amount - Proposed new budget amount
  • change_amount - Difference (positive or negative)
  • justification - Business reason for the change
  • status - DRAFT, SUBMITTED, APPROVED, REJECTED, CANCELLED
  • approved_by - Approving authority
  • approved_at - Approval timestamp

planning.budget_change_request_items

Line items in budget change requests

  • id - UUID primary key
  • change_request_id - Parent change request reference
  • budget_id - Specific budget line affected
  • category_id - Item category for the change
  • gl_account_id - GL account affected
  • current_amount - Current allocation for this line
  • proposed_amount - Proposed allocation
  • change_amount - Delta amount
  • remarks - Line-level justification

planning.budget_approvals

Budget approval workflow

  • id - UUID primary key
  • budget_id - Budget being approved
  • change_request_id - Optional link to change request
  • approval_level - Sequential approval stage number
  • approver_id - User designated as approver
  • approval_status - PENDING, APPROVED, REJECTED, ESCALATED
  • comments - Approver remarks
  • approved_at - Timestamp of approval action
  • delegated_from - Original approver if delegated

planning.budget_commitments

PO commitments against budgets

  • id - UUID primary key
  • budget_id - Budget being committed against
  • po_id - Purchase Order creating the commitment
  • po_number - PO reference number
  • committed_amount - Amount reserved from budget
  • released_amount - Amount released back (cancellation/invoice)
  • spent_amount - Amount converted to actual spend
  • status - ACTIVE, PARTIALLY_RELEASED, FULLY_RELEASED, CANCELLED
  • committed_at - Timestamp of commitment creation
  • released_at - Timestamp of final release

planning.annual_procurement_plans

Annual procurement planning

  • id - UUID primary key
  • company_id - Company scope
  • fiscal_year - Planning year
  • department_id - Department submitting the plan
  • category_id - Procurement category
  • item_description - Description of planned procurement
  • estimated_quantity - Planned quantity
  • estimated_unit_price - Estimated unit cost
  • estimated_total - Total estimated spend
  • planned_quarter - Target quarter for procurement
  • procurement_method - OPEN_TENDER, LIMITED_TENDER, DIRECT, RATE_CONTRACT
  • budget_id - Linked budget allocation
  • status - DRAFT, SUBMITTED, APPROVED, IN_PROGRESS, COMPLETED
  • created_by - Plan creator

Budget Amount Calculations

Key Formulas

Available Amount = budget_amount - committed_amount - spent_amount
Utilization % = (committed_amount + spent_amount) / budget_amount * 100
Spent % = spent_amount / budget_amount * 100

Field Updated By Direction Description
budget_amount Budget approval Set Initial allocation from finance
committed_amount PO approval + Increase Reserved when PO is approved
committed_amount PO cancellation - Decrease Released when PO is cancelled
spent_amount Invoice posting + Increase Actual spend recorded
committed_amount Invoice posting - Decrease Commitment converted to spend

Budget Transactions

PR Created
Budget Check
PR Approved
PO Approved
COMMITMENT Created
Invoice Approved
SPEND + RELEASE
Transaction Type Triggered By Effect
COMMITMENT PO Approval Increases committed_amount, decreases available
RELEASE PO Cancellation or Invoice Decreases committed_amount, increases available
SPEND Invoice Posting Increases spent_amount, decreases available
ADJUSTMENT Manual Adjustment Budget reallocation or correction

Budget Check Process

Budget validation occurs at PR submission and PO creation to prevent overspending:

-- Check budget availability before PO approval
WITH budget_check AS (
    SELECT
        b.id AS budget_id,
        b.budget_amount,
        b.committed_amount,
        b.spent_amount,
        b.budget_amount - b.committed_amount - b.spent_amount AS available,
        :po_amount AS requested_amount
    FROM planning.budgets b
    WHERE b.company_id = :company_id
      AND b.fiscal_year = :fiscal_year
      AND b.department_id = :department_id
      AND b.cost_center_id = :cost_center_id
      AND b.status = 'APPROVED'
)
SELECT
    budget_id,
    available,
    requested_amount,
    CASE
        WHEN available >= requested_amount THEN 'SUFFICIENT'
        WHEN available > 0 THEN 'PARTIAL'
        ELSE 'INSUFFICIENT'
    END AS budget_status
FROM budget_check;

Over-Budget Handling

When budget is insufficient, options include: (1) Request budget increase, (2) Obtain exception approval from finance, (3) Defer purchase to next period, (4) Reallocate from another budget.

Commitment Lifecycle

-- Create commitment on PO approval
BEGIN;

-- Record commitment transaction
INSERT INTO planning.budget_line_items (
    budget_id, transaction_type, transaction_date,
    reference_type, reference_id, reference_number, amount, description
) VALUES (
    :budget_id,
    'COMMITMENT',
    CURRENT_DATE,
    'PO',
    :po_id,
    :po_number,
    :po_amount,
    'PO commitment for ' || :po_number
);

-- Update budget committed amount
UPDATE planning.budgets
SET
    committed_amount = committed_amount + :po_amount,
    available_amount = budget_amount - committed_amount - :po_amount - spent_amount
WHERE id = :budget_id;

COMMIT;
-- Convert commitment to spend on invoice posting
BEGIN;

-- Release commitment
INSERT INTO planning.budget_line_items (
    budget_id, transaction_type, reference_type, reference_id, amount, description
) VALUES (
    :budget_id, 'RELEASE', 'INVOICE', :invoice_id,
    -:committed_amount, 'Release commitment for invoice ' || :invoice_number
);

-- Record spend
INSERT INTO planning.budget_line_items (
    budget_id, transaction_type, reference_type, reference_id, amount, description
) VALUES (
    :budget_id, 'SPEND', 'INVOICE', :invoice_id,
    :invoice_amount, 'Invoice spend ' || :invoice_number
);

-- Update budget amounts
UPDATE planning.budgets
SET
    committed_amount = committed_amount - :committed_amount,
    spent_amount = spent_amount + :invoice_amount,
    available_amount = budget_amount - committed_amount + :committed_amount - spent_amount - :invoice_amount
WHERE id = :budget_id;

COMMIT;

Query Examples

Budget Utilization by Department

SELECT
    d.department_name,
    b.budget_type,
    b.fiscal_year,
    b.budget_amount,
    b.committed_amount,
    b.spent_amount,
    b.available_amount,
    ROUND((b.committed_amount + b.spent_amount) / b.budget_amount * 100, 2) AS utilization_pct,
    ROUND(b.spent_amount / b.budget_amount * 100, 2) AS spent_pct
FROM planning.budgets b
JOIN organization.departments d ON b.department_id = d.id
WHERE b.company_id = :company_id
  AND b.fiscal_year = :fiscal_year
  AND b.status = 'APPROVED'
ORDER BY utilization_pct DESC;

Budget Transaction History

SELECT
    bt.transaction_date,
    bt.transaction_type,
    bt.reference_type,
    bt.reference_number,
    bt.amount,
    bt.description,
    SUM(bt.amount) OVER (
        PARTITION BY bt.budget_id
        ORDER BY bt.transaction_date, bt.created_at
    ) AS running_balance
FROM planning.budget_line_items bt
WHERE bt.budget_id = :budget_id
ORDER BY bt.transaction_date DESC, bt.created_at DESC;

Budget vs Actual Variance

SELECT
    d.department_name,
    cc.cost_center_name,
    b.budget_amount AS budgeted,
    b.spent_amount AS actual,
    b.budget_amount - b.spent_amount AS variance,
    CASE
        WHEN b.spent_amount > b.budget_amount THEN 'OVER'
        WHEN b.spent_amount < b.budget_amount * 0.9 THEN 'UNDER'
        ELSE 'ON_TRACK'
    END AS variance_status
FROM planning.budgets b
JOIN organization.departments d ON b.department_id = d.id
LEFT JOIN organization.cost_centers cc ON b.cost_center_id = cc.id
WHERE b.fiscal_year = :fiscal_year
  AND b.period_type = 'QUARTERLY'
  AND b.period_number = :quarter
ORDER BY variance;

Best Practices

Regular Monitoring

Review budget utilization weekly. Set up alerts for budgets approaching 80% utilization to allow time for adjustments.

Timely Updates

Ensure commitments are recorded immediately upon PO approval. Delayed entries lead to inaccurate availability and potential overspending.

Variance Analysis

Investigate significant variances (>10%) between budget and actual. Understanding root causes improves future budget accuracy.