Files
clinicpro/.claude/prompt/unclaimed-doctor-null-rating.md
T

5.4 KiB
Raw Blame History

پروفایل unclaimed پزشک — حذف امتیاز پیش‌فرض جعلی از پاسخ API

پروژه

clinicpro (backend) — cross-repo. پرامپت همتای frontend: nobat724_front/.claude/prompt/unclaimed-doctor-public-page.md این تغییر backend باید اول انجام شود؛ سایت عمومی و پنل ادمین و tauri همگی همین پاسخ را مصرف می‌کنند.

زمینه

پزشکانِ ایمپورت‌شده از نظام پزشکی (IRIMC) با owner_status = 'unclaimed' ساخته می‌شوند و هیچ‌گاه فیلد امتیاز ست نمی‌شود؛ پس مقادیر پیش‌فرضِ انتیتی (doctor_rate = 3.5, doctor_rate_percentage = 60) به‌عنوان امتیاز واقعی در پاسخ عمومی برمی‌گردند. سایت این‌ها را به‌صورت «امتیاز: ۳.۵» و «۶۰٪ رضایت» و در JSON-LD به‌صورت AggregateRating نشان می‌دهد — در حالی که تعداد نظرات واقعی صفر است.

مشکل / هدف

  • بحرانی: داده‌ی امتیاز جعلی برای پروفایل بدون صاحب. هم گمراه‌کننده، هم نقض دستورالعمل structured data گوگل (ریویوی جعلی) و ریسک جریمه.
  • هدف: تا وقتی پروفایل claimed نشده، فیلدهای امتیاز در پاسخ عمومی null برگردند (نه مقدار پیش‌فرض). بعد از claim، رفتار عادی برگردد (بدون تغییر، چون آن‌موقع owner_status='claimed').

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

فایل نقش
src/Doctor/Entity/Doctor.php toDetailArray() (L530576) و toListArray() (L506–528) — سریال‌سازی satisfaction/point/owner_status
src/Doctor/Controller/DoctorController.php show() L149173 (public GET /api/v1/doctor/{uuid}list() L244260 (public GET /api/v1/doctors) — بدون تغییر، فقط مصرف‌کننده
docs/api/doctor.md باید به‌روز شود

وضعیت فعلی

فیلدهای انتیتی (src/Doctor/Entity/Doctor.php):

#[ORM\Column(name: 'doctor_rate', type: 'float')]
private float $doctorRate = 3.5;                 // L6768

#[ORM\Column(name: 'doctor_rate_percentage', type: 'float')]
private float $doctorRatePercentage = 60.0;      // L7071

// owner_status enum: claimed | unclaimed | pending_transfer  (L83)
#[ORM\Column(name: 'owner_status', type: 'string', length: 20)]
private string $ownerStatus = 'claimed';         // L8485

سریال‌سازی فعلی (هر دو آرایه امتیاز را همیشه برمی‌گردانند):

// toDetailArray()  L557559
'satisfaction'        => (string) $this->doctorRatePercentage,
'point'               => (string) $this->doctorRate,
'owner_status'        => $this->ownerStatus,

// toListArray()  L521526  — همان دو کلید + owner_status

وظایف

۱. helper برای «آیا امتیاز واقعی نمایش داده شود؟»

در Doctor.php یک متد کوچک اضافه کن (منبع واحد منطق):

/** امتیاز فقط برای پروفایل claimed معتبر است؛ unclaimed/pending_transfer مقدار پیش‌فرض جعلی دارد. */
public function hasPublicRating(): bool
{
    return $this->ownerStatus === 'claimed';
}

۲. null کردن امتیاز در toDetailArray() و toListArray()

در هر دو متد، به‌جای مقدار مستقیم:

'satisfaction' => $this->hasPublicRating() ? (string) $this->doctorRatePercentage : null,
'point'        => $this->hasPublicRating() ? (string) $this->doctorRate           : null,

owner_status بدون تغییر بماند (frontend به آن نیاز دارد). کلیدها حذف نشوند، فقط مقدارشان null شود تا شکل پاسخ نشکند.

۳. مستندسازی

docs/api/doctor.md را به‌روز کن:

  • در توضیح فیلدهای پاسخ single (L83118) و list (L196222) ذکر کن: point و satisfaction برای owner_status !== 'claimed' مقدار null دارند.
  • یک خط در header note اضافه کن که امتیاز پیش‌فرض فقط برای پروفایل claimed منتشر می‌شود.

نکات مهم

  • پاسخ double-nested است: show() از $this->success(['data' => array_merge($doctor->toDetailArray($schedule), [...])]) استفاده می‌کند → frontend با data.data.data می‌خواند. شکل را تغییر نده، فقط مقدار دو کلید.
  • بعد از claim خودکار درست می‌شود: DoctorClaimService::finalize() وضعیت را به 'claimed' می‌برد → hasPublicRating() صحیح می‌شود → امتیاز واقعی برمی‌گردد. نیازی به منطق اضافه برای «برگشت به حالت عادی» نیست.
  • pending_transfer هم مثل unclaimed امتیاز نداشته باشد (فقط claimed امتیاز دارد).
  • تست موجود اگر روی toDetailArray/toListArray هست را چک کن (مقدار point/satisfaction ممکن است اکنون null شود). ddev exec php bin/phpunit.
  • migration لازم نیست (فقط منطق سریال‌سازی، نه تغییر schema).
  • بعد از تغییر: ddev exec php vendor/bin/phpstan analyse و graphify update ..