Skip to content

feat: back Buzz Events with Zoom Meetings - #288

Merged
harshtandiya merged 9 commits into
developfrom
feat/zoom-meetings
Jul 27, 2026
Merged

feat: back Buzz Events with Zoom Meetings#288
harshtandiya merged 9 commits into
developfrom
feat/zoom-meetings

Conversation

@harshtandiya

@harshtandiyaharshtandiya commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

What

Lets a Buzz Event be backed by a Zoom Meeting as well as a Webinar — create it from the event, keep it in sync, register ticket holders so they get a join URL — and picks which of the two an event uses from its category.

Depends onbwhtech/zoom_integration#17. Ship together; that app migrates first. Tests here need that branch on the same bench.

Changes

  • install.py — custom field zoom_meeting (Link → Zoom Meeting) on Buzz Event; the ticket's registration field is now zoom_session_registration; seeds a "Zoom Meeting" event category.
  • buzz_event.pycreate_meeting_on_zoom() + update_zoom_meeting(), mirroring the webinar methods; on_update syncs both.
  • event_ticket.py — builds the registration's reference_doctype / reference_name pair from whichever session the event has.
  • api/__init__.py — ticket details returns zoom_reference_doctype / zoom_reference_name in place of zoom_webinar / zoom_meeting.
  • buzz_event.js — the "Create on Zoom" group collapses to a single button chosen by category.

Category drives the Zoom action

An event uses exactly one session type, so the button group holding both a webinar and a meeting button made no sense. It is now one button, labelled for the category:

CategoryZoom session linked?Button
WebinarsnoCreate Webinar on Zoom
WebinarsyesView Webinar
Zoom MeetingnoCreate Meeting on Zoom
Zoom MeetingyesView Meeting

The category name "Webinars" was hardcoded in eight places and a second session type would have doubled that, so the mapping lives in one constant per layer: ZOOM_BACKED_CATEGORIES (buzz/utils.py), ZOOM_SESSION_BY_CATEGORY (buzz_event.js), isZoomBackedCategory (dashboard). The two depends_on expressions stay inline because eval strings cannot import.

Behaviour that was webinar-only now applies to both, since Zoom wants the same things either way: a last name on every registrant, attach_email_ticket off by default, and the free-event checkbox. isWebinar in the booking form becomes isZoomEvent, which is what it always meant.

create_event_categories() is now called on migrate so the new category reaches existing sites. The insert was already ignore_if_duplicate, so re-running only fills in what is missing.

Migrations

PatchStageDoes
rename_zoom_registration_fieldpost_model_syncRenames the Event Ticket custom field zoom_webinar_registrationzoom_session_registration, following the doctype rename in zoom_integration#17. Calls create_zoom_integration_custom_fields() first, because rename_field copies into an existing field and the after_migrate hook that creates them runs after patches. No-op without zoom_integration.
rename_free_webinar_to_free_eventpost_model_syncRenames free_webinarfree_event on Buzz Event and Event Proposal.

Old columns are left for bench trim-tables.

free_webinar → free_event

The flag hides pricing, payment sections and the ticket type picker. None of that is webinar-specific, and it now applies to Zoom Meeting events too, so the name was wrong on two counts.

Both doctypes rename in the same patch on purpose: Event Proposal maps onto Buzz Event through get_mapped_doc, which matches on fieldname with no field_map, so renaming one side alone would silently stop carrying the flag over with nothing raised. A test covers that carry-over.

SuccessMessage took an isWebinar prop fed by this flag. It picks registration wording over booking wording, so it is now isRegistration — named for what it controls rather than what feeds it.

Verified against real rows: 3 events had the flag set before the patch, 3 after, values intact.

Why the ticket needed no new field

The ticket's single registration link points at the now-generic session registration doctype, so it holds meeting and webinar registrations alike — one field, not two.

Not in this PR

Buzz Event still carries two links, zoom_webinar and zoom_meeting, rather than the dynamic reference the registration doctype uses. Folding those into one pair wants a UX pass on the Meeting-vs-Webinar choice first; deferred deliberately.

Tests

All mocked — no real Zoom calls. 173 passing (backend) · 61 (scheduler) · 25 (dashboard unit, yarn test:unit). Typecheck, build and ruff clean.

Covers both session types end to end: a ticket on a meeting-backed event and on a webinar-backed event each produce a registration with the right reference pair; last name is required on both Zoom categories and not on others; the free flag survives proposal → event.

Desk behaviour is not unit-testable, so the buttons were checked in a real browser against each category.

Breaking changes

Renamed fields

DocTypeBeforeAfter
Event Ticket (custom field)zoom_webinar_registrationzoom_session_registration
Buzz Eventfree_webinarfree_event
Event Proposalfree_webinarfree_event

Buzz Event.zoom_webinar and zoom_meeting are unchanged.

Changed API payload keys

MethodBeforeAfter
get_ticket_detailszoom_webinar, zoom_meetingzoom_reference_doctype, zoom_reference_name
get_event_booking_datafree_webinarfree_event
get_booking_confirmationfree_webinarfree_event

zoom_join_url is unchanged — if that is all you read, nothing to do.

What the patches fix for you

rename_zoom_registration_field and rename_free_webinar_to_free_event copy the values into the new fields and update Reports, report-view settings, Property Setters and user settings. Old columns stay until you run bench trim-tables.

What you must fix by hand

Grep your custom app, Server Scripts, Client Scripts, Notification conditions, Print Formats and Jinja templates:

grep -rn "free_webinar\|zoom_webinar_registration".

Then apply:

If your code doesChange it to
event.free_webinarevent.free_event
filters={"free_webinar": 1}filters={"free_event": 1}
ticket.zoom_webinar_registrationticket.zoom_session_registration
reads zoom_webinar / zoom_meeting off get_ticket_detailszoom_reference_doctype + zoom_reference_name

Requires zoom_integration#17 — the session doctype and field renames there apply to this app's data too.

Category behaviour

Not a rename, but it changes what runs: the Zoom buttons and the last-name requirement now key off the category being WebinarsorZoom Meeting. Custom code branching on category == "Webinars" should use ZOOM_BACKED_CATEGORIES from buzz/utils.py.

Events sitting in the Webinars category with a zoom_meeting attached now show the webinar button and ignore the linked meeting — move them to the Zoom Meeting category. There were 2 such events on the dev site.

🤖 Generated with Claude Code

…tration)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

harshtandiya has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

harshtandiya has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

harshtandiyaand others added 2 commits July 26, 2026 20:28
zoom_integration renamed Zoom Webinar Registration to Zoom Session Registration.
Point the Event Ticket custom field, its creation in install.py, the registration
created on ticket submit and get_ticket_details at the new name, and rename the
field itself to zoom_session_registration.
rename_field copies values into a field that must already exist, and the
after_migrate hook that creates our custom fields runs after patches, so the
patch calls create_zoom_integration_custom_fields() first, then copies, then
drops the old Custom Field. The old column is left for `bench trim-tables`.
Requires zoom_integration to be migrated first: until it is, the custom field
points at a doctype that does not exist yet.
The dashboard is untouched - get_ticket_details still returns zoom_join_url,
zoom_webinar and zoom_meeting under the same keys.
BREAKING CHANGE: Event Ticket.zoom_webinar_registration is now
zoom_session_registration. Any REST read, custom report or client script naming
the old fieldname breaks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Move the single "Create Webinar on Zoom" button into a "Create on Zoom" group
and add the meeting equivalents, so an event can be backed by either a Zoom
Webinar or a Zoom Meeting from the form.
Viewing a meeting resolves zoom_link off the Zoom Meeting record rather than
building a URL, since Zoom Meeting is named by hash and the docname is not the
Zoom id.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

harshtandiya has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

Zoom Session Registration now carries reference_doctype + reference_name
instead of separate webinar and meeting links. Event Ticket builds that pair
from whichever the event has, and get_ticket_details returns
zoom_reference_doctype / zoom_reference_name in place of zoom_webinar /
zoom_meeting.
The Buzz Event fields stay two separate links for now; folding those in wants
a UX pass on the create/view buttons first.
"View Meeting" drops the round-trip that fetched zoom_link. It existed because
Zoom Meeting used hash naming; the docname is the Zoom meeting ID now, so the
URL is built the same way as the webinar one.
BREAKING CHANGE: get_ticket_details no longer returns zoom_webinar or
zoom_meeting. Requires zoom_integration with the dynamic session reference.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

harshtandiyaand others added 2 commits July 27, 2026 17:28
Buzz Events could only be backed by a Zoom Webinar: the desk showed a
"Create on Zoom" group holding both a webinar and a meeting button, and
everything keyed off the literal category name "Webinars".
A new "Zoom Meeting" category picks the meeting path instead. Only one
session type applies to an event now, so the button group collapses to a
single button labelled for that type -- "Create Webinar on Zoom" or
"Create Meeting on Zoom", and the matching View button once created.
The category name was hardcoded in eight places, and a second session type
would have doubled that, so the mapping now lives in one constant per layer:
ZOOM_BACKED_CATEGORIES in buzz/utils.py, ZOOM_SESSION_BY_CATEGORY in
buzz_event.js, and isZoomBackedCategory in the dashboard. The two depends_on
expressions stay inline because eval strings cannot import.
Behaviour that was webinar-only now applies to both, since Zoom needs the
same things either way: a last name on every registrant, attach_email_ticket
off by default, and the free-event checkbox.
isWebinar becomes isZoomEvent in the booking form, which is what it actually
meant. create_event_categories is called on migrate so the new category
reaches existing sites; the insert is ignore_if_duplicate, so re-running it
only fills in what is missing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The flag hides pricing, payment sections and the ticket type picker. None of
that is webinar-specific, and it now applies to Zoom Meeting events too, so
the name was wrong on two counts.
Both doctypes rename in one patch. Event Proposal maps onto Buzz Event
through get_mapped_doc, which matches on fieldname with no field_map, so
renaming one side alone would have stopped carrying the flag over without
raising anything. A test covers that carry-over.
SuccessMessage took an isWebinar prop fed by this flag; it selects
registration wording over booking wording, so it becomes isRegistration.
BREAKING CHANGE: the booking payloads return free_event instead of
free_webinar. API clients reading the old key must be updated.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@harshtandiyaharshtandiya added the backport main backport to main branch label Jul 27, 2026
Zoom Webinar fetches its own token rather than going through api.py, so
patching `requests` alone left the token call live. It passed locally, where
credentials exist, and failed in CI where they do not.
Uses mock_zoom_post, which patches both, matching the fix already applied to
the zoom_integration tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@greptile-appsgreptile-appsBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@harshtandiya
harshtandiya merged commit f3ced3f into developJul 27, 2026
7 checks passed
@harshtandiya
harshtandiya deleted the feat/zoom-meetings branch July 27, 2026 13:20
@github-actions

Copy link
Copy Markdown
Contributor

Successfully created backport PR for main:

harshtandiya added a commit that referenced this pull request Jul 27, 2026
feat: back Buzz Events with Zoom Meetings (#288)
* feat: back Buzz Events with Zoom Meetings (create, sync, ticket registration)
* ci: install zoom_integration app for server tests
* refactor!: follow Zoom Session Registration rename
zoom_integration renamed Zoom Webinar Registration to Zoom Session Registration.
Point the Event Ticket custom field, its creation in install.py, the registration
created on ticket submit and get_ticket_details at the new name, and rename the
field itself to zoom_session_registration.
rename_field copies values into a field that must already exist, and the
after_migrate hook that creates our custom fields runs after patches, so the
patch calls create_zoom_integration_custom_fields() first, then copies, then
drops the old Custom Field. The old column is left for `bench trim-tables`.
Requires zoom_integration to be migrated first: until it is, the custom field
points at a doctype that does not exist yet.
The dashboard is untouched - get_ticket_details still returns zoom_join_url,
zoom_webinar and zoom_meeting under the same keys.
BREAKING CHANGE: Event Ticket.zoom_webinar_registration is now
zoom_session_registration. Any REST read, custom report or client script naming
the old fieldname breaks.
* feat(events): group Zoom create/view actions on Buzz Event
Move the single "Create Webinar on Zoom" button into a "Create on Zoom" group
and add the meeting equivalents, so an event can be backed by either a Zoom
Webinar or a Zoom Meeting from the form.
Viewing a meeting resolves zoom_link off the Zoom Meeting record rather than
building a URL, since Zoom Meeting is named by hash and the docname is not the
Zoom id.
* refactor!: follow the Zoom session dynamic reference
Zoom Session Registration now carries reference_doctype + reference_name
instead of separate webinar and meeting links. Event Ticket builds that pair
from whichever the event has, and get_ticket_details returns
zoom_reference_doctype / zoom_reference_name in place of zoom_webinar /
zoom_meeting.
The Buzz Event fields stay two separate links for now; folding those in wants
a UX pass on the create/view buttons first.
"View Meeting" drops the round-trip that fetched zoom_link. It existed because
Zoom Meeting used hash naming; the docname is the Zoom meeting ID now, so the
URL is built the same way as the webinar one.
BREAKING CHANGE: get_ticket_details no longer returns zoom_webinar or
zoom_meeting. Requires zoom_integration with the dynamic session reference.
* feat(events): pick the Zoom action from the event category
Buzz Events could only be backed by a Zoom Webinar: the desk showed a
"Create on Zoom" group holding both a webinar and a meeting button, and
everything keyed off the literal category name "Webinars".
A new "Zoom Meeting" category picks the meeting path instead. Only one
session type applies to an event now, so the button group collapses to a
single button labelled for that type -- "Create Webinar on Zoom" or
"Create Meeting on Zoom", and the matching View button once created.
The category name was hardcoded in eight places, and a second session type
would have doubled that, so the mapping now lives in one constant per layer:
ZOOM_BACKED_CATEGORIES in buzz/utils.py, ZOOM_SESSION_BY_CATEGORY in
buzz_event.js, and isZoomBackedCategory in the dashboard. The two depends_on
expressions stay inline because eval strings cannot import.
Behaviour that was webinar-only now applies to both, since Zoom needs the
same things either way: a last name on every registrant, attach_email_ticket
off by default, and the free-event checkbox.
isWebinar becomes isZoomEvent in the booking form, which is what it actually
meant. create_event_categories is called on migrate so the new category
reaches existing sites; the insert is ignore_if_duplicate, so re-running it
only fills in what is missing.
* refactor!: rename free_webinar to free_event
The flag hides pricing, payment sections and the ticket type picker. None of
that is webinar-specific, and it now applies to Zoom Meeting events too, so
the name was wrong on two counts.
Both doctypes rename in one patch. Event Proposal maps onto Buzz Event
through get_mapped_doc, which matches on fieldname with no field_map, so
renaming one side alone would have stopped carrying the flag over without
raising anything. A test covers that carry-over.
SuccessMessage took an isWebinar prop fed by this flag; it selects
registration wording over booking wording, so it becomes isRegistration.
BREAKING CHANGE: the booking payloads return free_event instead of
free_webinar. API clients reading the old key must be updated.
* test: stop the ticket webinar test from needing a live Zoom token
Zoom Webinar fetches its own token rather than going through api.py, so
patching `requests` alone left the token call live. It passed locally, where
credentials exist, and failed in CI where they do not.
Uses mock_zoom_post, which patches both, matching the fix already applied to
the zoom_integration tests.
---------
(cherry picked from commit f3ced3f)
Co-authored-by: Harsh Tandiya <harsh.tandiya@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport mainbackport to main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@harshtandiya