Skip to main content

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

ReportData
Revenue by monthSUM(payments.amount) per month, filterable by currency
Outstanding receivablesSUM(invoices.balance_due) by age bucket (0–30, 31–60, 61–90, 90+)
Payment methods mixCOUNT(*) by payments.payment_method
Refundspayments.status = 'refunded' total

Operational

ReportData
Appointments by statusBar chart of appointments.status counts for a date range
No-show rateno_show / total per month
Booking source mixPie chart of booking_source
Vet utilisationCompleted appointment hours per vet

Clinical

ReportData
Species mixPet count by species
Age distributionHistogram of pet.date_of_birth
Top medical flagsWord 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 groupBy queries — 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 / currency filter 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&currency=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 fputcsv from a controller.
  • PDF: defer to a headless-chrome based approach (e.g. browsershot) when it becomes a priority.