5.4 KiB
پروفایل 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() (L530–576) و toListArray() (L506–528) — سریالسازی satisfaction/point/owner_status |
src/Doctor/Controller/DoctorController.php |
show() L149–173 (public GET /api/v1/doctor/{uuid})، list() L244–260 (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; // L67–68
#[ORM\Column(name: 'doctor_rate_percentage', type: 'float')]
private float $doctorRatePercentage = 60.0; // L70–71
// owner_status enum: claimed | unclaimed | pending_transfer (L83)
#[ORM\Column(name: 'owner_status', type: 'string', length: 20)]
private string $ownerStatus = 'claimed'; // L84–85
سریالسازی فعلی (هر دو آرایه امتیاز را همیشه برمیگردانند):
// toDetailArray() L557–559
'satisfaction' => (string) $this->doctorRatePercentage,
'point' => (string) $this->doctorRate,
'owner_status' => $this->ownerStatus,
// toListArray() L521–526 — همان دو کلید + 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 (L83–118) و list (L196–222) ذکر کن:
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 ..