# خطة الاستضافة — ERP (شامل وحدة العيادات)

آخر تحديث: 2026-08-31 — مبني على فحص فعلي للمشروع (ليس افتراضات عامة).

## 1) متطلبات المشروع الفعلية

| العنصر | القيمة | ملاحظة |
|---|---|---|
| PHP | `^8.2` (composer.json) | يُفضّل تشغيل 8.3 على الخادم لدعم أطول وتحسينات أداء |
| Framework | Laravel 12 | |
| قاعدة البيانات | MySQL 8.0+ / MariaDB 10.6+ | `DB_CONNECTION=mysql` |
| Extensions مطلوبة | `gd` **(بدعم WebP — مُستخدم فعليًا في رفع الصور)**, `pdo_mysql`, `mbstring`, `bcmath`, `zip`, `openssl`, `curl`, `fileinfo` | تأكد من تفعيل WebP في GD تحديدًا عند اختيار الاستضافة |
| التخزين | **قرص دائم (Persistent Disk)**، وليس تخزين مؤقت/ephemeral | الصور والمرفقات (PDF/صور) تُكتب مباشرة في `public/uploads/...`، وليس عبر S3 — أي استضافة "بدون قرص دائم" (بعض منصات الـ PaaS) ستفقد الملفات عند كل نشر جديد |
| حجم الرفع | `upload_max_filesize` و`post_max_size` **لا تقل عن 64M** (وفي Nginx: `client_max_body_size 64m`) | فيديو قسم «من نحن» في البيانات الرئيسية يقبل حتى 50 ميجابايت |
| البريد | `MAIL_MAILER=log` حاليًا (إعداد تطوير فقط) | **يجب استبداله بخدمة SMTP/Transactional حقيقية قبل الإطلاق** (مثل Mailgun, SES, Brevo) |
| WebSocket (الشات) | Laravel Reverb مُهيأ بالكامل، وPusher كبديل جاهز | التفاصيل في القسم 3 — هذا هو العامل الأهم في اختيار نوع الاستضافة |
| SSL | إلزامي | المشروع يتعامل مع حجوزات ودفعات وبيانات مرضى |

## 2) مقارنة أنواع الاستضافة

| المعيار | استضافة مشتركة (cPanel) | VPS (خادم افتراضي خاص) | Managed Cloud / PaaS (مثل Forge+VPS, Laravel Cloud) |
|---|---|---|---|
| **تشغيل عملية دائمة (Reverb WebSocket)** | ❌ غير مدعوم عادةً | ✅ عبر Supervisor/systemd | ✅ (لو المنصة تدعم Worker Processes منفصلة) |
| **Cron حقيقي (للتذكيرات المستقبلية بمواعيد الحجز)** | ✅ متوفر غالبًا | ✅ | ✅ |
| **Queue Worker دائم (`queue:work`)** | ⚠️ محدود/غير مضمون الاستمرارية | ✅ عبر Supervisor | ✅ |
| **Redis (للكاش المستقبلي)** | ❌ نادرًا ما يكون متاحًا | ✅ تثبيت مباشر | ✅ (غالبًا كخدمة منفصلة جاهزة) |
| **سهولة الإدارة** | الأسهل (لوحة تحكم جاهزة) | تحتاج خبرة SSH/Linux أو مدير سيرفر | متوسطة — Forge مثلاً يبسّط VPS بواجهة إدارة |
| **التكلفة** | الأرخص | متوسطة، تدفع فقط للموارد | أعلى قليلًا (رسوم الإدارة + الخادم) |
| **التحكم/الخصوصية (بيانات مرضى)** | محدود | كامل | كامل غالبًا |
| **مناسب لهذا المشروع؟** | ❌ لا يكفي بسبب Reverb + الخطط المستقبلية (Redis + تذكيرات مجدولة) | ✅ الأنسب | ✅ الأفضل لو الميزانية تسمح (يقلل عبء الصيانة اليدوية) |

### لماذا الاستضافة المشتركة غير كافية لهذا المشروع تحديدًا

بخلاف مشروع بسيط، هذا المشروع يحتاج **ثلاث قدرات لا تتوفر عادة في cPanel التقليدي**:
1. **عملية خلفية دائمة** لتشغيل Reverb (الشات المباشر) — ما لم يُستخدم Pusher بدلًا منه (انظر القسم 3).
2. **Redis** كخدمة تعمل باستمرار — مطلوب للخطة المستقبلية للكاش.
3. **Queue Worker مستمر** — مطلوب لتنفيذ إرسال التذكيرات بمواعيد الحجز بشكل موثوق دون تعليق طلب المستخدم (انظر القسم 4).

## 3) قرار Reverb مقابل Pusher (يحدد هل تحتاج VPS أصلًا)

المشروع مُجهّز بالكامل لكلا الخيارين — التبديل بينهما هو سطر واحد في `.env` (`BROADCAST_CONNECTION`) بدون أي تعديل كود.

| | Reverb (ذاتي الاستضافة) | Pusher (SaaS) |
|---|---|---|
| يحتاج VPS؟ | نعم (عملية دائمة + Nginx reverse proxy لـ `wss://`) | لا — يعمل على أي استضافة PHP عادية |
| التكلفة الإضافية | لا شيء (ضمن تكلفة السيرفر) | اشتراك Pusher (مجاني حتى حد معيّن، ثم مدفوع) |
| خصوصية بيانات الشات | تبقى بالكامل على سيرفرك | تمر عبر سيرفرات Pusher الخارجية |
| التعقيد | أعلى (إعداد Supervisor + SSL للـ WebSocket) | أبسط (تعبئة مفاتيح API فقط) |

**التوصية**: لو قررت VPS أصلًا (بسبب Redis + التذكيرات المجدولة أدناه)، لا يوجد سبب إضافي لتفادي Reverb — التكلفة الحدّية صفر. لكن يمكن البدء بـ Pusher في أول أسابيع الإطلاق لتقليل نقاط الفشل أثناء المراقبة، ثم التبديل لاحقًا.

## 4) خطط مستقبلية مذكورة — وأثرها على الاستضافة

### أ) الكاش (Redis)

- يحتاج تثبيت **Redis Server** على السيرفر (خفيف الموارد، عادة ~512MB–1GB RAM كافية لحجم هذا المشروع).
- على جهة الكود: `config/cache.php` في Laravel يدعم `redis` كخيار جاهز مسبقًا، فقط يحتاج مكتبة عميل (`predis/predis` أو امتداد `phpredis`) وتغيير `CACHE_STORE=redis` في `.env` — لا حاجة لتعديل كود التطبيق نفسه.
- **ملاحظة تقنية من هذه الجلسة**: محاولة تثبيت `predis/predis` عبر Composer على بيئة التطوير المحلية (Windows/XAMPP) واجهت مشكلة قفل ملفات معروفة (مضاد الفيروسات/مفهرس بحث Windows) أثناء الاستخراج — تم التراجع عن المحاولة مؤقتًا لتفرغ للمهمة الحالية. هذا لن يحدث على سيرفر Linux (VPS/استضافة)، فالتثبيت هناك متوقع أن يمر بسلاسة.

### ب) الإشعارات والتذكيرات (تم تنفيذها — plan_Clinics/12-notifications-plan.md)

الإشعارات داخل النظام (جرس الأدمن والطبيب والمريض) تُكتب فورًا ولا تحتاج شيئًا على السيرفر.
أما التذكيرات قبل المواعيد، والإرسال عبر واتساب/SMS/Push، فتحتاج على السيرفر:

1. **Cron للمهام المجدولة** (يشغّل `clinic:send-appointment-reminders` كل 5 دقائق):
   ```
   * * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1
   ```
2. **Queue Worker** لإرسال واتساب/SMS/Push (مع `QUEUE_CONNECTION=database`):
   - على VPS تحت Supervisor:
     ```
     php artisan queue:work --sleep=3 --tries=3 --max-time=3600
     ```
   - على cPanel بدون Supervisor: سطر Cron إضافي يشغّل الـ Worker كل دقيقة ثم يتوقف:
     ```
     * * * * * cd /path-to-project && php artisan queue:work --stop-when-empty --max-time=55 >> /dev/null 2>&1
     ```
   بدون Worker تبقى رسائل واتساب/SMS/Push في جدول `jobs` ولا تُرسل (إشعارات الجرس تعمل عادي).

3. **بعد رفع التحديث**:
   ```
   composer install --no-dev
   php artisan migrate --force
   php artisan db:seed --class=IntegrationProviderSeeder --force
   php artisan config:cache && php artisan route:cache
   ```

4. **تفعيل المزوّدين** (الإعدادات ← التكاملات)، ثم الإعدادات ← الإشعارات ← "تجربة وسجل" لإرسال رسالة تجريبية:
   - **SMS**: حساب Msegat أو Twilio + اسم مرسل معتمد.
   - **واتساب (Meta Cloud API)**: حساب Meta Business + رقم واتساب موثّق + Access Token دائم (System User).
     رسائل التذكير والتأكيد تبدأها العيادة، فـ Meta لا توصلها إلا عبر **قوالب معتمدة**: أنشئ قالبًا لكل رسالة
     في Meta Business Manager بمتغيرات بالترتيب {{1}} المريض، {{2}} الطبيب، {{3}} التاريخ، {{4}} الوقت، {{5}} العيادة، {{6}} الفرع،
     ثم اكتب اسم القالب في الإعدادات ← الإشعارات ← نصوص واتساب / SMS.
   - **Push**: مشروع Firebase + ملف Service Account (JSON) في التكاملات، وتطبيق الموبايل يسجّل رمز الجهاز عبر
     `POST /api/patient/devices`.

5. **المتابعة**: سجل الإرسال في الإعدادات ← الإشعارات يوضح كل رسالة (تم الإرسال / فشل / تم التخطي والسبب).

## 5) التوصية النهائية

| الحجم | المواصفات | التكلفة التقريبية شهريًا | يناسب |
|---|---|---|---|
| **بداية** | 2 vCPU / 4GB RAM / 80GB SSD NVMe | $18–24 (Hetzner / DigitalOcean / Vultr) | 1–3 عيادات، حركة متوسطة، يشمل Redis + Worker + Reverb معًا بارتياح |
| **نمو/إنتاج فعلي** | 4 vCPU / 8GB RAM / 150GB SSD NVMe | $40–48 | عدة فروع/عيادات، حجوزات ودفعات ومحادثات نشطة يوميًا |

**المكدس الكامل الموصى به على السيرفر**:
- Nginx + PHP-FPM 8.3
- MySQL 8
- Redis (للكاش المستقبلي)
- Supervisor يدير: Reverb (لو اخترته)، و`queue:work` (لتنفيذ التذكيرات لاحقًا)
- Cron واحد لـ `schedule:run`
- Let's Encrypt SSL
- نسخ احتياطي يومي لقاعدة البيانات **و**`public/uploads` (الملفات لا تُخزَّن على S3 حاليًا، فهي عرضة للفقدان الكامل عند أي عطل في السيرفر بدون نسخة احتياطية منفصلة)

**نقطة قرار لاحقة (وليست الآن)**: قبل تفعيل ميزة تذكيرات الحجز فعليًا في الكود، يُفضّل تأكيد: (1) قناة الإرسال (SMS؟ بريد؟ إشعار داخل النظام فقط؟)، (2) التوقيت الافتراضي للتذكير (كم ساعة قبل الموعد)، (3) هل يُرسل للمريض فقط أم للطبيب أيضًا — هذه قرارات منتج يجب تأكيدها قبل البناء، وليست قرارات استضافة.
