Files
clinicpro/docs/api/secretary.md
T
hamedandClaude Opus 4.8 89e23a2c0d feat: port secretaries tab from tauri to admin my-secretaries page
- Redesign MySecretariesPage pixel-perfect to clinic-pro-tauri (active/previous
  tabs, desktop table, mobile cards, add/edit/view modal with permission
  accordions, deactivate confirm)
- Permission sections based on existing admin pages (appointments, patients,
  payments, insurances, addresses, clinic_info)
- Extend DoctorSecretary with national_code + address columns (+migration);
  wire create/update in SecretaryController; add patients/payments to
  DEFAULT_PERMISSIONS
- Extend Secretary/SecretaryPermissions types; update admin SecretariesPage
- Backend + frontend tests; update docs/api/secretary.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 12:23:17 +03:30

13 KiB
Raw Blame History

Secretary API

Prefix: /api/v1/secretary, /api/v1/secretaries

مدل Scope

هر رابطه منشی-پزشک دارای یک scope است که از تداخل بین محیط‌های مختلف جلوگیری می‌کند:

Scope owner_type تعریف‌کننده دسترسی
مطب شخصی doctor خود پزشک فقط نوبت‌ها و داده‌های مطب شخصی
کلینیک clinic مدیر کلینیک فقط نوبت‌ها و داده‌های کلینیک
  • یک منشی می‌تواند هم در مطب شخصی یک دکتر و هم در کلینیک همان دکتر فعال باشد (دو ردیف مجزا)
  • منشی کلینیک می‌تواند به چند دکتر در همان کلینیک متصل باشد
  • scope فعال در runtime از جدول user_active_context (db_uuid) خوانده می‌شود

Secretaries are linked to a doctor and have granular permissions controlling what they can do on behalf of the doctor.


POST /api/v1/secretary

Create a secretary for a doctor.

Permission: ROLE_DOCTOR (must own the doctor — creates owner_type='doctor') | ROLE_CLINIC (must have the doctor in its clinic — creates owner_type='clinic') | ROLE_ADMIN

Request Body (application/json)

{
    "doctor_uuid": "550e8400-...",
    "mobile_number": "09123456789",
    "name": "سارا احمدی",
    "national_code": "1234567890",
    "address": "یزد، خیابان تست",
    "password": "secretaryPass123",
    "permissions": {
        "version": 1,
        "resources": {
            "appointments": {
                "view": true,
                "create": true,
                "cancel": false,
                "update_status": true
            },
            "patients": {
                "view": true,
                "create": false,
                "update": false,
                "delete": false
            },
            "payments": {
                "view": true,
                "create": false,
                "update": false,
                "delete": false
            },
            "insurances": {
                "view": true,
                "create": false,
                "update": false,
                "delete": false
            },
            "addresses": {
                "view": true,
                "create": false,
                "update": false,
                "delete": false
            },
            "clinic_info": { "view": true, "update": false }
        }
    }
}
Field Type Required Description
doctor_uuid string (UUID) Doctor to assign secretary to
mobile_number string Secretary's login mobile
name string Full name (نام + نام خانوادگی) → user_name
national_code string کد ملی منشی (nullable)
address string آدرس منشی (nullable)
password string Initial password (auto-generated if omitted)
permissions object Permission set (see structure below)

Permissions Structure:

مجموعهٔ منابع (resources) بر اساس صفحات موجود پنل ادمین است. mergePermissions هر منبع/اکشن ارسال‌شده را deep-merge می‌کند؛ فقط appointments در بک‌اند enforce می‌شود (MyAppointmentsController, DashboardController)، بقیه UI/ذخیره‌ای هستند.

{
    "version": 1,
    "resources": {
        "appointments": {
            "view": true, // Can view appointments list
            "create": true, // Can book appointments
            "cancel": false, // Can cancel appointments
            "update_status": true // Can mark as completed/no_show
        },
        "patients": {
            "view": true,
            "create": false,
            "update": false,
            "delete": false
        },
        "payments": {
            "view": true,
            "create": false,
            "update": false,
            "delete": false
        },
        "insurances": {
            "view": true,
            "create": false,
            "update": false,
            "delete": false
        },
        "addresses": {
            "view": true,
            "create": false,
            "update": false,
            "delete": false
        },
        "clinic_info": {
            "view": true,
            "update": false
        }
    }
}

Response 201

{
  "success": true,
  "data": {
    "uuid": "sec-uuid-...",
    "user_name": "علی محمدی",
    "mobile_number": "09123456789",
    "doctor_name": "دکتر احمد رضایی",
    "doctor_uuid": "...",
    "owner_type": "doctor",
    "clinic_uuid": null,
    "is_active": true,
    "national_code": "1234567890",
    "address": "یزد، خیابان تست",
    "permissions": { ... },
    "created_at": 1717000000
  }
}

مقادیر owner_type:

مقدار معنی
doctor منشی توسط خود دکتر تعریف شده — فقط مطب شخصی
clinic منشی توسط مدیر کلینیک تعریف شده — فقط کلینیک

پیامک خوش‌آمد: پس از ساخت موفق منشی، یک پیامک به‌صورت async به mobile_number منشی ارسال می‌شود (تگ secretary). متن از قالب ویرایش‌پذیر DB می‌آید (fallback به پیش‌فرض) و placeholderهای {owner} (نام دکتر یا کلینیک بسته به owner_type{username} (موبایل منشی) و {link} (لینک ورود) را جایگزین می‌کند. ویرایش متن از PATCH /api/v1/admin/sms/messages/secretary — رجوع به sms.md.

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing token
ERR_AUTH_006 403 Not the doctor owner / clinic owner / admin
ERR_NOT_FOUND_001 404 Doctor not found
ERR_CONFLICT_001 409 Secretary already added for this doctor
ERR_SECRETARY_001 422 Plan limit for secretaries reached

GET /api/v1/secretary/{uuid}

Get secretary detail.

Permission: AUTH — must be the linked doctor or ROLE_ADMIN

Path Parameters

Param Type Description
uuid string (UUID) Secretary UUID

Response 200

{
  "success": true,
  "data": {
    "uuid": "...",
    "mobile_number": "09123456789",
    "active": true,
    "permissions": { ... },
    "doctor": { "uuid": "...", "title": "دکتر علی احمدی" },
    "created_at": 1717000000
  }
}

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing token
ERR_FORBIDDEN_001 403 Not authorized
ERR_NOT_FOUND_001 404 Secretary not found

PATCH /api/v1/secretary/{uuid}

Update secretary active status, profile fields (name/national_code/address), or permissions. تمام فیلدها اختیاری‌اند و فقط موارد ارسال‌شده اعمال می‌شوند.

Permission: ROLE_DOCTOR — must be the linked doctor

Request Body (application/json)

{
    "active": false,
    "name": "نام جدید",
    "national_code": "9999999999",
    "address": "آدرس جدید",
    "permissions": {
        "version": 1,
        "resources": {
            "appointments": {
                "view": true,
                "create": false,
                "cancel": false,
                "update_status": false
            }
        }
    }
}
Field Type Required Description
active boolean Enable/disable secretary
name string به‌روزرسانی نام کامل منشی (user_name)
national_code string به‌روزرسانی کد ملی (nullable)
address string به‌روزرسانی آدرس (nullable)
permissions object New permissions object (deep-merged)

Response 200

Updated secretary object.

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing token
ERR_FORBIDDEN_001 403 Not the linked doctor
ERR_NOT_FOUND_001 404 Secretary not found

DELETE /api/v1/secretary/{uuid}

Delete a secretary.

Permission: ROLE_DOCTOR — must be the linked doctor

Response 200

{ "success": true, "data": { "message": "منشی حذف شد" } }

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing token
ERR_FORBIDDEN_001 403 Not the linked doctor
ERR_NOT_FOUND_001 404 Secretary not found

GET /api/v1/secretaries/{doctorUuid}

Get all secretaries for a specific doctor.

Permission: ROLE_DOCTOR (must own doctor) | ROLE_CLINIC (must have doctor in clinic) | ROLE_ADMIN

Path Parameters

Param Type Description
doctorUuid string (UUID) Doctor UUID

Response 200

{
  "success": true,
  "data": [
    {
      "uuid": "...",
      "user_name": "علی محمدی",
      "mobile_number": "09...",
      "doctor_name": "دکتر احمد رضایی",
      "doctor_uuid": "...",
      "is_active": true,
      "permissions": { ... },
      "created_at": 1717000000
    }
  ]
}

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing token
ERR_FORBIDDEN_001 403 Not authorized
ERR_NOT_FOUND_001 404 Doctor not found

GET /api/v1/secretaries/clinic/{clinicUuid}

Get all secretaries across all doctors of a clinic.

Permission: ROLE_CLINIC (must own clinic) | ROLE_ADMIN

Path Parameters

Param Type Description
clinicUuid string (UUID) Clinic UUID

Response 200

{
  "success": true,
  "data": [
    {
      "uuid": "...",
      "user_name": "علی محمدی",
      "mobile_number": "09...",
      "doctor_name": "دکتر احمد رضایی",
      "doctor_uuid": "...",
      "is_active": true,
      "permissions": { ... },
      "created_at": 1717000000
    }
  ]
}

Notes

  • این endpoint فقط منشی های را برمی‌گرداند که با owner_type='clinic' تعریف شده‌اند
  • منشی های که خود دکتر (با owner_type='doctor') تعریف کرده از این لیست مخفی هستند
  • یک منشی می‌تواند به چند دکتر در همان کلینیک متصل باشد — در لیست چندبار ظاهر می‌شود (یک ردیف به ازای هر دکتر)

Errors

Code HTTP Description
ERR_AUTH_001 401 Missing token
ERR_FORBIDDEN_001 403 Not clinic owner
ERR_NOT_FOUND_001 404 Clinic not found

محدودیت پنل اشتراکی

تعداد منشی‌های مجاز بر اساس پنل فعال doctor تعیین می‌شود:

پنل حداکثر منشی
Free (بدون اشتراک) ۱
Basic ۳
Professional ۱۰

اگر تعداد منشی‌های فعال به حد مجاز رسیده باشد، ایجاد منشی جدید خطای زیر را برمی‌گرداند:

{
    "success": false,
    "errors": [
        {
            "code": "ERR_SECRETARY_001",
            "message": "پلن فعلی اجازه منشی بیشتر را نمی‌دهد"
        }
    ]
}

برای افزایش محدودیت، باید پنل را از POST /api/v1/subscription/trial (تریال) یا POST /api/v1/subscription-payment (پرداخت) ارتقاء داد.