feat: implement doctor invitation acceptance logic to add doctors to clinic_doctors

This commit is contained in:
hamed
2026-06-13 17:53:27 +03:30
parent 5c167b5d39
commit aa15addcb9
5 changed files with 310 additions and 6 deletions
+106
View File
@@ -0,0 +1,106 @@
# Fix: پذیرفتن دعوتنامه کلینیک، پزشک را به clinic_doctors اضافه نمی‌کند
## مشکل
وقتی پزشک دعوتنامه کلینیک را می‌پذیرد (از طریق پنل پزشک یا لینک SMS)، فقط وضعیت دعوتنامه به `accepted` تغییر می‌کند — اما پزشک به جدول `clinic_doctors` اضافه **نمی‌شود**.
## ریشه باگ
`src/ClinicInvitation/Service/ClinicInvitationService.php` — متد `accept()`:
```php
public function accept(ClinicDoctorInvitation $inv): void
{
if (!$inv->isUsable()) {
throw new AppException('ERR_NOT_FOUND_001', 'دعوتنامه منقضی یا غیرمعتبر است', 410);
}
$inv->setStatus(ClinicDoctorInvitation::STATUS_ACCEPTED);
$inv->markUsed();
$this->em->flush(); // ← فقط status عوض می‌شود، هیچ رابطه‌ای ثبت نمی‌شود
}
```
باید بعد از `accept`، پزشک به `$clinic->getDoctors()` اضافه شود. رابطه در `Clinic::$doctors` (ManyToMany → جدول `clinic_doctors`) تعریف شده است.
## فایل‌های مرتبط
| فایل | نقش |
|------|-----|
| `src/ClinicInvitation/Service/ClinicInvitationService.php` | متد `accept()` — جای اصلی باگ |
| `src/ClinicInvitation/Entity/ClinicDoctorInvitation.php` | entity دعوتنامه — دارای `getClinic()` و `getDoctor()` |
| `src/Clinic/Entity/Clinic.php` | دارای `getDoctors(): Collection` و رابطه ManyToMany |
## وضعیت فعلی
- `ClinicDoctorInvitation::$doctor` وقتی پزشک در سیستم وجود دارد، set می‌شود (در `invite()`)
- `ClinicDoctorInvitation::$doctor` ممکن است `null` باشد (پزشک هنوز ثبت‌نام نکرده)
- پذیرش از دو مسیر اتفاق می‌افتد:
1. **لینک SMS**`POST /api/v1/clinic-invitation/{token}/accept` (بدون احراز هویت)
2. **پنل پزشک**`POST /api/v1/doctor/invitation/{invUuid}/respond` با `action=accept`
## وظایف
### ۱. رفع باگ در `ClinicInvitationService::accept()`
```php
public function accept(ClinicDoctorInvitation $inv): void
{
if (!$inv->isUsable()) {
throw new AppException('ERR_NOT_FOUND_001', 'دعوتنامه منقضی یا غیرمعتبر است', 410);
}
$inv->setStatus(ClinicDoctorInvitation::STATUS_ACCEPTED);
$inv->markUsed();
// اضافه کردن پزشک به کلینیک
$doctor = $inv->getDoctor();
if ($doctor !== null) {
$clinic = $inv->getClinic();
if (!$clinic->getDoctors()->contains($doctor)) {
$clinic->getDoctors()->add($doctor);
}
}
$this->em->flush();
}
```
### ۲. بررسی حالت لبه‌ای: پزشک null است
اگر `$inv->getDoctor()` در زمان accept هنوز null باشد (پزشک بعداً ثبت‌نام کرده)، باید با موبایل در DoctorRepository جستجو کرد و doctor را set و اضافه کرد:
```php
if ($doctor === null) {
$doctor = $this->doctorRepo->findOneByMobile($inv->getMobile());
if ($doctor !== null) {
$inv->setDoctor($doctor);
}
}
```
### ۳. تست
بعد از رفع:
```bash
ddev exec php -l src/ClinicInvitation/Service/ClinicInvitationService.php
ddev exec php bin/console cache:clear
ddev exec yarn dev
```
تست دستی:
- یک دعوتنامه ارسال کن
- پزشک از پنل داشبورد دعوت را بپذیرد
- در صفحه کلینیک بررسی کن که پزشک در لیست پزشکان کلینیک ظاهر شده
### ۴. مستندات
فایل `docs/api/clinic-invitation.md` را به‌روزرسانی کن:
- اضافه کن: هنگام accept، پزشک به clinic_doctors اضافه می‌شود
- edge case: اگر doctor هنگام دعوت ثبت‌نام نکرده بود، هنگام accept با موبایل match می‌شود
## نکات مهم
- **هر دو مسیر** (لینک SMS و پنل پزشک) از همان `$invitationService->accept()` استفاده می‌کنند — رفع باگ در یک جا کافی است
- `$clinic->getDoctors()->contains($doctor)` را چک کن تا duplicate نشود
- بعد از flush نیازی به migration نیست — جدول `clinic_doctors` از قبل وجود دارد