warmbox/docs/sprints/sprint-1.5.md

1.4 KiB

Sprint 1.5 — Stats API

Operator-visible campaign metrics via REST, backed by real-time DailySchedule counters and nightly DailyStat rollups.

What shipped

  • DailyStat model — materialized daily rollups with replyRateActual, inboxPlacementRate
  • stats.service.ts — today, daily time series, range summary, workspace overview
  • Stats routes:
    • GET /api/campaigns/:id/stats/today
    • GET /api/campaigns/:id/stats/daily?from=&to=
    • GET /api/campaigns/:id/stats?range=7d|30d|all
    • GET /api/workspace/overview
  • stats-rollup.job.ts — hourly cron, finalizes yesterday at 00:xx campaign TZ
  • POST /api/jobs/rollup/run — manual rollup trigger
  • Logs filterGET /api/logs?campaignId=

Response example (/stats/today)

{
  "campaignId": "...",
  "date": "2026-06-25",
  "dayIndex": 12,
  "planned": { "sends": 18, "replies": 6 },
  "actual": { "sends": 15, "replies": 5, "spamDetected": 2, "spamRescued": 2 },
  "rates": { "reply": 33.3, "inbox": 86.7 },
  "recipe": "grow",
  "onTrack": true
}

FillCare manual QA

  1. Active Grow campaign with sends in progress
  2. GET /api/campaigns/:id/stats/today — verify planned vs actual
  3. GET /api/workspace/overview — see hello@ primary at a glance
  4. Compare stats counts to GET /api/logs?campaignId=:id

Key files

  • src/services/stats.service.ts
  • src/jobs/stats-rollup.job.ts
  • src/routes/stats.routes.ts