Skip to content

fix: prevent booking after event start date#135

Closed
UmakanthKaspa wants to merge 1 commit intoBuildWithHussain:mainfrom
UmakanthKaspa:fix/prevent-booking-after-event-start
Closed

fix: prevent booking after event start date#135
UmakanthKaspa wants to merge 1 commit intoBuildWithHussain:mainfrom
UmakanthKaspa:fix/prevent-booking-after-event-start

Conversation

@UmakanthKaspa
Copy link
Contributor

@UmakanthKaspa UmakanthKaspa commented Jan 21, 2026

Stops users from booking tickets after event has started.

Two options for organizers

  1. Global - Stop booking X days before event (set in Buzz Settings)
  2. Per event - Pick a specific date to stop booking (set in each event)

If both are set, the per-event date is used.

Works for max cases: close booking on start date, X days before start, or for multi-day events - any
day between start and end.

Summary by CodeRabbit

Release Notes

  • New Features
    • Event organizers can now set a "Booking Closes On" date to control when ticket bookings close for individual events.
    • Added global setting to configure default booking availability (days before event start).
    • Booking page displays "Bookings Closed" message and blocks form submissions after the deadline.
    • Server-side validation prevents ticket bookings when bookings are no longer open.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

The PR introduces a booking closure system enabling per-event booking_closes_on dates with a global fallback setting allow_booking_before_event_start_days. An is_booking_open property in BuzzEvent determines booking availability. Validation in EventBooking prevents bookings when closed, the API exposes booking status, and the frontend displays "Bookings Closed" when bookings are unavailable.

Changes

Cohort / File(s) Change Summary
BuzzEvent Event Configuration
buzz/events/doctype/buzz_event/buzz_event.json, buzz/events/doctype/buzz_event/buzz_event.py
Added booking_closes_on date field and two new boolean fields (allow_editing_talks_after_acceptance, show_sponsorship_section). Introduced validate_booking_closes_on() validation to ensure booking close date does not exceed event end date. Added is_booking_open property that checks per-event booking_closes_on or falls back to global Buzz Settings for availability determination.
BuzzSettings Global Booking Configuration
buzz/events/doctype/buzz_settings/buzz_settings.json, buzz/events/doctype/buzz_settings/buzz_settings.py
Added allow_booking_before_event_start_days (Int) field as global fallback configuration for booking closure. Updated type hint for default_sponsor_deck_reply_to to Optional.
EventBooking Validation
buzz/ticketing/doctype/event_booking/event_booking.py
Added validate_booking_open() method called at start of validation flow to check if bookings are allowed before processing further, raising error if bookings are closed.
API Data Exposure
buzz/api.py
Exposed data.booking_allowed property populated from event_doc.is_booking_open in get_event_booking_data().
Frontend Booking State Display
dashboard/src/pages/BookTickets.vue
Added bookingAllowed reactive property (default true) populated from API response. Conditionally displays "Bookings Closed" message with LucideCalendarX2 icon when bookingAllowed is false, wrapping booking form in v-else.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client (Vue)
    participant API as API
    participant Event as BuzzEvent
    participant Settings as BuzzSettings
    participant Booking as EventBooking
    
    Client->>API: GET event booking data
    API->>Event: is_booking_open
    Event->>Event: Check booking_closes_on?
    alt Per-event date set
        Event->>Event: Compare current date ≤ booking_closes_on
    else Fall back to global
        Event->>Settings: allow_booking_before_event_start_days
        Settings-->>Event: days value
        Event->>Event: Calculate cutoff date & compare
    end
    Event-->>API: is_booking_open result
    API-->>Client: booking_allowed in response
    Client->>Client: bookingAllowed = data.booking_allowed
    alt bookingAllowed is true
        Client->>Client: Render booking form
        Client->>Booking: POST EventBooking (submit)
        Booking->>Booking: validate_booking_open()
        Booking->>Event: is_booking_open
        Event-->>Booking: booking status
        alt Bookings still open
            Booking-->>Client: Validation success
        else Bookings closed
            Booking-->>Client: Error - bookings closed
        end
    else bookingAllowed is false
        Client->>Client: Render "Bookings Closed" message
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops with delight

Bookings close with grace so fine,
Per-event dates or global line,
Validation checks before we test,
Frontend shows when bookings rest. 🗓️✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the primary change: implementing logic to prevent booking after event start date with configurable booking closure options.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@buzz/api.py`:
- Around line 120-124: In get_event_booking_data, you're assigning the method
object event_doc.is_booking_open instead of its boolean result; update the code
in get_event_booking_data to call the method (event_doc.is_booking_open()) and
assign that boolean to data.booking_allowed so serialization and booking checks
work correctly; locate the assignment to data.booking_allowed in the
get_event_booking_data function and replace the method reference with the method
call on the event_doc instance.

In `@buzz/events/doctype/buzz_event/buzz_event.py`:
- Around line 201-204: Clamp the booking cutoff to non-negative so a negative
settings.allow_booking_before_event_start_days cannot extend booking past the
event; when you read settings = frappe.get_cached_doc("Buzz Settings") compute
cutoff_days = max(0, settings.allow_booking_before_event_start_days or 0) (or
validate earlier in the Buzz Settings model) before calling
add_days(self.start_date, -cutoff_days), keeping the rest of the logic with
cutoff_date, getdate and current_date unchanged.

In `@buzz/ticketing/doctype/event_booking/event_booking.py`:
- Around line 42-44: The booking-closure check is calling the method object
instead of invoking it, so change places where event.is_booking_open is used
(notably in validate_booking_open called from validate and the block around
lines 293-297) to call the method as event.is_booking_open() and use its boolean
result to enforce closure (raise the existing validation error/throw when
False). Locate and update any conditional(s) that currently reference
event.is_booking_open to call the method and keep the existing error
message/exception behavior.

In `@dashboard/src/pages/BookTickets.vue`:
- Around line 73-76: The assignment eventBookingData.bookingAllowed =
data.booking_allowed can flip the UI to “Bookings Closed” when the API omits or
returns null; change it to use a nullish fallback so the existing default is
preserved (e.g., use the nullish coalescing pattern when setting bookingAllowed
or explicitly check for undefined/null before assignment in the BookTickets.vue
code that assigns eventBookingData.bookingAllowed).
🧹 Nitpick comments (1)
buzz/events/doctype/buzz_settings/buzz_settings.py (1)

18-25: Add server-side bounds validation for booking cutoff days.

The new setting is only constrained at the DocType level; adding a server-side guard keeps behavior consistent with other “*_before_event_start_days” settings.

♻️ Suggested validation hook
 def validate(self):
 	"""Validate the settings."""
 	self.validate_transfer_days()
+	self.validate_booking_days()
+
+def validate_booking_days(self):
+	"""Validate that booking cutoff days is a reasonable value."""
+	if self.allow_booking_before_event_start_days is None:
+		return
+	if self.allow_booking_before_event_start_days < 0:
+		frappe.throw(_("Allow Booking Before Event Start Days cannot be negative."))
+	elif self.allow_booking_before_event_start_days > 365:
+		frappe.throw(_("Allow Booking Before Event Start Days cannot be more than 365 days."))

Comment on lines 120 to 124
def get_event_booking_data(event_route: str) -> dict:
data = frappe._dict()
event_doc = frappe.get_cached_doc("Buzz Event", {"route": event_route})

data.booking_allowed = event_doc.is_booking_open
# Ticket Types
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Call is_booking_open() instead of passing the method object.

event_doc.is_booking_open is a method on Buzz Event; assigning it directly will either serialize incorrectly or always truthy. This prevents proper booking closure and can break JSON serialization.

🐛 Fix
-	data.booking_allowed = event_doc.is_booking_open
+	data.booking_allowed = event_doc.is_booking_open()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def get_event_booking_data(event_route: str) -> dict:
data = frappe._dict()
event_doc = frappe.get_cached_doc("Buzz Event", {"route": event_route})
data.booking_allowed = event_doc.is_booking_open
# Ticket Types
def get_event_booking_data(event_route: str) -> dict:
data = frappe._dict()
event_doc = frappe.get_cached_doc("Buzz Event", {"route": event_route})
data.booking_allowed = event_doc.is_booking_open()
# Ticket Types
🤖 Prompt for AI Agents
In `@buzz/api.py` around lines 120 - 124, In get_event_booking_data, you're
assigning the method object event_doc.is_booking_open instead of its boolean
result; update the code in get_event_booking_data to call the method
(event_doc.is_booking_open()) and assign that boolean to data.booking_allowed so
serialization and booking checks work correctly; locate the assignment to
data.booking_allowed in the get_event_booking_data function and replace the
method reference with the method call on the event_doc instance.

Comment on lines +201 to +204
settings = frappe.get_cached_doc("Buzz Settings")
cutoff_days = settings.allow_booking_before_event_start_days or 0
cutoff_date = add_days(self.start_date, -cutoff_days)
return current_date <= getdate(cutoff_date)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against negative allow_booking_before_event_start_days.

A negative value would extend booking after the event start, breaking the intended rule. Consider clamping to >= 0 here (or validating in Buzz Settings).

✅ Suggested defensive clamp
-		cutoff_days = settings.allow_booking_before_event_start_days or 0
+		cutoff_days = max(int(settings.allow_booking_before_event_start_days or 0), 0)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
settings = frappe.get_cached_doc("Buzz Settings")
cutoff_days = settings.allow_booking_before_event_start_days or 0
cutoff_date = add_days(self.start_date, -cutoff_days)
return current_date <= getdate(cutoff_date)
settings = frappe.get_cached_doc("Buzz Settings")
cutoff_days = max(int(settings.allow_booking_before_event_start_days or 0), 0)
cutoff_date = add_days(self.start_date, -cutoff_days)
return current_date <= getdate(cutoff_date)
🤖 Prompt for AI Agents
In `@buzz/events/doctype/buzz_event/buzz_event.py` around lines 201 - 204, Clamp
the booking cutoff to non-negative so a negative
settings.allow_booking_before_event_start_days cannot extend booking past the
event; when you read settings = frappe.get_cached_doc("Buzz Settings") compute
cutoff_days = max(0, settings.allow_booking_before_event_start_days or 0) (or
validate earlier in the Buzz Settings model) before calling
add_days(self.start_date, -cutoff_days), keeping the rest of the logic with
cutoff_date, getdate and current_date unchanged.

Comment on lines 42 to 44
def validate(self):
self.validate_booking_open()
self.validate_ticket_availability()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

is_booking_open must be called to enforce booking closure.

event.is_booking_open is a method, so the current check always evaluates truthy and never blocks bookings.

🐛 Fix
-		if not event.is_booking_open:
+		if not event.is_booking_open():
 			frappe.throw(frappe._("Bookings are closed for {0}").format(event.title))

Also applies to: 293-297

🤖 Prompt for AI Agents
In `@buzz/ticketing/doctype/event_booking/event_booking.py` around lines 42 - 44,
The booking-closure check is calling the method object instead of invoking it,
so change places where event.is_booking_open is used (notably in
validate_booking_open called from validate and the block around lines 293-297)
to call the method as event.is_booking_open() and use its boolean result to
enforce closure (raise the existing validation error/throw when False). Locate
and update any conditional(s) that currently reference event.is_booking_open to
call the method and keep the existing error message/exception behavior.

Comment on lines 73 to 76
eventBookingData.customFields = data.custom_fields || [];
eventBookingData.paymentGateways = data.payment_gateways || [];
eventBookingData.bookingAllowed = data.booking_allowed;
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard against missing booking_allowed to avoid false “closed” state.

If the API omits the field or returns null, the UI flips to “Bookings Closed.” A nullish fallback keeps the default behavior intact.

🐛 Suggested fix
-		eventBookingData.bookingAllowed = data.booking_allowed;
+		eventBookingData.bookingAllowed = data.booking_allowed ?? true;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
eventBookingData.customFields = data.custom_fields || [];
eventBookingData.paymentGateways = data.payment_gateways || [];
eventBookingData.bookingAllowed = data.booking_allowed;
},
eventBookingData.customFields = data.custom_fields || [];
eventBookingData.paymentGateways = data.payment_gateways || [];
eventBookingData.bookingAllowed = data.booking_allowed ?? true;
},
🤖 Prompt for AI Agents
In `@dashboard/src/pages/BookTickets.vue` around lines 73 - 76, The assignment
eventBookingData.bookingAllowed = data.booking_allowed can flip the UI to
“Bookings Closed” when the API omits or returns null; change it to use a nullish
fallback so the existing default is preserved (e.g., use the nullish coalescing
pattern when setting bookingAllowed or explicitly check for undefined/null
before assignment in the BookTickets.vue code that assigns
eventBookingData.bookingAllowed).

@UmakanthKaspa
Copy link
Contributor Author

Closing - duplicate of #110 (started working after seeing #109 closed).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant