feat: fix access scoping for clinic member doctors and add representation_id handling for clinics

This commit is contained in:
hamed
2026-06-19 13:42:24 +03:30
parent aeef59fe0d
commit d910a30a7e
7 changed files with 365 additions and 27 deletions
+2 -2
View File
@@ -293,8 +293,8 @@ Authorization: Bearer <token>
**قانون `context.role`** — نقشی که در آن محیط کاری فعال است:
- context مطب شخصی دکتر: `"doctor"`
- context کلینیک که دکتر **عضو** آن است: `"clinic"` (read-only — دسترسی به اطلاعات کلینیک)
- context کلینیک که دکتر **صاحب** آن است: `"clinic"`
- context کلینیک که دکتر **عضو** آن است (مالک نیست): `"doctor"` + `"scope": "clinic"` — پزشک می‌ماند و فقط نوبت‌های خودش در آن کلینیک را می‌بیند؛ دسترسی مدیریتی پنل کلینیک ندارد
- context کلینیک که دکتر **صاحب** آن است: `"clinic"` (دسترسی کامل مالک)
- context منشی: `"secretary"`
> **نکته frontend:** پس از `switchContext`، `primaryRole` در store باید از `context.role` آپدیت شود.
+70 -1
View File
@@ -294,7 +294,7 @@ Get yearly earnings dashboard for a representation.
### POST `/api/v1/representation/clinic`
افزودن کلینیک توسط نماینده.
افزودن کلینیک توسط نماینده. `representation_id` کلینیک خودکار روی نماینده‌ی کاربر جاری ست می‌شود (مثل createDoctor) تا در لیست‌های scoped دیده شود.
#### Request Body
```json
@@ -357,3 +357,72 @@ Get yearly earnings dashboard for a representation.
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | کاربر جاری نماینده نیست |
---
### GET `/api/v1/representation/doctors`
پزشکانِ ثبت‌شده توسط نماینده‌ی جاری (فقط ردیف‌های `representation_id = نماینده‌ی کاربر جاری`). شکل آیتم یکسان با `GET /api/v1/admin/doctors` است.
> **Permission:** `ROLE_REPRESENTATION` — id نماینده از `#[CurrentUser]` تعیین می‌شود، نه از query (نماینده نمی‌تواند داده‌ی نماینده‌ی دیگر را ببیند).
#### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | پیش‌فرض 1 |
| `limit` | integer | ❌ | پیش‌فرض 15، حداکثر 100 |
| `search` | string | ❌ | جستجو در نام یا موبایل پزشک |
#### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...", "id": 12, "name": "دکتر ...", "gender": "man", "degree": "...",
"medical_code": "...", "mobile": "0912...", "email": null,
"is_active": true, "rate": 3.5, "specialties": [],
"profile_image": null, "created_at": "2026-06-18T..."
}
],
"meta": { "totalRecords": 1, "totalPages": 1, "currentPage": 1 }
}
```
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | کاربر جاری نماینده نیست |
---
### GET `/api/v1/representation/clinics`
کلینیک‌های ثبت‌شده توسط نماینده‌ی جاری (فقط `representation_id = نماینده‌ی کاربر جاری`). شکل آیتم سازگار با `GET /api/v1/admin/clinics`.
> **Permission:** `ROLE_REPRESENTATION` — id نماینده از `#[CurrentUser]`.
#### Query Parameters
| Param | Type | Required | Description |
|-------|------|----------|-------------|
| `page` | integer | ❌ | پیش‌فرض 1 |
| `limit` | integer | ❌ | پیش‌فرض 15، حداکثر 100 |
| `search` | string | ❌ | جستجو در نام یا تلفن کلینیک |
#### Response `200`
```json
{
"success": true,
"data": [
{
"uuid": "...", "id": 5, "name": "کلینیک ...", "telephone": "...",
"logo": null, "clinic_logo": null, "is_active": true,
"doctors_count": 0, "created_at": "2026-06-18T..."
}
],
"meta": { "totalRecords": 1, "totalPages": 1, "currentPage": 1 }
}
```
#### Errors
| Code | HTTP | Description |
|------|------|-------------|
| `ERR_NOT_FOUND_001` | 404 | کاربر جاری نماینده نیست |