feat: add staff role functionality with dashboard access and service management
- Implemented SidebarStaff component tests to ensure staff users see only their dashboard and services. - Created StaffMyServicesPage to display assigned services for staff users. - Added migration to link clinic staff rows to user accounts for ROLE_STAFF access. - Defined StaffPermissions class for static permissions related to staff role. - Introduced StaffRouteGuardSubscriber to restrict API access for staff users. - Developed StaffAccountService for managing staff user accounts and linking them to clinic staff. - Added comprehensive tests for StaffAccountService to validate user creation, mobile number handling, and account attachment. - Implemented tests for staff dashboard access to ensure proper permissions and access control. - Created tests for staff login context to verify correct environment visibility based on user roles.
This commit is contained in:
+58
-17
@@ -2,6 +2,18 @@
|
||||
|
||||
مدیریت پرسنل مطب/کلینیک (بدون حذف — فقط toggle فعال/غیرفعال).
|
||||
|
||||
**هر پرسنل حساب کاربری ورود دارد.** هنگام ایجاد/ویرایش، یک `User` با نقش `ROLE_STAFF` ساخته
|
||||
(یا کاربر موجودِ همان موبایل استفاده) و به ردیف پرسنل وصل میشود؛ بنابراین `phone` اجباری و
|
||||
معتبر (`^09\d{9}$`) است و همان **نامکاربری ورود** است. تغییر `phone` یعنی تغییر نامکاربری.
|
||||
|
||||
چنین کاربری در `/admin` وارد میشود، ولی دسترسیاش به `GET /api/v1/dashboard/staff` و چند
|
||||
مسیر حساب کاربری محدود است (بقیهٔ `/api/v1/*` برای او ۴۰۳ است — رجوع به
|
||||
[dashboard.md](dashboard.md) و [auth.md](auth.md)). قطع دسترسی با
|
||||
`PATCH /api/v1/staff/{uuid}/toggle` انجام میشود، نه با حذف حساب.
|
||||
|
||||
> ردیفهای پرسنلِ ساختهشده پیش از این تغییر ممکن است `has_account: false` باشند؛ با اولین
|
||||
> ویرایش (که `phone` معتبر میخواهد) صاحب حساب میشوند.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/v1/staff
|
||||
@@ -25,6 +37,8 @@
|
||||
"address": null,
|
||||
"national_code": "0012345678",
|
||||
"active": true,
|
||||
"has_account": false,
|
||||
"user_uuid": null,
|
||||
"created_at": 1718000000,
|
||||
"updated_at": 1718000000
|
||||
}
|
||||
@@ -32,6 +46,11 @@
|
||||
}
|
||||
```
|
||||
|
||||
| فیلد | نوع | توضیح |
|
||||
|------|-----|-------|
|
||||
| has_account | bool | حساب ورود دارد یا نه — برای ردیفهای جدید همیشه `true`؛ `false` فقط در ردیفهای قدیمیِ پیش از این قابلیت |
|
||||
| user_uuid | string\|null | uuid کاربرِ متصل؛ `null` یعنی حساب ندارد |
|
||||
|
||||
---
|
||||
|
||||
## POST /api/v1/staff
|
||||
@@ -43,38 +62,45 @@
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"full_name": "علی محمدی",
|
||||
"phone": "09121234567",
|
||||
"job_title": "منشی",
|
||||
"full_name": "محمد رحیمی",
|
||||
"phone": "09121110002",
|
||||
"job_title": "پرستار",
|
||||
"address": "تهران، خیابان ولیعصر",
|
||||
"national_code": "0012345678"
|
||||
"national_code": "0012345678",
|
||||
"password": "Staff@1234"
|
||||
}
|
||||
```
|
||||
|
||||
| فیلد | نوع | الزامی |
|
||||
|------|-----|--------|
|
||||
| full_name | string | ✅ |
|
||||
| phone | string | ❌ |
|
||||
| phone | string — `^09\d{9}$`، ارقام فارسی به لاتین تبدیل میشوند | ✅ نامکاربری ورود |
|
||||
| job_title | string | ❌ |
|
||||
| address | string | ❌ |
|
||||
| national_code | string(15) — ارقام فارسی به لاتین تبدیل میشوند | ❌ |
|
||||
| password | string | ❌ — رمز ورود؛ خالی بگذارید تا کاربر با «فراموشی رمز» تعیینش کند. روی کاربر موجود، رمز فعلی پاک نمیشود |
|
||||
|
||||
**Response 201:**
|
||||
اگر موبایل قبلاً `User` داشته باشد، کاربر جدید ساخته نمیشود؛ فقط `ROLE_STAFF` به نقشهایش
|
||||
اضافه و به این ردیف پرسنل وصل میشود.
|
||||
|
||||
**Response 201** (خروجی واقعی):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"uuid": "a1b2c3d4-...",
|
||||
"entity_type": "clinic",
|
||||
"entity_id": 5,
|
||||
"full_name": "علی محمدی",
|
||||
"phone": "09121234567",
|
||||
"job_title": "منشی",
|
||||
"address": "تهران، خیابان ولیعصر",
|
||||
"national_code": "0012345678",
|
||||
"uuid": "d64826bc-5e5d-4df6-83bb-3ddc70a99636",
|
||||
"entity_type": "doctor",
|
||||
"entity_id": 1,
|
||||
"full_name": "محمد رحیمی",
|
||||
"phone": "09121110002",
|
||||
"job_title": "پرستار",
|
||||
"address": null,
|
||||
"national_code": null,
|
||||
"active": true,
|
||||
"created_at": 1718000000,
|
||||
"updated_at": 1718000000
|
||||
"has_account": true,
|
||||
"user_uuid": "4d79b9b0-f330-4dea-9f02-e38fc716b115",
|
||||
"created_at": 1785393740,
|
||||
"updated_at": 1785393740
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -83,8 +109,16 @@
|
||||
| Code | HTTP | توضیح |
|
||||
|------|------|-------|
|
||||
| ERR_VALIDATION_001 | 422 | full_name خالی است |
|
||||
| ERR_STAFF_MOBILE_INVALID | 422 | شماره خالی/نامعتبر است یا شمارهٔ خودِ مالک محیط است (`field: "phone"`) |
|
||||
| ERR_STAFF_MOBILE_TAKEN | 409 | در همین محیط، پرسنل دیگری با این شماره ثبت شده است (`field: "phone"`) |
|
||||
| ERR_FORBIDDEN_001 | 403 | پروفایل doctor/clinic یافت نشد |
|
||||
|
||||
خروجی واقعی خطاها:
|
||||
```json
|
||||
{"success":false,"data":null,"errors":[{"code":"ERR_STAFF_MOBILE_INVALID","message":"شماره موبایل پرسنل معتبر نیست","field":"phone"}]}
|
||||
{"success":false,"data":null,"errors":[{"code":"ERR_STAFF_MOBILE_TAKEN","message":"برای این شماره قبلاً پرسنلی ثبت شده است","field":"phone"}]}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PATCH /api/v1/staff/{uuid}
|
||||
@@ -100,16 +134,23 @@
|
||||
"phone": "09129999999",
|
||||
"job_title": "منشی ارشد",
|
||||
"address": null,
|
||||
"national_code": null
|
||||
"national_code": null,
|
||||
"password": "NewPass@123"
|
||||
}
|
||||
```
|
||||
|
||||
ویرایش هم حساب را میسازد/بهروز میکند: اگر `phone` ارسال نشود، شمارهٔ فعلی همان ردیف
|
||||
استفاده میشود؛ اگر شمارهٔ جدید بیاید، نامکاربری ورود عوض میشود. `password` خالی رمز فعلی
|
||||
را پاک نمیکند.
|
||||
|
||||
**Response 200:** همان ساختار staff object
|
||||
|
||||
**Errors:**
|
||||
| Code | HTTP | توضیح |
|
||||
|------|------|-------|
|
||||
| ERR_STAFF_NOT_FOUND | 404 | پرسنل یافت نشد |
|
||||
| ERR_STAFF_MOBILE_INVALID | 422 | شمارهٔ نامعتبر یا شمارهٔ مالک محیط |
|
||||
| ERR_STAFF_MOBILE_TAKEN | 409 | شماره در همین محیط قبلاً ثبت شده |
|
||||
| ERR_FORBIDDEN_001 | 403 | دسترسی ندارید |
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user