This pipeline handles the full FP&A budget cycle for QBO-connected clients:
Both modes output Excel workbooks in a standard suite format (Calibri, dark header, F/U coloring, CDC log).
scripts/pipelines/budget-builder.py
.cache/budget-builder/{slug}_budget_{year}.json # Budget file for Mode B
.cache/budget-builder/{slug}_cdc.json # CDC accuracy tracker
base_monthly_avg × seasonal_index × growth_factor| Tab | Contents |
|---|---|
| --- | --- |
| Budget Summary | Annual KPI totals + monthly Revenue/EBITDA grid |
| Monthly Detail | All line items × 12 months + Annual total |
| Assumptions | Growth method, rate, base avg, annual budget per account |
| Seasonal Patterns | Monthly indices, strength, peak/trough months per account |
# Basic — use default growth rates (revenue +5%, COGS +3%, expenses +3%)
python3 budget-builder.py --slug <client-slug> --build --year 2026
# Custom growth assumptions
python3 budget-builder.py --slug <client-slug> --build --year 2026 --assumptions growth.json
# With manual overrides for specific accounts
python3 budget-builder.py --slug <client-slug> --build --year 2026 --overrides overrides.csv
# Custom output directory
python3 budget-builder.py --slug <client-slug> --build --year 2026 --out ~/Desktop/reports
{
"global": {
"income": 0.08,
"cogs": 0.04,
"expense": 0.03
},
"overrides": {
"Rent": {"method": "flat"},
"Software Subscriptions": {"method": "pct_growth", "rate": 0.12},
"Total Income": {"method": "pct_growth", "rate": 0.08}
}
}
Methods:
pct_growth (default) — apply percentage growth rate to trailing averageflat — no growth from trailing average (rate = 0)For hard-coded monthly amounts that override the calculated budget:
account,section_type,2026-01,2026-02,2026-03,...,2026-12
Rent,expense,3500,3500,3500,...,3500
Owner's Draw,expense,8000,8000,8000,...,8000
Columns: account + section_type + one column per YYYY-MM (or Jan/Feb/Mar shorthand).
| Tab | Contents | ||
|---|---|---|---|
| --- | --- | ||
| Variance Summary | Headline KPIs + all material variances | ||
| Monthly Detail | All line items × closed months (Budget \ | Actual \ | Var per month) |
| Material Flags | Sorted by $ variance + monthly trend + action prompts | ||
| Rolling Forecast | Full-year forecast by account (gray=closed, blue=forecasted) | ||
| Management Commentary | WHAT/WHY/ACTION/OUTLOOK per material variance (draft) | ||
| CDC Log | Budget accuracy tracker + systematic bias analysis |
# Default: compare through last completed month, use cached budget
python3 budget-builder.py --slug <client-slug> --compare
# Specify through month
python3 budget-builder.py --slug <client-slug> --compare --through 2026-02
# Use explicit budget file
python3 budget-builder.py --slug <client-slug> --compare --budget-file ~/Desktop/Budget_client_2026.json
# Use manually-prepared budget CSV
python3 budget-builder.py --slug <client-slug> --compare --budget-file my_budget.csv
# Custom output
python3 budget-builder.py --slug <client-slug> --compare --through 2026-03 --out ~/Desktop/reports
If the budget was prepared outside this tool (e.g., in Excel), export as:
account,section_type,2026-01,2026-02,...,2026-12
Total Income,income,50000,52000,...,85000
Cost of Goods Sold,cogs,15000,15600,...,25500
Rent,expense,3500,3500,...,3500
| Category | $ Threshold | % Threshold |
|---|---|---|
| --- | --- | --- |
| Revenue | ≥ $2,500 | ≥ 5% |
| Expenses | ≥ $2,500 | ≥ 10% |
Both conditions use OR logic — either trigger alone is enough to flag.
IS SEASONAL = YESExample: Q4 revenue spike → indices for Oct/Nov/Dec will be > 1.0, Q1-Q2 will be < 1.0. Budget will correctly allocate more to Q4.
Closed months: Actual values locked in (not adjusted)
Open months: Budget × blend_factor
blend_factor = (0.70 × ytd_factor) + (0.30 × 1.0)
ytd_factor = actual_YTD / budget_YTD
FORECAST_TREND_WEIGHTTracks per-account variance data across all BvA runs. After 2+ periods, identifies:
Use case: If Marketing always runs 20% over budget, the CDC will surface this after 2-3 months. Use for next year's budget calibration.
CDC is appended, not overwritten — it accumulates across fiscal years.
1. [Month 1 of new FY] Run --build to generate annual budget
→ Saves: .cache/budget-builder/{slug}_budget_{year}.json
→ Share Excel with the reviewer for approval before using in BvA
2. [Each month after close] Run --compare
→ Pulls actuals from QBO automatically
→ Flags variances, generates commentary stubs
→ Updates CDC accuracy log
3. [Mid-year review] Re-run --build with updated assumptions + YTD overrides
→ Export updated budget JSON, pass to --budget-file in --compare
| Scenario | Behavior |
|---|---|
| --- | --- |
| QBO connection error | Raises RuntimeError with stdout/stderr for diagnosis |
| Missing month in history | Fills with $0; warns in console |
| Budget file not found | Raises FileNotFoundError with clear message + instructions |
| Division by zero (budget = $0 for actuals) | Returns ZERO variance; flags if actual > $2,500 |
| Invalid CSV column format | Skips unrecognized columns; warns |
pip install openpyxl
# Node.js QBO client must be configured with valid auth tokens
Mode A: Budget_{slug}_{year}.xlsx (e.g., Budget_acme_2026.xlsx)
Mode B: BvA_{slug}_{month_label}.xlsx (e.g., BvA_acme_Feb_26.xlsx)
Cache: .cache/budget-builder/{slug}_budget_{year}.json
CDC: .cache/budget-builder/{slug}_cdc.json
# January 2026: Build the budget
python3 budget-builder.py --slug <client-slug> --build --year 2026 \
--assumptions clients/<client-slug>/budget-assumptions-2026.json
# February 28 (after Jan close):
python3 budget-builder.py --slug <client-slug> --compare --through 2026-01
# March 31 (after Feb close):
python3 budget-builder.py --slug <client-slug> --compare --through 2026-02
# Q2 reforecast (after March close):
python3 budget-builder.py --slug <client-slug> --compare --through 2026-03
# Review CDC log — which categories need budget adjustment?
# Build revised budget with Q1 actuals as overrides:
python3 budget-builder.py --slug <client-slug> --build --year 2026 \
--overrides clients/<client-slug>/q1-actuals-overrides.csv
共 1 个版本