4.6.3 Gathering Schedules
Gathering schedules place activities in timed slots within an event. GatheringScheduledActivitiesTable stores the rows; GatheringScheduleService owns reusable add/edit/delete validation; GatheringsController exposes the corresponding actions.
Model expectations
A schedule row belongs to one gathering and references the selected gathering activity. It carries a start time, optional end time, has_end_time, display title, description, preregistration flag, and custom-activity flag. Venue/location context belongs to the parent gathering, not the scheduled-activity row. Times must fall within the rules enforced by the table/service and be interpreted using gathering timezone context.
Mutation path
- Load and authorize the parent gathering.
- Pass request data, gathering, and identity to
GatheringScheduleService. - Render service validation errors without losing field values or focus.
- Return the expected full-page or Turbo Frame response.
Do not save schedule rows directly from a plugin or Stimulus controller. The service keeps activity membership, timing, and auditing rules in one place.
GatheringCloneService::cloneSchedule() is the supported copy path when cloning an event.
Accessibility and verification
Use properly labeled date/time inputs and include the relevant timezone in visible help text. Announce add/edit/delete results when a frame updates. Test invalid ranges, cross-gathering activity IDs, authorization, clone behavior, timezone boundaries, keyboard operation, and tenant separation.