Budget-Comparison Reports — Account Variance & Budget¶
Date: 2026-07-01
Problem / motivation¶
Peachtree's General Ledger and Financial-Statement sections compare actuals to a budget: Account
Variance ("actual amount, budget amount, variance amount, and variance percent … by selected
accounts"), the Budget report ("budget amounts for the period and year-to-date"), and the
Income/Budget statement family. We ship Budgets (budgets + budget_lines, per account
per period) and posted ledger actuals, so this joins the two into a variance report and surfaces the
budget itself. Phase 3 of the Peachtree Report Parity tracker.
In scope¶
account_variance(budget_id, date_filter, start_period, end_period, account_types?, generate_csv)— per account: budgeted amount (sum of budget lines in the period range), actual (posted ledger activity in the account's natural balance direction over the date range), variance, and variance %. Optionalaccount_typesfilter makes it serve the Income/Budget view (filter to revenue/expense).budget_report(budget_id, generate_csv)— the budget's amounts per account per period (a flat listing the frontend can pivot to period + YTD).- Posted actuals only.
Path.REPORTS. CSV-exportable.
Out of scope¶
- Account Variance – Dual Budgets and the multi-column Income/Budget-YTD statement layouts — the underlying actual-vs-budget data is delivered here; the dual-budget/statement presentation is deferred.
- Balance Sheet/Budget layout (same data restricted to balance-sheet accounts via
account_types).
Data model changes¶
None. Reads budgets / budget_lines (account_id, period_number, amount) and posted
ledger_entries / ledger_entry_lines joined to accounts. No migration, no new Path/Resource.
What's being implemented¶
- Responses —
app/graphql/reports/strawberry/budget/budget_report_response.py(AccountVarianceLineResponse,BudgetLineReportResponse). - Repository —
app/graphql/reports/repositories/budget/budget_report_repository.py(budget_by_account,actuals_by_account,budget_lines). - Service —
app/graphql/reports/services/budget/budget_report_service.py(merges + natural-signs). - Queries —
app/graphql/reports/queries/budget/budget_report_queries.py. - Tests —
tests/graphql/reports/test_budget_reports.py.
GraphQL surface¶
accountVariance(budgetId: UUID!, dateFilter: DateRangeFilter!, startPeriod: Int! = 1, endPeriod: Int! = 12, accountTypes: [AccountType!], generateCsv: Boolean! = false): GenericReportPage!
budgetReport(budgetId: UUID!, generateCsv: Boolean! = false): GenericReportPage!
type AccountVarianceLine { accountCode: Int!, accountName: String, accountType: AccountType!, budgetAmount: Decimal!, actualAmount: Decimal!, varianceAmount: Decimal!, variancePct: Decimal! }
type BudgetLineReport { accountCode: Int!, accountName: String, periodNumber: Int!, amount: Decimal! }
Frontend contract¶
- Account Variance: pass a budget id, an actuals date range, and the fiscal period range for the
budget columns; optional
accountTypesto scope (e.g. revenue+expense for an Income/Budget view).actualAmountis already in each account's natural sign;varianceAmount = actual − budget. - Budget: flat
BudgetLineReportrows (account × period); pivot client-side for period + YTD totals. generateCsv: true→csvUrl.
Future additions¶
- Dual-budget comparison and the multi-column Income/Budget-YTD statement layouts.