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:
hamed
2026-07-18 13:32:56 +03:30
parent 2553b45990
commit f1258d206d
28 changed files with 2126 additions and 276 deletions
+23
View File
@@ -327,3 +327,26 @@ refresh مستقیم هم کار کند، بنابراین فیلترکردن س
|------|------|-------|
| ERR_SERVICE_NOT_FOUND | 404 | سرویس یافت نشد |
| ERR_VALIDATION_001 | 422 | سال نامعتبر |
---
## Owner resolution (2026-07)
Every endpoint in this file resolves its owner through `App\Shared\Context\EntityContextResolver`
instead of reading the caller's role directly. Precedence:
1. an explicit **`clinic_uuid`** on the request (query string, or body on `POST`/`PATCH`/`PUT`) —
403 if the caller may not act in that clinic;
2. the caller's stored active context (`user_active_context`);
3. their role.
This fixes a user who is both a doctor and a clinic owner: they used to always resolve as `doctor`
and could never reach their own clinic's services.
`GET /api/v1/service-items?clinic_uuid=…` therefore returns that clinic's services rather than the
caller's personal ones.
> **TODO:** `Inventory`, `Patient`, `Staff`, `Billing`, `Insurance`, `Subscription`, `Tag` and `Sms`
> controllers still carry their own private `resolveEntity()` copy with the old role-first logic.
> They should be migrated to `EntityContextResolver` too.