استوديو الذكاء الاصطناعي

كيف يمنع النظام تعارض الحجوزات؟ وأين يتم ذلك في الشيفرة؟

عن المشروع: حجز القاعات
  1. أنت

    كيف يمنع النظام تعارض الحجوزات؟ وأين يتم ذلك في الشيفرة؟

  2. النموذج

    يمنع النظام تعارض الحجوزات من خلال تطبيق قاعدة واضحة: لا يمكن حجز القاعة نفسها في فترة زمنية تتداخل مع حجز آخر مؤكد أو قيد الاعتماد. يتم ذلك عبر دالة تحقق اسمها validate_no_overlap التي تُستدعى في نقاط حرجة من دورة حياة الحجز.

    1. منطق المنع (كيف يعمل؟)

    يعتمد المنع على مقارنة الفترات الزمنية باستخدام قاعدة رياضية بسيطة: تتداخل فترتان [start1, end1) و [start2, end2) إذا كان: start1 < end2 و start2 < end1

    إذا وُجد حجز موجود (بالحالة CONFIRMED أو PENDING_APPROVAL) يطابق هذه الشروط لنفس القاعة، يرفض النظام العملية ويرمي استثناء ValidationError برسالة:

    • بالعربية: "توجد حجزات متعارضة في نفس الفترة الزمنية لهذه القاعة"
    • بالإنجليزية: "There is an overlapping booking for this room in the same time slot"

    2. أين يتم ذلك في الشيفرة؟

    يتم تنفيذ المنع في ثلاثة أماكن رئيسية:

    أ. دالة التحقق الأساسية

    توجد في ملف [backend/models/validation.py]، وهي الدالة التي تستعلم عن قاعدة البيانات للتحقق من التعارض:

    def validate_no_overlap(
        db: Session,
        room_id: str,
        start_time: datetime.datetime,
        end_time: datetime.datetime,
        exclude_booking_id: Optional[str] = None
    ) -> None:
        """
        Validate that no existing confirmed or pending bookings overlap with the proposed time slot
        for the same room (FR-01).
        """
        query = db.query(Booking).filter(
            Booking.room_id == room_id,
            Booking.status.in_([BookingStatus.CONFIRMED, BookingStatus.PENDING_APPROVAL]),
            Booking.start_time < end_time,
            Booking.end_time > start_time
        )
    
        if exclude_booking_id:
            query = query.filter(Booking.id != exclude_booking_id)
    
        overlapping_booking = query.first()
    
        if overlapping_booking:
            raise ValidationError(
                message_ar="توجد حجزات متعارضة في نفس الفترة الزمنية لهذه القاعة",
                message_en="There is an overlapping booking for this room in the same time slot"
            )
    

    ب. عند إنشاء حجز جديد

    في ملف [backend/services/bookings/service.py]، داخل دالة create_booking، يتم استدعاء validate_no_overlap قبل حفظ الحجز في قاعدة البيانات. إذا فشل التحقق، لن يُنشأ الحجز.

    ج. عند تعديل حجز قائم

    في نفس الملف [backend/services/bookings/service.py]، داخل دالة modify_booking، يتم استدعاء validate_no_overlap مع تمرير exclude_booking_id (معرف الحجز الحالي) لضمان عدم اعتبار الحجز نفسه متعارضاً مع نفسه عند تغيير موعده.

    د. عند البحث عن القاعات المتاحة

    في ملف [backend/services/availability/service.py]، تستخدم دالة search_available_rooms منطقاً مشابهاً (عبر filter_rooms_by_availability و validate_no_overlap) لاستبعاد القاعات التي لديها تعارض من نتائج البحث، مما يضمن أن المستخدم لا يرى قاعات غير متاحة أصلاً.

    ملاحظة تقنية

    تُستبعد الحجوزات الملغاة (CANCELLED) تلقائياً من فحص التعارض لأنها لا تحتجز الموارد فعلياً، مما يتيح إعادة استخدام نفس الفترة الزمنية بعد الإلغاء (متوافق مع [FR-08]).

  3. أنت

    وما الاختبارات التي تغطي ذلك؟

  4. النموذج

    تغطي الاختبارات منع تعارض الحجوزات على مستويين: مستوى دالة التحقق المباشرة (validate_no_overlap)، ومستوى خدمة الحجوزات (BookingService)، ومستوى خدمة التوفر (AvailabilityService).

    1. اختبارات دالة التحقق المباشرة

    توجد في [backend/tests/test_validation.py] وتختبر منطق validate_no_overlap بشكل معزول:

    • test_validate_no_overlap_no_conflict:

      • الهدف: التحقق من نجاح التحقق عندما لا توجد حجوزات متداخلة.
      • السيناريو: إنشاء قاعة، ثم استدعاء validate_no_overlap لفترة زمنية لا يوجد فيها أي حجز.
      • النتيجة المتوقعة: is_valid is True و error is None.
    • test_validate_no_overlap_with_conflict:

      • الهدف: التحقق من رفض التحقق عند وجود حجز متداخل.
      • السيناريو:
        1. إنشاء حجز مؤكد (CONFIRMED) من الساعة 1 إلى الساعة 3.
        2. محاولة التحقق من حجز جديد من الساعة 2 إلى الساعة 4 (تداخل واضح).
      • النتيجة المتوقعة: is_valid is False و error تحتوي على كلمة "تعارض" أو "overlap".

    2. اختبارات خدمة الحجوزات (BookingService)

    توجد في [backend/tests/test_bookings_service.py] وتختبر سلوك الخدمة الكاملة عند إنشاء حجز:

    • test_create_booking_conflict:

      • الهدف: التحقق من أن خدمة create_booking ترفض إنشاء حجز متعارض.
      • السيناريو:
        1. وجود حجز مؤكد (EMP002) من الساعة 1 إلى الساعة 3.
        2. محاولة EMP003 إنشاء حجز لنفس القاعة من الساعة 2 إلى الساعة 4.
      • النتيجة المتوقعة: رمي استثناء ValidationError مع رسالة تحتوي على "تعارض" أو "overlap".
    • test_modify_booking_success (غير مباشر):

      • رغم أن الاسم يشير إلى النجاح، إلا أن الكود يتحقق من أن التعديل إلى وقت غير متعارض ينجح. لو كان الوقت متعارضا، لرمى ValidationError (كما هو مضمن في منطق modify_booking).
    • test_cancel_booking_resource_release:

      • الهدف: التحقق من أن إلغاء الحجز يحرر الفترة الزمنية.
      • السيناريو:
        1. إنشاء حجز.
        2. إلغاءه.
        3. محاولة إنشاء حجز جديد لنفس الفترة الزمنية بالضبط.
      • النتيجة المتوقعة: نجاح الحجز الجديد (status == CONFIRMED)، مما يؤكد أن الحجز الملغي لم يعد سبباً في التعارض.

    3. اختبارات خدمة التوفر (AvailabilityService)

    توجد في [backend/tests/test_availability_service.py] وتختبر كيف يتعامل البحث عن القاعات مع التعارضات:

    • test_search_available_rooms_excludes_booked_rooms:

      • الهدف: التحقق من استبعاد القاعات المحجوزة من نتائج البحث.
      • السيناريو:
        1. وجود حجز مؤكد من الساعة 1 إلى الساعة 2.
        2. البحث عن قاعات متاحة من الساعة 1 إلى الساعة 2.
      • النتيجة المتوقعة: قائمة فارغة (len(results) == 0).
    • test_search_available_rooms_includes_non_overlapping_bookings:

      • الهدف: التحقق من تضمين القاعات التي لديها حجوزات غير متداخلة.
      • السيناريو:
        1. وجود حجز من الساعة 1 إلى الساعة 2.
        2. البحث عن قاعات متاحة من الساعة 3 إلى الساعة 4.
      • النتيجة المتوقعة: القاعة تظهر في النتائج (len(results) == 1).
    • test_check_room_availability_with_conflict:

      • الهدف: التحقق من أن فحص توفر قاعة محددة يعيد "غير متاحة" عند وجود تعارض.
      • السيناريو:
        1. وجود حجز من الساعة 1 إلى الساعة 3.
        2. فحص التوفر من الساعة 2 إلى الساعة 4.
      • النتيجة المتوقعة: is_available is False و error تحتوي على "تعارض".
    • test_check_room_availability_pending_booking_conflict:

      • الهدف: التحقق من أن الحجوزات "قيد الاعتماد" (PENDING_APPROVAL) تُعتبر تعارضاً أيضاً.
      • السيناريو: وجود حجز بحالة PENDING_APPROVAL وفحص فترة متداخلة.
      • النتيجة المتوقعة: is_available is False.
    • test_check_room_availability_cancelled_booking_no_conflict:

      • الهدف: التحقق من أن الحجوزات الملغاة لا تُعتبر تعارضاً.
      • السيناريو: وجود حجز بحالة CANCELLED وفحص فترة متداخلة.
      • النتيجة المتوقعة: is_available is True.

    التتبع مع متطلبات النظام

    هذه الاختبارات تغطي بشكل مباشر [FR-01] (منع تعارض الحجوزات) و [FR-08] (تحرير القاعة بعد الإلغاء)، وتتوافق مع سيناريو الاختبار الوظيفي [TC-02].