7.8 KiB
پیامک اعلان نوبت جدید به «شمارهٔ اعلان» دکتر (فقط نوبتهای پرداختشدهٔ سایت)
پروژه
clinicpro (backend / Payment + Sms)
زمینه
هر دکتر در /admin/profile یک «شمارهٔ اعلان نوبت» (Doctor::notificationMobile) ست میکند («پیامک نوبت جدید به این شماره ارسال میشود»). این فیلد و تگ SmsLog::TAG_NOTIFICATION_MOBILE وجود دارند، ولی تگ فعلی فقط برای تأیید ثبت شماره (کد تأیید در NotificationMobileController) استفاده میشود — به رویداد «نوبت جدید» وصل نیست.
الان هنگام موفقیت پرداخت نوبت، فقط به بیمار پیامک میرود (PaymentManager::handleAppointmentConfirmation با تگ TAG_PAYMENT). هدف: علاوه بر آن، به شمارهٔ اعلانِ دکتر هم یک پیامک با قالب مشخص (شامل نام بیمار و ساعت نوبت) ارسال شود.
فقط نوبتهای پرداختشده از سایت باید این پیامک را بدهند — نه نوبتهایی که منشی ثبت میکند. چون handleAppointmentConfirmation فقط در مسیر موفقیت پرداخت (PaymentManager::processCallback → runPostAction) اجرا میشود و نوبتهای ثبتشده توسط منشی از این مسیر عبور نمیکنند، افزودن کد در همینجا بهطور طبیعی شرط «فقط سایت/پرداخت» را رعایت میکند.
مشکل / هدف
هنگام تأیید پرداختِ یک نوبت، اگر دکترِ آن نوبت notificationMobile ست کرده باشد، یک پیامک با تگ/قالب اختصاصی (TAG_DOCTOR_APPOINTMENT) شامل {patient} و {date} و {time} به آن شماره ارسال شود.
فایلهای مرتبط
| فایل | نقش |
|---|---|
clinicpro/src/Sms/Entity/SmsLog.php |
افزودن تگ TAG_DOCTOR_APPOINTMENT + به آرایهٔ TAGS |
clinicpro/src/Sms/Entity/SmsMessageTemplate.php |
افزودن قالب پیشفرض این تگ به DEFAULTS |
clinicpro/src/Payment/Service/PaymentManager.php |
ارسال پیامک به notificationMobile دکتر در handleAppointmentConfirmation |
clinicpro/docs/api/sms.md |
مستندسازی تگ/قالب جدید |
وضعیت فعلی
PaymentManager::handleAppointmentConfirmation (فقط پیامک بیمار)
private function handleAppointmentConfirmation(Payment $payment): void
{
$appointment = $payment->getAppointment();
if ($appointment === null || !$appointment->canTransitionTo(Appointment::STATUS_CONFIRMED)) {
return;
}
$appointment->transitionTo(Appointment::STATUS_CONFIRMED);
$this->em->persist($appointment);
$doctor = $appointment->getDoctor();
$this->commissionService->processAppointment(
$payment,
$doctor->getRepresentationId(),
$appointment->getBookingRepresentationId(),
$doctor->getId(),
);
$mobile = $appointment->getPatientMobile();
if ($mobile) {
$when = $this->jalali->formatDateTime($appointment->getSlotStart());
$message = $this->smsText->resolve(SmsLog::TAG_PAYMENT, [
'doctor' => $doctor->getName(),
'date' => $when,
]);
$this->smsService->dispatchAsync($mobile, $message, tag: SmsLog::TAG_PAYMENT);
}
}
مقادیر در دسترس
Doctor::getNotificationMobile(): ?string(فیلدnotification_mobile, nullable)Doctor::getName()Appointment::getPatientName(): ?string،getPatientMobile()،getSlotStart(): int(unix)JalaliDateService::formatDateTime(int $ts, bool $withTime = true): string—false= فقط تاریخ شمسی. متد جدا برای «ساعت» ندارد؛ ساعت را باdate('H:i', $slotStart)بگیر.
الگوی تگها (SmsLog)
public const TAG_NOTIFICATION_MOBILE = 'notification_mobile';
public const TAGS = [ self::TAG_GLOBAL, self::TAG_OTP, self::TAG_PAYMENT, /* ... */ self::TAG_SECRETARY ];
الگوی قالبها (SmsMessageTemplate::DEFAULTS)
SmsLog::TAG_PAYMENT => [
'title' => 'تأیید پرداخت و نوبت',
'body' => 'نوبت شما با {doctor} در تاریخ {date} ثبت و تأیید شد.',
'variables' => ['doctor', 'date'],
],
وظایف
۱. تگ جدید در SmsLog
public const TAG_DOCTOR_APPOINTMENT = 'doctor_appointment';
و آن را به آرایهٔ TAGS اضافه کن (تا در پنل مدیریت قالبها و seed شناخته شود).
۲. قالب پیشفرض در SmsMessageTemplate::DEFAULTS
SmsLog::TAG_DOCTOR_APPOINTMENT => [
'title' => 'نوبت جدید (اعلان به پزشک)',
'body' => "نوبت جدید ثبت شد.\nبیمار: {patient}\nتاریخ: {date} ساعت {time}",
'variables' => ['patient', 'date', 'time'],
],
۳. ارسال پیامک به شمارهٔ اعلان دکتر در handleAppointmentConfirmation
بعد از بلوک پیامک بیمار (داخل همان متد)، اضافه کن:
$notify = $doctor->getNotificationMobile();
if ($notify) {
$docMessage = $this->smsText->resolve(SmsLog::TAG_DOCTOR_APPOINTMENT, [
'patient' => $appointment->getPatientName() ?? '—',
'date' => $this->jalali->formatDateTime($appointment->getSlotStart(), false),
'time' => date('H:i', $appointment->getSlotStart()),
]);
$this->smsService->dispatchAsync($notify, $docMessage, tag: SmsLog::TAG_DOCTOR_APPOINTMENT);
}
۴. seed قالب جدید
بعد از افزودن به DEFAULTS، دستور موجود را اجرا کن تا رکورد قالب برای تگ جدید ساخته شود (فقط تگهای بدون رکورد را میسازد):
ddev exec php bin/console app:seed-sms-message-templates
۵. مستندسازی
docs/api/sms.md: تگ doctor_appointment، قالب پیشفرض، placeholderها (patient/date/time)، و اینکه فقط برای نوبتهای پرداختشدهٔ سایت (در مسیر verify پرداخت) ارسال میشود و به Doctor.notificationMobile میرود.
نکات مهم
- فقط مسیر پرداخت: کد داخل
handleAppointmentConfirmationاست که تنها ازrunPostActionبعد از verify موفق صدا زده میشود؛ نوبتهای منشی (بدون پرداخت) اینجا نمیآیند — پس شرط «نه نوبت منشی» خودکار برقرار است. کد را جای دیگری (مثل ساخت نوبت) نگذار. - اگر
notificationMobileخالی بود، هیچ پیامکی نرود (شرطif ($notify)). dispatchAsyncمثل پیامک بیمار استفاده شود (صف async، شکست پیامک نباید جریان پرداخت را بشکند — الگوی موجود).- ارسال پیامک دکتر مستقل از پیامک بیمار است (حتی اگر
patientMobileخالی باشد، پیامک دکتر باید برود). title/bodyقالب فارسی و قابل ویرایش از پنل قالبهاست؛ فقط مقدار پیشفرض را درDEFAULTSبگذار.Doctorتغییر Entity ندارد (فیلد موجود است) → migration لازم نیست.- هزینهٔ پیامک: این پیامک هم مثل بقیه از کیفپول/سهمیهٔ پیامک همان entity کسر میشود (اگر
SmsService/wallet چنین منطقی دارد، خودکار اعمال میشود؛ چیزی اضافه نکن مگر لازم شود).