تتتبّع هذه الصفحة كل مسار يتحرك وحده أو بنقرة واحدة. اقرأها قبل أن تقرأ أي رقم في المقاييس: فالرقم لا معنى له حتى تعرف أي خطوة كتبته.
كيف تعمل الأتمتة هنا
لا يوجد في سبيس مُجدوِل: لا مشغّل cron في wrangler.jsonc، ولا عامل طوابير، ولا بريد إلكتروني. ما يحدث "وحده" يحدث بإحدى ثلاث طرق.
| الآلية | متى تعمل | أمثلة |
|---|---|---|
| كسولة عند القراءة | كلما قيّمت صفحة أو استعلام شرطاً | انتهاء حجز المقعد في الحجوزات والتذاكر، وإغلاق مواعيد البرامج والفرص، وانتهاء الباقات |
| المهام اليومية | عند أول فتح لصفحة /dashboard/desk في كل يوم بتوقيت بورتسودان | فواتير الإيجار، والخروج المنسي، وإكمال الحجوزات أو إلغاؤها |
| داخل المعاملة | داخل الإجراء الذي يطلقه الضيف أو الموظف | قائمة الانتظار عند امتلاء السعة، وقفل تعارض القاعات، وإصدار التذاكر المجانية فوراً |
أحداث الحجز والمقهى ترسل أيضاً إشعارات تلقائياً — جرس التطبيق، والإشعار على الهاتف، وواتساب، والبريد، كلٌّ متى ضُبط؛ انظر الإشعارات. أما بقية الروابط الخارجة فهي روابط واتساب (wa.me): يضغطها الضيف أو الموظف ويرسل الرسالة بنفسه، ولا تُسجَّل أي ضغطة.
إن لم يفتح أحد مكتب الاستقبال في يوم ما، فلن تعمل مهام ذلك اليوم. تعمل في المرة التالية التي يُفتح فيها المكتب، ولا تسجّل إلا آخر يوم. راجع DeskSettings.routinesRanOn — انظر استعلام صحة الأتمتة في المقاييس.
دليل الألوان
الحالات الخضراء يصل إليها النظام. الرمادية يضعها شخص. السطر الثاني يعرض الحالات التي قد يخرج إليها السجل من المسار.
الحجز
يختار الضيف منتجاً ووقتاً في /book. يسعّر createOnlineBooking الطلب إن كان للمنتج سعر محدد، ويأخذ قفلاً في Postgres على القاعة، ويتحقق من التعارض، ثم ينقل الضيف إلى صفحة حجزه.
| الخطوة | من | ما يُسجَّل |
|---|---|---|
إنشاء الطلب؛ القاعة المسعّرة تُحجز لمدة ticketHoldMinutes (افتراضياً 120 دقيقة) | الضيف | createdAt، amount، holdUntil |
| الضيف يرسل رقم عملية بنكك | الضيف | bankakReference، paymentSubmittedAt |
| الموظف يتحقق من التحويل ← يُكتب القيد والدفعة في الدفتر | الاستقبال (ADMIN، CASHIER) | DeskCharge.createdAt، DeskPayment.createdAt |
| الموظف يرفض التحويل | الاستقبال | cancelReason (بلا وقت) |
| ضيف التذكرة اليومية يسجّل الدخول ← CONFIRMED | الاستقبال | DeskVisit.checkedInAt |
تلقائي: مؤكد وتجاوز endsAt ← COMPLETED | المهام اليومية | updatedAt فقط |
تلقائي: معلّق ولم يُدفع وتجاوز endsAt ← CANCELLED | المهام اليومية | updatedAt فقط |
كسول: تجاوز الحجز holdUntil ← يتحرر الموعد وتعرض صفحة الضيف "منتهٍ" | عند القراءة | بلا تغيير في الحالة |
المكاتب المخصصة والمكاتب الخاصة وكل منتج بلا سعر تأخذ amount = null: يسعّرها الفريق عبر واتساب.
التذاكر
الفعاليات المدفوعة تبيع التذاكر على الإنترنت أو عند الباب. يقفل createOnlineOrder صف الفعالية، ويعدّ المقاعد المدفوعة والمرسلة والمحجوزة، ويحدّ الطلب بعشر تذاكر.
| الخطوة | من | ما يُسجَّل |
|---|---|---|
| إنشاء الطلب وحجز المقاعد | الضيف | createdAt، holdUntil |
| تذكرة مجانية (سعرها 0) ← PAID وتُصدر التذاكر فوراً | النظام | paidAt |
| الضيف يرسل رقم بنكك | الضيف | bankakReference (بلا وقت خاص) |
| الموظف يتحقق ← PAID، وتُصدر التذاكر، ويُكتب الدفتر | الاستقبال | paidAt |
| بيع عند الباب ← PAID فوراً (نقداً أو بنكك) | الاستقبال | paidAt، channel = DOOR |
| مسح رمز QR عند الباب ← دخول، مرة واحدة | الاستقبال | Ticket.checkedInAt |
| كسول: انتهاء الحجز ← تتحرر المقاعد | عند القراءة | يبقى الطلب PENDING إلى الأبد |
التسجيل في الفعاليات المجانية
الفعاليات بلا أنواع تذاكر تقبل التسجيل في صفحة الفعالية. داخل معاملة واحدة، يعدّ registerForEvent صفوف REGISTERED: إن امتلأت الفعالية يصبح الصف الجديد WAITLISTED.
كل ما بعد التسجيل يدوي في لوحة الإدارة. لا ترقية من قائمة الانتظار حين يتحرر مقعد، ولا يحفظ الصف إلا createdAt.
طلبات البرامج
يقبل applyToProgram الطلب ما دام البرنامج OPEN وقبل موعده النهائي. الموعد النهائي يغلق النموذج بشكل كسول — الحالة المخزنة لا تتغير أبداً.
الاستفسارات
نماذج التواصل والشركاء والمجتمع والعضوية كلها تكتب Enquiry مع topic (وتحفظ العضوية الباقة في subject). ويستطيع الضيف المتابعة على واتساب مباشرة.
مكتب الاستقبال
- الزيارات. زيارة مفتوحة واحدة لكل عميل. التذكرة اليومية تكتب قيد
DAY_PASS؛ وزيارة الباقة تُفحص مقابل دقائق الباقة وانتهائها. الخروج يقرّب الدقائق للأعلى ويضيفها إلى الباقة. - الزيارات المنسية. تغلق المهام اليومية الزيارات المفتوحة من يوم سابق عند وقت إغلاق ذلك اليوم وتكتب "auto check-out at closing".
- الباقات. تُباع في الاستقبال. حالات النشطة والمستنفدة والمنتهية تُحسب عند القراءة.
- المكاتب. عقد نشط واحد لكل مكتب. فواتير الإيجار الشهرية تصدر تلقائياً من المهام اليومية (أو بزر الإدارة)، فاتورة لكل عقد في كل شهر، مستحقة في يوم الاستحقاق. الإيجار المتأخر له رابط تذكير على واتساب.
- الدفتر. كل قيد (
DAY_PASS،PACKAGE،OFFICE_RENT،ROOM_HIRE،TICKET،OTHER) يقبل دفعات جزئية نقداً أو ببنكك. الإلغاءات تُحفظ مع سببها.
المقهى
يطلب الضيوف بمسح رمز QR على الطاولة (channel = QR)؛ ويسجّل الموظفون طلبات الكاونتر (channel = COUNTER، ويبدأ مؤكداً).
كل تغيير في الحالة أو الدفع يختم وقته (confirmedAt، preparingAt، readyAt، completedAt، cancelledAt، paidAt) ويكتب صفاً في CafeOrderEvent مع اسم الموظف. إنه سجل الأحداث الكامل الوحيد في المنتج. شاشات الموظفين تتحدّث كل 5 ثوانٍ وتنبّه كل 30 ثانية ما دام طلب ينتظر.
الإبلاغ عن مشكلة
نافذة الإبلاغ في التذييل ولوحة الإدارة تشغّل مساراً: مرشحات ← حدّ المعدل ← بحث عن التكرار في GitHub وفرز بالذكاء الاصطناعي (حين يوجد مفتاح) ← درجة. البلاغات التي تبلغ 30 أو أكثر تصبح مشكلات في GitHub. قياساته تذهب إلى سجلات الـ Worker فقط.
حراسة كل نموذج عام
- حقل مصيدة مخفي، ثم حدّ معدل لكل عنوان IP (5 إرسالات كل 10 دقائق افتراضياً؛ والمقهى يسمح بـ 60).
- البوت المكشوف يتلقى نجاحاً وهمياً، فلا يعيد المحاولة.
- المحدِّد يعيش في ذاكرة كل Worker، ولا يُعدّ شيء — راجع التحسينات.