feat(migrations): add clinic_id context to weekly_schedules, date_overrides, and holidays
- Introduced clinic_id to weekly_schedules, date_overrides, and holidays to differentiate between personal and clinic schedules. - Updated unique constraints and indexes to accommodate the new clinic context. feat(command): create AssignScheduleClinicCommand to move schedules - Added a command to move a doctor's personal weekly schedule into a clinic context. - Implemented checks to ensure sessions align with the target clinic. feat(context): implement EntityContext and EntityContextResolver - Created EntityContext to represent the effective working environment of a request (doctor or clinic). - Developed EntityContextResolver to determine the execution context based on user roles and active contexts. test: add ServiceModeContextTest for appointment scheduling - Implemented tests to ensure service booking respects clinic and personal contexts. - Verified that financial data is omitted in clinic contexts in InvitedDoctorDashboardScopeTest.
This commit is contained in:
@@ -266,3 +266,34 @@ Returns time-series chart data for admin dashboard. All series are filtered to t
|
||||
- `appointment_status` — all-time counts, not filtered by period
|
||||
- `top_specialties` — top 8 by appointment volume, all-time
|
||||
- `subscription_sales_by_plan` — subscriptions created in period, grouped by plan; `revenue` sums only payments with status `received`
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Doctor dashboard is context-scoped (2026-07)
|
||||
|
||||
`GET /api/v1/dashboard/doctor` now accepts an optional **`clinic_uuid`**. When absent it falls back
|
||||
to the caller's stored active context (`user_active_context`), then to their role.
|
||||
|
||||
In a **clinic context** the response is restricted to that clinic:
|
||||
|
||||
* appointment counts and `today_appointments` only include appointments whose `address_id` belongs
|
||||
to that clinic;
|
||||
* the financial fields are **omitted entirely** — `revenue_period_rials`, `today_payments_rials`,
|
||||
`week_payments_rials`, `sms_wallet_balance`, `unique_patients_count`, `total_patients`, and
|
||||
`charts.revenue_by_day`. They describe the doctor's personal practice and have no meaning inside
|
||||
someone else's clinic. They return only in the personal context, or for the clinic's own owner
|
||||
holding `payments.view`;
|
||||
* `clinics` comes back as `[]` — the "کلینیکهای من" list belongs to the personal dashboard.
|
||||
|
||||
A `clinic_uuid` the caller has no access to is ignored and the personal context is used.
|
||||
|
||||
New response field:
|
||||
|
||||
```json
|
||||
"context": { "type": "personal" | "clinic", "clinic_uuid": "…|null", "clinic_name": "…|null" }
|
||||
```
|
||||
|
||||
The admin SPA dispatches on this: `primaryRole === 'doctor' && context.scope === 'clinic'` renders
|
||||
`InvitedDoctorDashboard` (appointment tiles + today's list only) instead of the full doctor
|
||||
dashboard. Hiding the cards client-side was not enough — the endpoint is directly callable.
|
||||
|
||||
Reference in New Issue
Block a user