7.4 KiB
Doctor Import (IRIMC) API
Endpoint:
POST /api/v1/admin/doctors/importPermission:ROLE_ADMINController:App\Admin\Controller\AdminApiController::importDoctor
وارد کردن یک پزشک از سازمان نظام پزشکی (membersearch.irimc.org) بدون شماره موبایل.
برخلاف POST /api/v1/admin/doctors (که موبایل معتبر ایرانی میخواهد)، این اندپوینت برای
هر پزشک یک کاربر جانشینِ غیرفعال با شناسهٔ مصنوعی و نقشِ اختصاصی ROLE_UNCLAIMED_DOCTOR
میسازد و پروفایل را در وضعیت unclaimed ذخیره میکند تا بعداً به پزشک واقعی منتقل شود.
این نقش، هم کاربر جانشین را قابلشناسایی میکند و هم مبنای حذفِ امنِ او پس از انتقال است.
مصرفکنندهٔ اصلی: خزندهٔ پایتون (clinicpro-crawler/pipeline.py) که با کاربر «مالک
سیستمی» (0000000000) لاگین میکند و هر ~۶۰ ثانیه یک پزشک را میفرستد.
مدل مالکیت (ستونهای جدید doctors)
| ستون | مقدار هنگام ایمپورت | توضیح |
|---|---|---|
owner_status |
unclaimed |
claimed | unclaimed | pending_transfer |
source |
irimc |
manual (پیشفرض رکوردهای قدیمی) | irimc |
source_ref |
profile_url |
شناسهٔ رکورد مبدأ برای ممیزی |
managed_by |
id کاربر ادمینِ فراخوان | کاربری که پروفایل را مدیریت میکند |
claimed_at |
null |
زمان انتقال مالکیت (هنگام claim پر میشود) |
رکوردهای موجود در migration مقدار manual + claimed میگیرند تا رفتارشان تغییر نکند.
idempotency
کلید یکتای منطقی: (source, medical_system_code).
- اگر پزشکی با همان
source+medical_system_codeوجود نداشته باشد → ساخته میشود (201). - اگر وجود داشته باشد و
owner_status != claimed→ بهروزرسانی میشود (200). - اگر وجود داشته باشد و
owner_status == claimed→ رد میشود (200,skipped: "claimed") تا دادهٔ مالک واقعی بازنویسی نشود.
Request
{
"name": "دکتر فرخنده حسینی",
"medical_system_code": "145657",
"source": "irimc",
"source_ref": "https://membersearch.irimc.org/member/profile?id=…",
"gender": "woman",
"degree": "general",
"info": "دکترای حرفهای پزشکی",
"specialties": [1],
"states": [23],
"cities": [123]
}
| فیلد | الزامی | توضیح |
|---|---|---|
name |
✅ | نام کامل پزشک |
medical_system_code |
✅ | کد نظام پزشکی (کلید idempotency) |
source |
— | پیشفرض irimc |
source_ref |
— | profile_url یا شناسهٔ مبدأ |
gender |
— | man | woman |
degree |
— | general | expert | specialist | subspecialistplus |
info |
— | متن تخصص/توضیح |
specialties / states / cities |
— | آرایهٔ شناسههای مرجع (id) |
gender/degreeباید با ثابتهایDoctor::GENDERS/Doctor::DEGREESسازگار باشند.specialties/states/citiesاگر داده شوند مجموعهٔ فعلی را جایگزین میکنند.
Response
201 Created (ساخته شد)
{ "success": true, "data": { "uuid": "…", "created": true } }
200 OK (بهروزرسانی شد)
{ "success": true, "data": { "uuid": "…", "created": false } }
200 OK (رد بهدلیل تصاحبشده)
{ "success": true, "data": { "uuid": "…", "created": false, "skipped": "claimed" } }
422 (اعتبارسنجی)
{ "success": false, "data": null, "errors": [ { "code": "…", "message": "کد نظام پزشکی الزامی است", "field": "medical_system_code" } ] }
عکس پروفایل
پس از ایمپورت، عکس با دو مرحله اضافه میشود (همان مسیر پزشکِ عادی):
POST /file/upload/clinic_pro/doctor/field_image— بدنه: باینری خام؛ هدرContent-Disposition: attachment; filename="145657.jpg". پاسخ:{ fid, uuid, url, filename, filemime, filesize }.PATCH /api/v1/doctor/{uuid}با بدنهٔ{ "image_data": <پاسخ مرحلهٔ ۱> }تا به آرایهٔimagesپروفایل افزوده شود.
انتقال مالکیت به پزشک واقعی
Endpoint:
POST /api/v1/admin/doctors/{uuid}/transfer— permissionROLE_ADMIN
مالکیت یک پروفایلِ unclaimed را به پزشک واقعی منتقل میکند.
// Request
{ "mobile": "09120000000" }
مراحل اتمیک:
- کاربر واقعی بر پایهٔ
mobileپیدا یا ساخته میشود (باید موبایل معتبر ایران باشد). - اگر کاربر واقعی از قبل صاحب پزشک دیگری باشد →
409. user_idپروفایل به کاربر واقعی تغییر میکند،ROLE_DOCTORبه او داده میشود،owner_status = claimedوclaimed_at = nowوmanaged_by = nullمیشود.- کاربر جانشین حذف میشود — فقط اگر واقعاً
ROLE_UNCLAIMED_DOCTORداشته باشد و دیگر هیچ پزشکی به او وصل نباشد (حذف امن).
// Response 200
{ "success": true, "data": {
"uuid": "…", "owner_status": "claimed",
"transferred_to": "09120000000", "placeholder_deleted": true
} }
| کد | حالت |
|---|---|
404 |
پزشک یافت نشد |
409 |
قبلاً claimed است، یا کاربر مقصد پزشک دیگری دارد |
422 |
موبایل نامعتبر |
کاربر سیستمی و چرخهٔ عمر
# ساخت/فعالسازی کاربر مالک سیستمی (کرالر با این لاگین میکند)
php bin/console app:system-owner 0000000000 --password=<secret> --activate
# غیرفعالسازی پس از پایان کار (کرالر هم با --deactivate-on-finish این را از طریق API انجام میدهد)
php bin/console app:system-owner 0000000000 --deactivate
کاربر باید ROLE_ADMIN و status=1 داشته باشد تا لاگینِ رمزی (POST /api/v1/user/login)
و فراخوانی این اندپوینت ممکن باشد.
⚠️ captcha: مسیر
/api/v1/user/loginازCaptchaGuardرد میشود و این guard وقتیALTCHA_ENABLED=trueباشد (مقدار فعلی.env) یک payloadِ altcha میخواهد. برای اجرای بدونِمرورگرِ کرالر یکی از اینها لازم است: ۱) روی همان سرورALTCHA_ENABLED=falseدر.env.local(سادهترین برای dev)، یا ۲) افزودن یک استثنا درPasswordAuthenticatorکه برای کاربر مالک سیستمی captcha را رد کند، یا ۳) لاگین سرویس با یک هدر سرّیِ مورد اعتماد. تا وقتی این حل نشود، لاگین کرالر با ۴۲۲ (ERR_CAPTCHA_001) رد میشود.