Module: Controlling (Phase 5)
The read-model / reporting layer. Aggregates the three team dashboards (Outreach, Connect, Closing) into one cross-stage overview, closes the loop on spend with yield-based budget allocation optimization, and prepares read-only BI views.
Responsibilities
- One cross-stage overview: the full funnel from researched → sold, per campaign and overall.
- Cost per stage and yield per source (which target sources / branches / postal codes pay off).
- Per-agent performance for Connect-Agents and Closing-Agents (reach, gatekeeper quote, interest, appointment, close, commission).
- Budget health per campaign, tied to the budget guard.
- Budget allocation optimization — shift remaining budget toward higher-yield sources/campaigns. (Named distinctly from the outreach content Bandit — this is a separate, spend-side concern.)
- Benchmark weighting A/B — compare score versions against realized outcomes.
Design
- Build as a read model: materialized aggregates refreshed nightly + on-demand, not live queries
over raw logs. The sources are
audit_logs,Callrecords,OutreachMessages,bandit_events, andresearch_api_calls(for cost). - Never hand-edit aggregates — always recomputed from the underlying events.
- A React charting library renders funnel, trend, and yield charts.
- Prepare for BI with a read-only DB user scoped to dedicated
bi_*views. Reporting tables avoid soft-deletes so figures stay consistent (documented exceptions only, filtered out by the BI views).
Funnel (the headline view)
Researched → Qualified → Emailed → Replied / No-reply → Called → Interested
→ Appointment scheduled → Sold
Each step shows count, conversion %, and cost so far → cost per sold deal and cost per stage.
Budget allocation optimization
- Observe yield per source/campaign (sold deals or appointments per euro spent).
- Reallocate remaining campaign budget toward higher-yield arms.
- Ties back to the research budget guard: the guard enforces the hard limits (pre-check before any paid call, auto-pause at 100%); this optimization decides where the remaining budget flows. Kept separate in name from the outreach content Bandit to avoid confusion.
Key services / jobs
RefreshControllingAggregates— scheduled nightly + on-demand.OptimizeBudgetByYield— the budget allocation step.CompareBenchmarkVersions— A/B score versions vs. realized outcomes.
Business logic lives in NestJS services; scheduled refreshes run on the BullMQ queues.
Acceptance
- The overview shows the cross-stage funnel with counts, conversions, and cost per stage.
- Yield per source and per-agent KPIs (Connect-Agents + Closing-Agents) match the underlying logs.
- Budget allocation shifts toward higher-yield arms in a simulated run.
bi_*views are read-only and exclude soft-deleted exception rows.- Tests cover aggregate correctness and the allocation logic.
Screens (see 04-design-workflow)
- Controlling — cross-team funnel, cost per stage, yield per source, per-agent KPIs.
- Dashboard — the Supervisor's condensed daily view (a subset of Controlling).