Module: Reports
Analytical views over the clinic's day-to-day data.
The Reports module is currently a stub in the React SPA (
ReportsModule.js). This page documents the intended behaviour so it can be implemented against the existing schema.
Purpose
- Give clinic admins and finance staff recurring reports they'd otherwise build in Excel.
- Expose enough raw numbers for a lightweight "how is the clinic doing?" dashboard.
Report catalogue
Financial
| Report | Data |
|---|---|
| Revenue by month | SUM(payments.amount) per month, filterable by currency |
| Outstanding receivables | SUM(invoices.balance_due) by age bucket (0–30, 31–60, 61–90, 90+) |
| Payment methods mix | COUNT(*) by payments.payment_method |
| Refunds | payments.status = 'refunded' total |
Operational
| Report | Data |
|---|---|
| Appointments by status | Bar chart of appointments.status counts for a date range |
| No-show rate | no_show / total per month |
| Booking source mix | Pie chart of booking_source |
| Vet utilisation | Completed appointment hours per vet |
Clinical
| Report | Data |
|---|---|
| Species mix | Pet count by species |
| Age distribution | Histogram of pet.date_of_birth |
| Top medical flags | Word cloud / count of pet.medical_flags (requires tokenising) |
Inventory
Depends on the not-yet-built medicines / stock_movements tables. Planned:
- Stock-on-hand snapshot.
- Stock turnover per medicine.
- Low-stock alerts.
Access control
Reports should default to clinic admins only. The tenant_user.role column is already in place; the Reports controller (to be built) will guard on it.
Implementation hints
- Most reports can be done with straightforward
groupByqueries — no OLAP engine needed at this scale. - For time-series plots, use
recharts(already referenced in a related example). - Reports take a
date_from/date_to/currencyfilter at minimum; expose more dimensions as real users ask for them.
API surface (proposed)
GET /api/v1/tenant/{tenant}/reports/revenue-by-month?year=2026¤cy=INR
GET /api/v1/tenant/{tenant}/reports/appointments-by-status?from=…&to=…
GET /api/v1/tenant/{tenant}/reports/receivables-aging
Each returns { data: [...], meta: { currency, range } }.
CSV / PDF export
- CSV: straightforward — stream via
fputcsvfrom a controller. - PDF: defer to a headless-chrome based approach (e.g.
browsershot) when it becomes a priority.