نظام إدارة اشتراكات كامل لنادٍ رياضي: ملف لكل عضو بصورته، سجل اشتراكات لا يُعدّل أبدًا، لوحة تحكم تنبّهك قبل انتهاء أي اشتراك، تجديد بضغطة وحدة، وتقارير مالية بمدى تاريخي. وفوق هذا كله — API تحقق جاهز يخلي بوابة النادي نفسها تقرر مين يدخل ومين لا.
أغلب النوادي تدير اشتراكاتها بدفتر أو بملف إكسل: ما تعرف مين اشتراكه خلص إلا لما يجي للباب، ولا تعرف كم جمعت هذا الشهر إلا بالحساب اليدوي، ولا تقدر تمنع عضو معيّن من الدخول بدون ما تعتمد على ذاكرة موظف الاستقبال. GYM 80 يحوّل هذا كله لنظام واحد: كل اشتراك له تاريخ بداية ونهاية وحالة دفع، والنظام نفسه يحسب من هو الفعّال ومن هو المنتهي ومن قرب ينتهي — ويعطي البوابة قرارًا جاهزًا بدل الاجتهاد البشري.
ملف عضو كامل — رقم PIN ثابت لكل عضو، اسم، هاتف، تاريخ ميلاد، وصورة شخصية مرفوعة ومُتحقَّق منها كصورة حقيقية (مو بالامتداد فقط).
سجل اشتراكات لا يُعدّل — كل تجديد يُضاف كسطر جديد بدل ما يستبدل القديم، فيبقى تاريخ العضو المالي كامل ومرجعي: المبلغ، المدة، تاريخ البداية والنهاية، وحالة الدفع.
لوحة تحكم تنبيهية — ستة مؤشرات فورية (إجمالي الأعضاء، الفعّالة، المنتهية، القريبة من الانتهاء، إيراد الشهر، مشتركون جدد) وقوائم جاهزة بالاشتراكات اللي على وشك الانتهاء وبالمنتهية فعلًا.
تجديد بضغطة وحدة — زر تجديد بجانب كل عضو بالقوائم يفتح نافذة سريعة تحسب تاريخ الانتهاء الجديد تلقائيًا حسب المدة المختارة.
تقارير مالية بمدى تاريخي — من تاريخ / إلى تاريخ، مع إجمالي المحصّل، عدد الاشتراكات، متوسط قيمة الاشتراك، والمستحقات غير المدفوعة، قابلة للتصدير والطباعة.
سجل دخول موثّق — كل محاولة تحقق (ناجحة أو فاشلة) تُسجّل بالاسم والرقم والنتيجة وعنوان الـ IP والوقت، فتبقى عندك مرجعية كاملة لحركة الباب.
إيقاف وصول يدوي — الأدمن يقدر يمنع أي عضو من الدخول بغض النظر عن اشتراكه، والمنع له الأولوية على كل الحالات الثانية.
النظام ما يفترض نوع جهاز معيّن عند الباب. نقطة التحقق POST /api/verify.php تستقبل رقم العضو وترجّع قرار وصول جاهز بالعربي، وهذا يخلي أي جهاز يقدر يستخدمها: قارئ بطاقات RFID/NFC يحوّل رقم البطاقة لرقم العضو ويرسله، أو بوابة تعرّف على الوجه تتعرّف على العضو محليًا وترسل رقمه، أو حتى موظف استقبال يدخل الرقم بيده من صفحة التحقق. الثلاثة يوصلون لنفس الجواب من نفس المصدر — فما يصير عندك نسختين من الحقيقة.
# الجهاز عند الباب يرسل رقم العضو فقط curl -X POST https://gym80.local/api/verify.php \ -H "X-API-KEY: <مفتاح الجهاز>" \ -H "Content-Type: application/json" \ -d '{"pin": "1001"}' # والرد يحمل القرار + بيانات العرض على شاشة البوابة { "status": "valid", "member": { "name": "...", "photo_url": "/uploads/members/1001.jpg" }, "subscription": { "end_date": "2026-04-01", "days_remaining": 12 }, "message_ar": "الاشتراك فعّال" }
validاشتراك فعّال — البوابة تفتح، وتقدر تعرض اسم العضو وصورته على الشاشة.expiring_soonفعّال لكن باقي له أيام معدودة — تفتح مع تنبيه للعضو بأن اشتراكه قارب على الانتهاء.expiredالاشتراك منتهي — ترفض مع عدد الأيام اللي مرّت على الانتهاء.unpaidالاشتراك الأخير مسجّل كغير مدفوع — ترفض وتحوّله للاستقبال.disabledعضو موقوف يدويًا من الإدارة — ترفض دائمًا، حتى لو اشتراكه فعّال ومدفوع.not_foundرقم غير موجود أصلًا — بطاقة غير مسجّلة أو وجه غير معروف.مفتاح مستقل لكل جهاز — كل بوابة أو قارئ ياخذ مفتاح X-API-KEY خاص فيه، يتولّد ويتعطّل من الإعدادات بدون ما تلمس بقية الأجهزة. الجهاز اللي ينسرق أو ينفصل، تلغي مفتاحه وخلص.
حد استخدام تلقائي — 60 طلب بالدقيقة لكل مفتاح، فجهاز معطّل أو سكربت مكرر ما يقدر يغرق السيرفر.
كل محاولة تُسجّل — الرقم والنتيجة وعنوان الـ IP والوقت، تظهر بصفحة "سجل الدخول" بلوحة التحكم، سواء جت من البوابة أو من موظف الاستقبال.
نقاط إضافية للأجهزة — GET /api/member.php يرجّع ملف العضو وسجل اشتراكاته الكامل، و GET /api/expiring.php يرجّع كل من قرب اشتراكه على الانتهاء — مفيدة لشاشة استقبال أو تنبيهات تلقائية.


اللوحة مبنية بقائمة جانبية ثابتة: الرئيسية، الأعضاء، البحث، تسجيل الدخول، سجل الدخول، التقارير المالية، الإعدادات. الصفحة الرئيسية تفتح على ستة مؤشرات — إجمالي الأعضاء، الاشتراكات الفعّالة، المنتهية ولم تُجدَّد، القريبة من الانتهاء، إيراد الشهر الحالي، والمشتركين الجدد هذا الشهر — وتحتها مباشرة قائمتان عمليتان: من قرب اشتراكه على الانتهاء ومن انتهى فعلًا، وكل صف فيها عنده زر تجديد فوري. وبالأسفل آخر عشر عمليات دخول، عشان تعرف بنظرة وحدة شنو صار اليوم على الباب.
عتبة التنبيه قابلة للضبط — تحدد من الإعدادات كم يوم قبل الانتهاء يُعتبر الاشتراك "قريب الانتهاء"، والنظام كله (اللوحة والـ API) يمشي على نفس الرقم.
صفحة تحقق للاستقبال — إدخال رقم العضو يعطي بطاقة نتيجة فيها صورته وحالته ومدة اشتراكه المتبقية، مع زر تجديد مباشر إذا طلع منتهي. وهي ما تستخدم مفتاح الـ API أبدًا — تمر عبر وسيط محمي بجلسة الأدمن.
بحث سريع — بالاسم أو الرقم أو الهاتف، للوصول لملف أي عضو بثوانٍ وقت الازدحام على الاستقبال.


تختار مدى تاريخي فتطلع خمسة أرقام مباشرة: عدد الاشتراكات، عدد الأعضاء، إجمالي المبلغ المحصّل، متوسط قيمة الاشتراك، والمستحقات غير المدفوعة — ومعها جدول تفصيلي بكل عملية. تقدر تبدّل حالة الدفع من نفس الجدول، وتصدّر النتيجة أو تطبعها كتقرير جاهز لصاحب النادي.
نظام يمسك بيانات أعضاء وصورهم وحركة دخولهم اليومية لازم ينبني بحذر — هذي القرارات مأخوذة من أول سطر مو مضافة لاحقًا.
PDO بالكامل — كل استعلام SQL بالنظام يمر بعبارات مُجهّزة (Prepared Statements)، فما فيه أي مكان يُدمج فيه إدخال المستخدم داخل الاستعلام.
CSRF على كل عملية — كل فورم وكل طلب Fetch يغيّر بيانات يحمل توكن مرتبط بالجلسة ويُتحقق منه بالسيرفر.
رفع صور محكوم — الصورة تُفحص كصورة حقيقية بمحتواها لا بامتدادها، بحد أقصى للحجم، وتُعاد ترميز PNG إلى JPEG — ومجلد الرفع نفسه معطّل فيه تنفيذ PHP.
كلمات المرور مُعمّاة — تُخزّن بـ password_hash() وتُتحقق بـ password_verify()، وتقدر تغيّرها من الإعدادات.
مفتاح الـ API ما يوصل للمتصفح — صفحات الأدمن ما تحمل المفتاح بأي JavaScript؛ التحقق من داخل اللوحة يمر عبر وسيط محمي بالجلسة، والمفتاح يبقى حصرًا بين الجهاز والسيرفر.
لا فريمورك ولا خطوة بناء — PHP 8 وMySQL وJavaScript مباشرة، على خادم Apache عادي يشتغل بموارد بسيطة ويكفي نادي كامل.