# رفع نام دوتایی «دکتر» در ایمپورت IRIMC + دستور پاک‌سازی کامل پزشکان

## پروژه

`clinicpro` (backend + پنل ادمین)

## زمینه

پس از ایمپورت پزشکان نظام پزشکی، نام در پنل ادمین اشتباه نمایش داده می‌شود: به‌جای
«دکتر صفورا حجازی نیا»، «دکتر دکتر صفورا حجازی نیا» و در کارت grid به‌خاطر ellipsis
بریده و «دکتر دکتر صفورا حجازی نی» دیده می‌شود.

**ریشه (تأییدشده):** نامِ خامِ نظام پزشکی خودش پیشوند «دکتر» دارد (`دکتر صفورا حجازی نیا`
در `doctors.json` و در DB، ۲۰ کاراکتر — داده درست ذخیره شده). اما کنوانسیون پنل این است
که نام **بدون** پیشوند ذخیره شود و خودِ UI «دکتر» را جلو می‌گذارد:

```tsx
// assets/admin/pages/DoctorsPage.tsx:326 (جدول) و :412-413 (کارت grid با ellipsis)
<b>دکتر {doc.name}</b>
```

پس وقتی `doc.name = "دکتر صفورا حجازی نیا"` باشد، خروجی «دکتر دکتر …» می‌شود و در کارت
(`whiteSpace:nowrap; overflow:hidden; textOverflow:ellipsis`) طولانی‌تر شده و «…نیا»
بریده می‌شود. یک ریشه، هر دو نشانه.

علاوه بر این، کاربر می‌خواهد **همهٔ پزشکان و داده‌های وابسته به پزشک** پاک شوند تا یک
دیتابیس تمیز برای تست داشته باشیم (این کار با FK حذف مستقیم شکست می‌خورد — قبلاً خطای
`FK_4384ADBC87F4FB17` روی `doctor_provinces` دیدیم).

## مشکل / هدف

۱. ایمپورت IRIMC پیشوند «دکتر/دكتر» را از نام حذف کند تا با کنوانسیون پنل یکدست شود.
۲. ۳۴۰ رکورد IRIMC موجود (که با پیشوند ذخیره شده‌اند) اصلاح شوند.
۳. یک دستور کنسول امن برای پاک‌سازی کامل پزشکان + همهٔ داده‌های وابسته (FK-safe).

## فایل‌های مرتبط

| فایل | نقش |
|------|-----|
| `src/Doctor/Service/DoctorImportService.php` | ساخت/به‌روزرسانی پزشک؛ اینجا نام normalize شود |
| `src/Shared/Util/PersianText.php` | `stripDoctorTitle()` موجود — «دکتر» ابتدای نام را حذف می‌کند |
| `assets/admin/pages/DoctorsPage.tsx` | خط ۳۲۶ و ۴۱۲-۴۱۳ — نمایش `دکتر {doc.name}` (تغییر لازم ندارد، فقط داده اصلاح شود) |
| جداول FK به `doctors` (۱۶ عدد) | `weekly_schedules, date_overrides, comments, clinic_doctor_invitations, holidays, doctor_specialties, appointments, doctor_cities, doctor_expertise, rates, doctor_provinces, doctor_insurances, clinic_doctors, doctor_claim_requests, doctor_addresses, doctor_secretaries` |

## وضعیت فعلی

`DoctorImportService::doImport()` نام را همان‌طور که آمده ذخیره می‌کند:

```php
$name = trim((string) $data['name']);
// ...
$doctor->setName($name);   // نام هنوز شامل «دکتر …» است
```

`PersianText::stripDoctorTitle()` از قبل هست و دقیقاً همین کار را می‌کند:

```php
public static function stripDoctorTitle(string $name): string
{
    return trim(preg_replace('/^\s*دکتر\s+/u', '', self::normalize($name)) ?? $name);
}
```

## وظایف

### ۱. حذف پیشوند «دکتر» هنگام ایمپورت

در `DoctorImportService::doImport()`، نام را قبل از ذخیره normalize کن:

```php
use App\Shared\Util\PersianText;

$name = PersianText::stripDoctorTitle((string) ($data['name'] ?? ''));
if ($name === '') { /* همان اعتبارسنجی موجود در کنترلر — کنترلر نام خام را چک می‌کند */ }
```

- توجه: کنترلر (`DoctorImportController`) نام خام را برای اعتبارسنجی `!== ''` چک می‌کند؛
  strip فقط داخل سرویس برای مقدار ذخیره‌شده انجام شود تا اعتبارسنجی نشکند.
- `stripDoctorTitle` علاوه بر حذف پیشوند، `normalize` هم می‌کند (ي→ی، ك→ک، نیم‌فاصله) که
  برای یکدستی نام مفید است.
- **edge:** نام‌هایی که «دکتر» ندارند بدون تغییر می‌مانند؛ نام‌های دو-پیشوندی نادر
  («دکتر دکتر …») هم چون preg فقط یک بار از ابتدا حذف می‌کند، در صورت وجود باید بررسی شود
  (regex را در صورت نیاز به `^(?:\s*دکتر\s+)+` تغییر بده تا همهٔ پیشوندهای متوالی برود).

### ۲. اصلاح رکوردهای IRIMC موجود

یک دستور یک‌بارمصرف (هم‌سبک `BackfillSurrogateRoleCommand`) به نام
`app:doctors:fix-irimc-names`:

```php
// SELECT پزشکان source='irimc' که name با 'دکتر ' شروع می‌شود؛
// name = stripDoctorTitle(name)؛ با --dry-run فقط گزارش.
```

- فقط `source='irimc'` را دست بزن (پزشکان manual/seed را تغییر نده).
- `--dry-run` داشته باشد؛ در خروجی تعداد اصلاح‌شده را بده.
- در همان دستور، اگر `name` کاربرِ جانشین (`realName`) هم پیشوند دارد اختیاری است؛ اولویت با `doctors.name`.

### ۳. دستور پاک‌سازی کامل پزشکان (دیتابیس تمیز تست)

دستور `app:doctors:purge` در `src/Doctor/Command/PurgeDoctorsCommand.php`:

- **حفاظت:** فقط با `--force` اجرا شود؛ بدون آن فقط تعداد رکوردهای هر جدول را گزارش کند
  (dry-run پیش‌فرض). چون مخرب است، پیام تأیید واضح بدهد.
- ترتیب FK-safe: داخل یک تراکنش، اول جداول فرزند سپس `doctors`، سپس کاربران جانشین.
  ساده‌ترین و مطمئن‌ترین راه در MariaDB:

```php
$conn = $this->em->getConnection();
$conn->executeStatement('SET FOREIGN_KEY_CHECKS=0');
foreach ([
    'doctor_claim_requests','doctor_secretaries','doctor_addresses','doctor_insurances',
    'doctor_provinces','doctor_cities','doctor_specialties','doctor_expertise',
    'clinic_doctors','clinic_doctor_invitations','weekly_schedules','date_overrides',
    'holidays','comments','rates','appointments','doctors',
] as $t) {
    $n = $conn->executeStatement("DELETE FROM {$t}");   // یا TRUNCATE پس از خالی‌شدن FK
    $io->text("{$t}: {$n}");
}
$conn->executeStatement('SET FOREIGN_KEY_CHECKS=1');
```

- **کاربران جانشین:** پس از حذف پزشکان، کاربرانِ ایمپورت را هم پاک کن (وگرنه یتیم می‌مانند):
  `DELETE FROM users WHERE mobile_number LIKE 'imp\\_%' AND status=0`.
- **هشدار داده‌های مشترک:** `appointments`, `comments`, `rates` به بیمار/پرداخت هم وصل‌اند؛
  چون این دیتابیس فقط برای تستِ ایمپورت است حذف کامل قابل‌قبول است، ولی در دستور صریح
  هشدار بده که این عمل روی prod اجرا نشود (بررسی `APP_ENV !== 'prod'` یا نیاز به فلگ اضافهٔ
  `--i-know` برای prod).
- بعد از اجرا: `SET FOREIGN_KEY_CHECKS=1` حتی در صورت خطا (finally) اجرا شود.

## نکات مهم

- بعد از وظیفهٔ ۱، فقط ایمپورت‌های جدید نام تمیز می‌گیرند؛ وظیفهٔ ۲ برای ۳۴۰ رکورد فعلی لازم است.
- تغییری در `DoctorsPage.tsx` لازم نیست — با نام تمیز، `دکتر {doc.name}` درست رندر می‌شود و
  کارت grid دیگر بریده نمی‌شود.
- جریان claim (`DoctorClaimService::verifyIdentity`) از `stripDoctorTitle` روی `doctor.getName()`
  استفاده می‌کند؛ با نام تمیزِ ذخیره‌شده، این strip بی‌اثر (no-op) و تطبیق نام همچنان درست است — رگرسیون نده.
- تست:
  ```bash
  ddev exec php bin/console app:doctors:fix-irimc-names --dry-run
  ddev exec php bin/console app:doctors:purge            # dry-run
  ddev exec php bin/console app:doctors:purge --force    # پاک‌سازی
  # سپس یک ایمپورت تست و بررسی نام در /admin/doctors (باید «دکتر صفورا حجازی نیا» تک‌پیشوند باشد)
  ```
- بعد از تغییر سرویس/کنترلر ایمپورت، `docs/api/doctor-import.md` را با «نام بدون پیشوند دکتر ذخیره می‌شود» به‌روز کن.
- تست integration موجود `DoctorImportTest` را به‌روز کن: assert کند نام ذخیره‌شده پیشوند «دکتر» ندارد.
