Analytics — QA Plan
Auth
| Step | Expected |
|---|---|
Coach / member calls any /analytics/* endpoint | 403. |
| Non-member | 403. |
| Owner / admin | 200. |
Revenue summary
| Step | Expected |
|---|---|
| Org with 1 active monthly $100 plan | mrrInCents = 10000. |
| Org with 1 active yearly $1200 plan | mrrInCents = 10000 (1200/12). |
| Org with 1 active quarterly $300 plan | mrrInCents = 10000 (300/3). |
| Org with collected $500 this month, $400 last month | collectedDeltaPct = 0.25. |
| Org with $0 last month | collectedDeltaPct = null. |
| 3 subscriptions with debt = [100, 0, 250] cents | outstandingInCents = 350. |
Deleted subscription with price > 0 | Excluded from MRR. |
Revenue trend
| Step | Expected |
|---|---|
months=6 | 6 buckets returned, oldest → newest. |
months=24 | 24 buckets. |
| Failed payments | Not included. |
| Refunded payments | Excluded. |
Members summary
| Step | Expected |
|---|---|
| Org with 500 members, 450 active, 200 with Clerk accounts | activatedActive = 200. |
| 10 new this month, 5 new last month | newDeltaPct = 1.0. |
| 0 churned last month | churnedDeltaPct = null. |
Members activation
| Step | Expected |
|---|---|
| 100 imported (no Clerk, no invite) + 20 invited (pending) + 50 activated | Sums match. |
Total = imported + invited + activated. |
At-risk
| Step | Expected |
|---|---|
?sample=5 returns max 5 sample rows. | |
?sample=0 returns 0 sample rows but the correct count. | |
?sample=100 returns ≤ count rows. | |
| Sample ordered by name ascending. |
Classes
| Step | Expected |
|---|---|
?days=30 returns activity in past 30 days only. | |
popular-classes?limit=5 | At most 5 entries. |
| Class type with no bookings in the window | Not present (excluded from popular). |
| Class utilization for type with mixed full+empty sessions | Average fill rate reflects both. |
Workouts summary
| Step | Expected |
|---|---|
| MTD assignments and completions counted | Yes; PRs MTD counted. |
| Excludes deleted assignments | Yes. |
CSV export
| Step | Expected |
|---|---|
?tab=revenue-summary | 1-row CSV with header line and value line. |
?tab=invalid | 400. |
| CSV opens in Excel with Hebrew labels | UTF-8 BOM not present (gap) — consider adding if non-ASCII required. |
| Cells containing commas | Quoted properly. |
| Cells containing newlines | Quoted properly. |
Agent surface
| Step | Expected |
|---|---|
Agent prompt: “what’s our MRR?” → calls analytics.revenue_summary | Returns the same data; agent formats prose + table. |
Agent prompt: “Who’s at risk?” → calls analytics.at_risk_members | Returns sample + count. |
| Member role attempts to read | Agent doesn’t expose analytics tools to member. |
Performance
- p95 < 500ms for orgs up to 1000 members.
- Repeated requests should not regress (no per-call cache, but indexes are warm).
- Coach overview can be slower for 50-coach orgs; document threshold and consider caching if it crosses 1s.
Negative
- Pass
months=abc→ parsed as NaN, defaults applied. - Pass
sample=-1→ behavior depends on SQLLIMIT; document and ideally clamp to ≥ 0. - Pass
days=10000→ query returns all historical data; performance scales linearly.