<div dir="rtl" markdown="1">

# پاک‌سازی رکوردهای آلودهٔ پزشک و کلینیک

## پروژه

`clinicpro` (لایهٔ داده + اعتبارسنجی)

## زمینه

ممیزی SEO سایت عمومی رکوردهایی را در نتایج **عمومی** پیدا کرد که نام واقعی ندارند:

- پزشک با `name: "09390039833"` (شماره‌تلفن به‌جای نام) و `owner_status: "claimed"`
- پزشک با `name: "test"` و `owner_status: "claimed"`
- کلینیک `9c163d69-0051-4745-a423-c830135b1c01` با `title: "09398631203"`، `is_active: false`، بدون `caption`/`logo`/`services`

این رکوردها در HTML عمومی رندر می‌شدند و `<title>` صفحه‌ای مثل «09398631203 | یاسوج نوبت» می‌ساختند.

**وضعیت فعلی:** سایت عمومی موقتاً محافظت شده — `nobat724_front/lib/entityQuality.js` رکوردهایی با نام شبیه شماره‌تلفن یا `test` را `noindex` می‌کند و از sitemap بیرون می‌گذارد. ولی این فقط ماسک است: داده هنوز آلوده است، در API عمومی برمی‌گردد و در لیست‌ها به کاربر نمایش داده می‌شود.

سنجش روی دادهٔ واقعی: از ۵۰ رکورد اول لیست پزشکان، ۲ رکورد آلوده بودند.

## هدف

۱. رکوردهای آلودهٔ موجود پاک/غیرفعال شوند.
۲. جلوی تولید رکورد آلودهٔ جدید گرفته شود (اعتبارسنجی).

## وظایف

### ۱. گزارش دامنهٔ آلودگی (اول اندازه‌گیری، بعد حذف)

اسکریپت یا کوئری که بشمارد و **فهرست کند** (بدون تغییر داده):

- پزشکانی که `name` فقط رقم است یا با الگوی موبایل ایران می‌خواند (`^0?9\d{9}$` پس از حذف فاصله و خط تیره)
- پزشکان با نام در مجموعهٔ `test`, `تست`, `-`, `—` (بدون حساسیت به بزرگی/کوچکی)
- کلینیک‌ها با همان دو الگو روی `title`/`name`
- از هر گروه: تعداد کل، چندتا `owner_status = claimed`، چندتا نوبت/رابطهٔ واقعی دارند

الگوها را از `nobat724_front/lib/entityQuality.js` بردار تا معیار دو طرف یکی بماند:

```js
const PHONE_LIKE = /^0?9\d{9}$/;
const PLACEHOLDER_NAMES = new Set(["test", "تست", "-", "—"]);
```

**خروجی این مرحله را قبل از هر حذفی گزارش کن.** اگر رکوردی نوبت واقعی یا پرداخت دارد، حذف نیست — تصمیمش با تیم است.

### ۲. پاک‌سازی

بر اساس گزارش مرحلهٔ ۱، برای هر گروه تصمیم صریح بگیر و مستند کن:

| وضعیت رکورد | اقدام |
|---|---|
| بدون هیچ رابطهٔ واقعی (نوبت/پرداخت/کاربر) | حذف |
| دارای رابطهٔ واقعی ولی نام آلوده | نام اصلاح شود یا از انتشار عمومی خارج شود؛ حذف نشود |
| `owner_status: claimed` با نام آلوده | claim نامعتبر است — بازبینی دستی لازم دارد |

اسکریپت پاک‌سازی باید **dry-run پیش‌فرض** داشته باشد و فقط با فلگ صریح بنویسد.

### ۳. اعتبارسنجی برای جلوگیری از تکرار

در مسیر ایجاد/ویرایش پزشک و کلینیک (هم API عمومی، هم پنل ادمین، هم import):

- نام برابر الگوی شماره‌تلفن → خطای اعتبارسنجی فارسی
- نام در فهرست placeholderها → خطای اعتبارسنجی فارسی
- حداقل طول معنادار برای نام

پیام خطا فارسی باشد (قانون پروژه). به `clinicpro/src/Doctor/Controller/DoctorImportController.php` هم اعمال شود — import مسیر محتمل ورود دادهٔ آلوده است.

### ۴. بازبینی معیار `is_active` کلینیک

کلینیک `9c163d69` با `is_active: false` هنوز از API عمومی برمی‌گردد. تصمیم بگیر و مستند کن:

- `is_active: false` یعنی «موقتاً غیرفعال» → در API عمومی بماند ولی سایت `noindex` کند (رفتار فعلی سمت فرانت)
- یا یعنی «حذف‌شده» → از پاسخ‌های عمومی حذف شود

هر کدام را انتخاب کردی، در `docs/api/clinic.md` بنویس.

## نکات مهم

- **این تغییرات لایهٔ داده‌اند و برگشت‌ناپذیر.** قبل از حذف، بکاپ بگیر.
- بعد از پاک‌سازی، sitemap سایت عمومی خودکار بزرگ‌تر می‌شود (فیلتر `isThinDoctor` رکورد کمتری کنار می‌گذارد) — نیازی به تغییر فرانت نیست.
- اگر بعد از پاک‌سازی داده تمیز شد، فیلتر نام در `nobat724_front/lib/entityQuality.js` را **حذف نکن**؛ به‌عنوان لایهٔ دفاعی بماند.
- تست: `clinicpro/TEST_USERS.md` — کاربر تست `09390039833` است. مطمئن شو اسکریپت پاک‌سازی حساب‌های تست توسعه را با دادهٔ آلودهٔ production اشتباه نگیرد.

</div>
