When multiple fusion.report rows share a report_type (e.g. 4 PnL-typed
reports: pnl, cash_flow, executive_summary, annual_statements), the
engine's _get_report previously returned whichever matched the type
filter first \u2014 so all four reports rendered the canonical P&L
line_specs regardless of which report the user selected.
Adds report_code kwarg to compute_pnl, compute_balance_sheet,
compute_trial_balance, compute_gl. Controller /fusion/reports/run now
accepts and forwards report_code. _get_report has a 3-tier resolution:
1. Exact code match (validates type)
2. Canonical (code == report_type)
3. First by sequence
Two new tests assert distinct line_specs render for distinct codes and
that wrong-type code raises ValidationError.
Verified live on westin-v19: pnl/cash_flow/executive_summary/
annual_statements now return 3/9/7/5 rows respectively (was all
3 before).
Made-with: Cursor
Adds Aged Receivable, Aged Payable, and Partner Ledger as fusion.report
records using the new compute_partner_grouped engine method.
REPORT_TYPES is extended with aged_receivable / aged_payable /
partner_ledger so each report has a unique report_type. The HTTP
controller dispatches these to engine.compute_partner_grouped with
the appropriate account_type via PARTNER_GROUPED_ACCOUNT_TYPE.
Output includes per-partner aging buckets: current, 1-30, 31-60,
61-90, 90+ days.
Westin total: 4 + 4 + 3 = 11 of Enterprise's 22 standard reports.
Made-with: Cursor
Adds engine.compute_partner_grouped(period, account_type=...) that
returns per-partner aggregations with aging buckets (current/1-30/
31-60/61-90/90+). SQL-direct for performance — single GROUP BY query
with conditional sum per bucket.
Foundation for the 3 partner-grouped reports landing in commit 3:
Aged Receivable, Aged Payable, Partner Ledger.
Made-with: Cursor
Inherits fusion.migration.wizard from fusion_accounting_migration and
appends a _reports_bootstrap_step that confirms the 4 CORE report
definitions (pnl, balance_sheet, trial_balance, general_ledger) exist
after migration. Returns a structured result with expected, present, and
missing report types.
Hooked into action_run_migration via super(); failures are logged
(warning) but never raised, so the migration chain remains tolerant of
ordering between sub-modules.
Adds fusion_accounting_migration to manifest depends.
Tests: 1 new (test_migration_round_trip.py). Net 114 -> 115.
Made-with: Cursor
The engine orchestrator. compute_pnl, compute_balance_sheet,
compute_trial_balance, compute_gl, drill_down. All controllers,
wizards, AI tools must route through these methods; no direct
SQL aggregation from anywhere else.
Internal pipeline: validate -> fetch hierarchy -> SQL aggregate
-> resolve line_specs -> optional comparison + anomaly. Uses raw
SQL for the per-account aggregate (the perf-critical step), ORM
for everything else.
Per-company report lookup with global fallback (company_id desc
nulls last). Balance sheet uses 1970 epoch as date_from for
cumulative-since-inception semantics.
7 new tests, 42 total passing.
Made-with: Cursor
Persistent definition of a Fusion financial report. Each report (P&L,
balance sheet, trial balance, GL) has one row in fusion.report holding
its metadata + line specs (stored as JSON for layout flexibility).
V19 conventions: models.Constraint inline, no _sql_constraints. Per-
company uniqueness on (company_id, code).
3 new tests, 27 total passing.
Made-with: Cursor