Files
TapTrack-Hub/.paul/ROADMAP.md
kevin-asprec 0e0803e417 feat(phase-8): billing engine + invoice PDF + mark-paid + overdue escalation
Backend:
- app/services/invoice_pdf.py: Jinja2+WeasyPrint PDF generation, saves to
  /app/data/invoices/{id}.pdf, updates Invoice.pdf_path
- app/templates/invoice.html: professional branded A4 invoice template with
  school details, line items table, totals, payment instructions, paid receipt
- routers/billing.py: GET /invoices/{id}/pdf (auto-generate on demand, FileResponse),
  POST /invoices/{id}/mark-paid (payment_method + reference → status=paid),
  POST /trigger-generate-invoices (manual trigger), school_name in invoice list
- tasks/billing.py: fix missing func import in generate_monthly_invoices,
  new billing.generate_invoice_pdf Celery task, auto-send email after
  invoice creation, check_overdue upgraded with 7-day warning emails and
  30-day school suspension + suspension email

Frontend:
- BillingPage.vue: full rewrite — status filter tabs, school names (not UUIDs),
  PDF download button, mail icon, Mark Paid modal with method/reference fields,
  overdue rows highlighted, pagination, Generate Invoices trigger button
- api.ts: markInvoicePaid, downloadInvoicePdf, triggerGenerateInvoices
2026-03-16 13:46:33 +08:00

340 lines
15 KiB
Markdown

# Roadmap: TapTrack Hub
## Overview
TapTrack Hub is a cloud-hosted SaaS control plane for managing all on-prem TapTrack school deployments.
It handles school licensing, SMS gateway proxying (Semaphore PH), billing/invoicing, support tickets,
monthly automated reports, and provides a client-facing school portal.
Two user roles:
- **Super Admin** — you (the operator): full control over all schools, licenses, SMS, billing
- **School Admin** — each client school's administrator: portal access for billing, SMS, tickets
Architecture: FastAPI + PostgreSQL + Redis + Celery + Vue 3 + Nginx, deployed as Docker Compose on a cloud VPS.
SMS flow: On-prem TapTrack polls Hub every 30s → Hub queues SMS jobs → Hub sends via Semaphore → reports back status.
---
## Current Milestone
**v1.0 — Foundation & Core Services**
Status: Phase 8 complete — Phase 9 next
Phases: 8 of 15 complete
---
## Phase Status
| Phase | Name | Plans | Status | Completed |
|-------|------------------------------|-------|--------------|------------|
| 1 | Project Setup & Infrastructure | 1 | ✅ Complete | 2026-03-15 |
| 2 | School Registry + License Mgmt | 2 | ✅ Complete | 2026-03-15 |
| 3 | On-Prem License Validation | 1 | ✅ Complete | 2026-03-15 |
| 4 | SMS Gateway (credits + queue) | 2 | ✅ Complete | 2026-03-15 |
| 5 | On-Prem SMS Polling Agent | 1 | ✅ Complete | 2026-03-16 |
| 6 | Super Admin Dashboard UI | 1 | ✅ Complete | 2026-03-16 |
| 7 | School Admin Portal UI | 1 | ✅ Complete | 2026-03-16 |
| 8 | Billing Engine + Invoice PDF | 1 | ✅ Complete | 2026-03-16 |
| 9 | Email Dispatcher | TBD | Not started | — |
| 10 | Support Ticket System | TBD | Not started | — |
| 11 | Monthly Report Generation | TBD | Not started | — |
| 12 | On-Prem Monthly Report Pull | TBD | Not started | — |
| 13 | Feature Flags + Suspension | TBD | Not started | — |
| 14 | Onboarding Wizard + Welcome Email | TBD | Not started | — |
| 15 | UX Polish + Ops Tools | TBD | Not started | — |
---
## Phase Details
### Phase 1: Project Setup & Infrastructure ✅
**Goal:** Runnable Docker Compose stack with FastAPI, PostgreSQL, Redis, Celery, and Vue 3 frontend skeleton.
**Completed:** 2026-03-15
What was built:
- Docker Compose: backend (gunicorn+uvicorn), celery worker, celery beat, frontend (vite build + nginx), PostgreSQL, Redis, nginx reverse proxy
- Full database schema: hub_users, schools, licenses, sms_jobs, sms_credit_ledger, invoices, invoice_line_items, school_subscriptions, support_tickets, ticket_replies, audit_logs, announcements
- Auth: JWT (python-jose), bcrypt, role-based dependencies (super_admin, school_admin)
- All FastAPI routers: auth, schools, licenses, sms, billing, tickets, users, dashboard, school_portal, announcements, sync
- All Celery tasks: sms.process_queue, billing.generate_monthly_invoices, billing.send_invoice_email, billing.check_overdue, license.check_expiry, reports.send_monthly_reports
- Email service (SMTP), seed script (super admin)
- Vue 3 frontend: router (super admin + portal routes), Pinia auth store, full api.ts client, Tailwind CSS, all page skeletons (Login, Dashboard, Schools, SchoolDetail, Licenses, SMS, Billing, Tickets, TicketDetail, Users, Announcements, NotFoundPage + all 5 portal pages)
- Shared components: AppSidebar, PortalSidebar, SidebarItem, KpiCard, StatusBadge, ToastStack
---
### Phase 2: School Registry + License Management
**Goal:** Super admin can register schools, issue license keys, set billing plans, add SMS credits, activate/suspend.
**Depends on:** Phase 1
**Scope:**
- School create/edit form (modal) in SchoolsPage
- License detail panel in SchoolDetailPage: change expiry, tier, revoke
- Subscription setup form per school (monthly fee, SMS cost per message)
- Add SMS credits form with ledger view
- Send welcome email on school creation (onboarding stub)
- School status lifecycle: pending → active → suspended/expired
**Plans:**
- [ ] 2-01: School create/edit modal + license expiry editor in SchoolDetailPage
- [ ] 2-02: Subscription setup + SMS credit top-up form + ledger table
---
### Phase 3: On-Prem License Validation
**Goal:** TapTrack on-prem validates its license key against Hub on startup and periodically; Hub returns feature flags and school config.
**Depends on:** Phase 2
**Scope:**
- `POST /api/licenses/validate` endpoint (already built) — verify, update last_seen, return features
- On-prem TapTrack changes:
- Celery beat task every 6h to call Hub license validate
- If expired/revoked: SMS disabled, warning banner in UI
- Store validated features in Redis (5min TTL) for fast feature flag checks
- Hardware fingerprint binding (optional — store server MAC on first validation)
**Plans:**
- [ ] 3-01: On-prem license validation task + feature flag Redis cache (TapTrack side)
- [ ] 3-02: UI warning banner on TapTrack when license invalid/expired
---
### Phase 4: SMS Gateway (Credits + Job Queue)
**Goal:** Schools submit SMS jobs via Hub; Hub processes them through Semaphore using school's sender name and deducts credits.
**Depends on:** Phase 2
**Scope:**
- `POST /api/sms/submit` (already built) — on-prem posts jobs
- Celery `sms.process_queue` (already built) — processes via Semaphore, deducts credits, logs ledger
- SMS job retry logic (up to 5 retries, exponential backoff)
- Low credit email alert (already built)
- Super admin SMS dashboard: jobs by status, school breakdown, Semaphore API health check
- Credit ledger view per school in SchoolDetailPage
**Plans:**
- [ ] 4-01: SMS dashboard stats + per-school credit ledger UI in SchoolDetailPage
- [ ] 4-02: SMS retry logic hardening + Semaphore health check endpoint
---
### Phase 5: On-Prem SMS Polling Agent
**Goal:** TapTrack on-prem polls Hub every 30s for pending SMS jobs; sends them via Hub's Semaphore account; reports back completion.
**Depends on:** Phase 4
**Scope:**
- Replace TapTrack's direct Semaphore calls with Hub polling
- On-prem Celery task: `POST /api/sync/poll` with license key + completed job IDs
- Hub returns jobs to send, school config (sender name, credits, status)
- On-prem sends via Hub-provided sender name (not its own settings)
- If school status = suspended: skip SMS, show banner
- Graceful degradation: if Hub unreachable, queue locally and retry
**Plans:**
- [ ] 5-01: On-prem polling task replacing direct Semaphore calls (TapTrack side)
- [ ] 5-02: Graceful degradation + local queue fallback (TapTrack side)
---
### Phase 6: Super Admin Dashboard UI
**Goal:** Rich super admin dashboard with KPI overview, school health list, SMS volume chart, revenue snapshot.
**Depends on:** Phase 4, Phase 2
**Scope:**
- KPI row: total/active/suspended schools, licenses expiring, open tickets, SMS today, pending invoices
- School health table: name, status, credits, last seen, license expiry (sortable)
- SMS volume chart (last 30 days) — bar chart by day
- Revenue snapshot: MRR, outstanding, overdue total
- Quick action buttons: add school, trigger SMS queue, check overdue invoices
**Plans:**
- [ ] 6-01: Dashboard KPI row + school health table
- [ ] 6-02: SMS volume chart + revenue snapshot panel
---
### Phase 7: School Admin Portal UI
**Goal:** Complete school admin portal — overview, billing history, SMS reports with charts, support tickets, profile.
**Depends on:** Phase 5, Phase 8
**Scope:**
- Portal overview: license status card, credit meter with low-credit warning, monthly SMS usage chart
- Billing tab: full invoice table, PDF download button per invoice, credit top-up request form
- SMS tab: monthly SMS log, delivery rate chart, credit burn rate chart
- Tickets tab: create ticket + reply thread view (already built as stubs)
- Profile tab: change password, view school details
**Plans:**
- [ ] 7-01: Portal overview enhancements (credit meter, charts, license countdown)
- [ ] 7-02: Billing PDF download + credit top-up request form
- [ ] 7-03: SMS usage charts + delivery rate visualization
---
### Phase 8: Billing Engine + Invoice PDF
**Goal:** Automated monthly invoice generation per school; PDF export; mark as paid workflow; overdue escalation.
**Depends on:** Phase 2
**Scope:**
- `billing.generate_monthly_invoices` Celery task (already built) — creates draft invoices
- Invoice PDF generation using Jinja2 HTML template + WeasyPrint
- Invoice PDF stored at `/app/data/invoices/{id}.pdf`
- `GET /api/billing/invoices/{id}/pdf` — serve PDF
- Mark as paid workflow (super admin sets paid_at, payment_method, payment_reference)
- Overdue escalation: 7 days → warning email, 30 days → suspend school
- Invoice number sequencing: INV-YYYYMM-NNNN
**Plans:**
- [ ] 8-01: Invoice PDF generation (Jinja2 template + WeasyPrint) + serve endpoint
- [ ] 8-02: Mark-paid workflow + overdue escalation (suspend at 30 days)
---
### Phase 9: Email Dispatcher
**Goal:** All automated emails (invoices, low credits, license expiry, monthly reports) send correctly via SMTP with proper HTML templates.
**Depends on:** Phase 8
**Scope:**
- Jinja2 HTML email templates: invoice, low credit alert, license expiry warning, monthly report, welcome email
- Email queue via Celery (retry on failure)
- Email delivery log table (email_logs): to, subject, type, status, sent_at, error
- `GET /api/email-logs` — super admin can view all email delivery history
- Test email endpoint: `POST /api/email/test` — send a test email to verify SMTP config
**Plans:**
- [ ] 9-01: Jinja2 HTML email templates + email_logs table + delivery logging
- [ ] 9-02: Email delivery log UI in super admin + test email endpoint
---
### Phase 10: Support Ticket System
**Goal:** Full-featured support ticket system with SLA tracking, internal notes, priority management, and email notifications.
**Depends on:** Phase 9 (emails)
**Scope:**
- Ticket create/reply already built — polish and harden
- Email notification on new ticket (to super admin) and on reply (to school admin)
- Internal notes (super admin only, already supported via is_internal flag)
- SLA tracking: first_response_at already stored — display SLA status in ticket list
- Priority escalation: tickets open > 48h auto-escalate to high
- Ticket assignment to specific super admin users
- Bulk actions: close all resolved, assign multiple
**Plans:**
- [ ] 10-01: Email notifications on ticket create/reply + SLA display in ticket list
- [ ] 10-02: Ticket assignment + priority auto-escalation + bulk close
---
### Phase 11: Monthly Report Generation + Email
**Goal:** On the 1st of each month, automatically generate and email a comprehensive report to each active school.
**Depends on:** Phase 9, Phase 12
**Scope:**
- `reports.send_monthly_reports` Celery task (already built as stub) — enhance with real data
- Report content: attendance summary, SMS usage, credit consumption, invoice for period
- HTML email template for monthly report (branded, professional)
- Super admin can manually trigger report for any school: `POST /api/reports/send/{school_id}`
- School portal: view past monthly reports (list + detail)
**Plans:**
- [ ] 11-01: Monthly report data aggregation + HTML email template
- [ ] 11-02: Manual trigger endpoint + report history in school portal
---
### Phase 12: On-Prem Monthly Report Pull
**Goal:** Hub pulls attendance summary data from each on-prem TapTrack instance to populate monthly reports.
**Depends on:** Phase 11
**Scope:**
- New endpoint on TapTrack on-prem: `GET /api/hub/monthly-report?key={license_key}&month={YYYY-MM}`
- Returns: total_students, present_days, absent_days, late_days, avg_attendance_rate, sms_sent
- Hub Celery task: on the 1st at 5am, poll each active school's on-prem for monthly data
- Store result in `school_monthly_stats` table for report generation
- Fallback: if on-prem unreachable, report shows "data unavailable" for attendance section
**Plans:**
- [ ] 12-01: TapTrack on-prem monthly report endpoint + school_monthly_stats table in Hub
- [ ] 12-02: Hub Celery pull task + fallback handling
---
### Phase 13: Feature Flags + Service Suspension Logic
**Goal:** Hub controls which features each school's on-prem instance can use, based on tier and payment status.
**Depends on:** Phase 3, Phase 8
**Scope:**
- Feature flags per tier (already in `_tier_features()`) — expose via `/api/licenses/validate`
- Suspension flow:
1. Invoice overdue 30 days → school.status = suspended
2. On-prem polls Hub → gets status=suspended → disables SMS, shows banner
3. On-prem attendance still works (not blocked) — only SMS and reports disabled
- Feature flag UI: per-school overrides in SchoolDetailPage (super admin can enable beta features)
- `feature_overrides` JSON column on School model for per-school feature customization
**Plans:**
- [ ] 13-01: feature_overrides column + per-school feature flag UI in SchoolDetailPage
- [ ] 13-02: Suspension propagation to on-prem via sync poll + on-prem banner
---
### Phase 14: Onboarding Wizard + Welcome Email
**Goal:** When a new school is registered, automatically send a welcome email with license key and setup instructions; guide super admin through initial school setup.
**Depends on:** Phase 9
**Scope:**
- Welcome email template: school name, license key, setup instructions link, Hub portal login URL
- Triggered automatically on school creation (after license is issued)
- Super admin onboarding checklist in SchoolDetailPage:
- [ ] School created
- [ ] License issued
- [ ] Billing plan set
- [ ] SMS credits added
- [ ] Welcome email sent
- [ ] School admin account created
- "Resend welcome email" button
- "Complete onboarding" button sets school.status = active
**Plans:**
- [ ] 14-01: Welcome email template + auto-send on school creation
- [ ] 14-02: Onboarding checklist UI in SchoolDetailPage + "activate school" workflow
---
### Phase 15: UX Polish + Super Admin Ops Tools
**Goal:** Production-ready polish: loading states, empty states, error boundaries, keyboard shortcuts, mobile responsiveness, audit log viewer, bulk operations.
**Depends on:** All previous phases
**Scope:**
- Audit log viewer: `GET /api/audit-logs` — searchable table of all system events
- Bulk school actions: export CSV, bulk status change
- Global search: search schools, tickets, invoices by name/number
- Keyboard shortcuts: `/` focus search, `N` new school, `Esc` close modals
- Mobile-responsive layouts for portal (school admins may use phone)
- Error boundary component for API failures
- Dashboard refresh button with last-updated timestamp
- Empty state illustrations for zero-data pages
- Production hardening: rate limiting on auth endpoints, HTTPS redirect
**Plans:**
- [ ] 15-01: Audit log table + global search + bulk export
- [ ] 15-02: Mobile-responsive portal + error boundary + production hardening
---