Allow registrations to be for multiple people -- e.g., adding guests or "plus one"

Created on 8 January 2022, almost 3 years ago
Updated 21 November 2023, about 1 year ago

Problem/Motivation

Allow a person registering for an event to register for more than one person -- in other words, allow the person registering to add guests or a "plus one."

For example, user registers for Event A and there is a field available during registration that asks "Will you be bringing any guests?" The user answers "2" and so after registration is complete, there are 3 spots taken toward the registration limit (the user plus their 2 guests).

Another consideration could be allowing admins to limit how many guests any given registration can contain.

Proposed resolution

Add a boolean field to the event-creation process that toggles on "Add Guests" feature for registration.

If "Add Guests" feature is turned on, add a "Maximum Number of Guests" number field to the event-creation process that allows admin to set maximum number of guests per registration.

If "Add Guests" feature is turned on, users will see an option to add guests when filling out the registration form and the options will be limted by the "Maximum Number of Guests" field set during event creation.

When a registration with guests occurs, the number of available registrations for an event should reduce by one plus the number of guests chosen.

When a registration is cancelled, the number of guests should be added back to the registration limit

Something that could be awkward... what if there are 2 spots remaining for an event that has the waitlist feature enabled and someone tries to register themself plus 2 guests. That would be 3 registrations total and so there would not be enough spots available. Should the single guest be put on the waitlist, or should the user just be told that 3 registrations will not fit and only 2 can be registered?

Feature request
Status

Needs review

Version

2.0

Component

Recurring Events Registration (Submodule)

Created by

🇨🇦Canada endless_wander

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇦Canada endless_wander

    Re-rolling patch to be D10 compatible

  • 🇨🇦Canada endless_wander

    Adding missing accessCheck() to guests submodule

  • 🇧🇷Brazil carolpettirossi Campinas - SP

    Patch #22 stopped working for me. I'm now getting "Warning: Attempt to read property "recurring_events_guests_per_registrant" on null in Drupal\recurring_events_guests\Service\GuestService->getGuestsPerRegistrant() (line 111 of modules/contrib/recurring_events/modules/recurring_events_registration/modules/recurring_events_guests/src/Service/GuestService.php)."

  • 🇧🇷Brazil carolpettirossi Campinas - SP

    It looks like the error started because the service got update to shared:false here: https://www.drupal.org/project/recurring_events/issues/3452632 🐛 Registration creation service leaks data Fixed

  • 🇨🇦Canada endless_wander

    @carolpettirossi I will take a look soon as I will need to upgrade as well.

  • 🇨🇦Canada endless_wander

    Steps to reproduce bug from#23:
    - update to Recurring Events 2.0.2
    - create an event with Registration enabled and Number of Guests set to > 0
    - register for an event instance for the new event and add guests
    - on add registrant page is where error occurs -- e.g., /events/EVENTINSTANCEID/registrations/add

    Warning: Attempt to read property "recurring_events_guests_per_registrant" on null in Drupal\recurring_events_guests\Service\GuestService->getGuestsPerRegistrant() (line 111 of modules/contrib/recurring_events/modules/recurring_events_registration/modules/recurring_events_guests/src/Service/GuestService.php).

  • 🇨🇦Canada endless_wander

    Attaching a patch that merges all changes from this issue and solves the problem of the RegistrationCreationService no longer providing event data for the guests.

    Note that this updates the reported issue and also an issue that would be caused for the registrant contact form submit function as well. The RegistrationCreationService was used there as well to get event data.

  • 🇧🇬Bulgaria pfrenssen Sofia

    This looks very interesting and would be very useful. I had a look at the code. It looks very promising. Some things came to mind:

    1. There are 2 ways of handling multi-seat registrations: you can choose the "number of seats" (N reservations) or the "number of guests" (1 main reservation + N additional reservations). Depending on the event one or the other will be more appropriate. I personally think for a general solution setting the "number of seats" might be easier to handle. It can default to "1", and we don't require our users to do mental 1+N arithmetic. But I am also OK with "number of guests". By the way this has already been explored in #3090186: Registration quantity widget and there are screenshots showing how different popular platforms handle it.
    2. Making duplicate registrants is an easy way to introduce this with minimal changes to the current architecture. But this comes with some caveats:
      • The "main guest" will receive duplicated emails for each "additional guest". Every mail will contain unique edit and delete links that are specific to a single individual out of the group.
      • The registrant will not be able to easily manage their registration. If they want to cancel the registration for the entire group, they have to cancel each guest individually.
      • Similarly, managing a group registration will be difficult for event managers. In order to make a change they'll have to somehow locate all registrant entities that belong to the same group (probably by filtering on email address of the "main guest") and then perform the change on each one individually.
    3. So maybe a better way would be to have a single Registrant entity for a group registration? We can add a new base field to the Registrant entity that stores the number of seats, and use this in the calculation for the event capacity.
  • 🇧🇬Bulgaria pfrenssen Sofia

    I'll have a go at exploring if we can store the number of seats on the Registrant entity.

  • Merge request !110#3257502 Allow to register multiple seats → (Closed) created by pfrenssen
  • 🇨🇦Canada endless_wander

    Yeah, thank you for taking a look. We have been using this custom feature for a while now.

    For our purposes, we do not allow guests for every event so we could make sure number of seats is maximum 1 per registrant unless guests are allowed. I think originally we thought we would make guests an "inferior" type of registrant with settings to do things like allow only the "main" registrant to receive email notifications or have certain registration questions appear for the "main" registrant and not for the guests. In practice, our clients haven't done any of that yet.

    I still would like to reserve the ability to collect information for each guest rather than have all the information under one Registrant. Perhaps this is also related to the use of different Registrant types to collect different information.

    Maybe there would be some weirdness for the waiting list if single Registrants took up multiple Registrant slots?

  • 🇧🇬Bulgaria pfrenssen Sofia

    I made a proof of concept of storing the number of seats on the registrant. It can be found in the MR https://git.drupalcode.org/project/recurring_events/-/merge_requests/110

    How it works:

    Creating an event series

    There is a new option Maximum Seats Per Registration (max_seats) that allows event managers to control how many attendees can be included per registration. It defaults to 1, so by default the behavior will be unchanged.

    Registering for an event

    There is a new number field that allows the user to select how many seats they want to reserve. The number is limited by the current availability, the max_seats, and whether or not there is a waitlist.

    For example, if the max_seats are configured to 5:

    • If there are enough spaces left, the user can reserve max. 5 seats.
    • If there are not enough spaces left, the user can reserve max. the remaining spaces.
    • If there are no spaces left, the user can reserve max. 5 seats on the waitlist.

    I also accounted for some edge cases:

    • When there is only a single seat left, or max_seats is set to 1, the "Seats" number field is hidden, because it would not be possible to change the value and this could be confusing to users.
    • User A is told there are 5 spaces left, and wants to register them. In the meantime user B snatches up some of the remaining spaces. User A will then get the message "Unfortunately, this event is now full and you must join the waitlist.". This was a bit tricky to implement because we need to somehow keep track of how many spaces that user A has seen. We cannot use form state for this because the form state is not stored before the form is submitted. I used a private tempstore with a lifetime of 10 minutes to handle this.

    Managing registrants

    Because there is only 1 registrant entity, we can keep an easy UX for event managers:

    • Editing a multi-seat event is now easy - just edit the registrant as before. No need to edit 5 duplicates one by one.
    • Only 1 mail will ever be sent out for every action done on a registrant.
    • Adding and removing guests is now also just a matter of changing the number of seats.

    The overview shows for each registrant how many seats are reserved:

    Previously when creating or editing a registrant as an event manager you had the option to either put the registrant on the waitlist, or not. I added a new option to handle this automatically depending on current availability. Then the event manager doesn't need to check if there are still enough places available:

    Promoting from waitlist

    The first registrant on the waitlist will be promoted as soon as there are enough places available to match the number of requested seats.

    Update hooks

    The existing event series have the "max_seats" set to 1, and existing registrants have the number of seats set to 1. I reused the existing update hooks we had, but these are not fully migrating historic revisions of the event registration field data. Only the last revision is kept. I assume this was decided in the past to avoid problems if there are a large number of revisions?

  • 🇧🇬Bulgaria pfrenssen Sofia

    I still would like to reserve the ability to collect information for each guest separately rather than have all the information under one Registrant. Perhaps this is also related to the use of different Registrant types to collect different information. For example, parents could register as "main" Registrant and each guest would be a child and the registration would ask for their ages but not the parents' ages. Another example would be registrations where guests speak a different language than the "main" Registrant and forms could ask which language for each guest, which in turn is linked to communications sent out by our client.

    This is a very interesting thought, and one that I didn't consider before. We might indeed need a different entity type for that. It sounds a bit like the use case of the Profile module. This is probably something quite custom though, but I can absolutely see the need that projects will want to collect age information / name / profile picture per attendee. How could we do this in a generic way that would benefit most projects?

  • 🇨🇦Canada endless_wander

    - I think "Seats" is a strange term to use. Rest of the module uses "Spaces" so maybe should stick to that to keep language the same and meaningful. "Attendees" maybe for public-facing copy?

    - Same thing with "If there is no room" should be "If there are no spaces"

    - Regarding use of Profile module, it seems like it could be overkill if Registrants are not also users on the site. If I'm not mistaken, Profile module also requires site editors who want to edit fields to be editing the Profile entities, which for our users is a step above their skillset and permissions levels. It is hard to predict what kind of solution woudl work with such limited information about who is using the module for what purposes. It would be amazing to do some kind of survey and get this info. I would be happy to take that on.

    - "Previously when creating or editing a registrant as an event manager you had the option to either put the registrant on the waitlist, or not. I added a new option to handle this automatically depending on current availability. Then the event manager doesn't need to check if there are still enough places available"
    - I think this should be its own issue so that people not following this one will be aware of the change, or at least make sure this is announced very clearly if these features go into a release

    - In gneeral, for me, these changes are not helpful because we would no longer be able to track information per guest. In other words, under the proposed changes, all guests will have the same name and email address as the single "main" Registrant. For our purposes, we require guests to have some different information from the "main" Registrant. For example, some of the guests will receive notifications about the event via their email address. Or some guests will receive notifications in a language different from the main Registrant.

    - Another potential case that neither of our solutions solves but comes up frequently. for us... what about people who want to register a certain number of people exactly -- let's say it's a family event and family of 4 wants to register. There are 2 spots left, so the options for them are:

    1) simply not to register at all -- lame for organizer because they will have no idea what real interest in event is if all groups decide not to go on a waitlist

    2) register 2 spaces out of 4 now and add two more to the waitlist -- pain for the person registering to register three times and also if a spot never opens up, those 2 spaces will be wasted because the family will only go all-or-nothing. if they're nice, they'll cancel at last minute. if not, they will just no-show

    3) ideal but most complicated -- family is able to register 4 spaces and the two available ones are reserved with an asterisk in the system saying the Registrant actually wants 4 spots -- if a spot is emptied and they were first on the list, family's 3rd member is added... if another spot empties, then 4th is added. if not enough new spots empty, then perhaps X amount of time before event, organizer can choose to either add spots for this family or cancel their 2 spots to let next 2 individuals on the waitlist into the event instead... anyway, it quickly gets complex but this is a real situation faced by our client where the choice to register as a group is all-or-nothing. Right now, they don't have an accurate way to guage interest in the events

  • 🇨🇦Canada endless_wander

    Re-reading some of the discussion above from the origins of this issue and it's really the waitlist system that is the hard call here. Another potential and complex scenario:

    - a family event and multiple families of different sizes register to be on the waitlist, assuming we've modified the site to allow the waitlist to accommodate multiple registration spaces
    - Family 1 is first on the waitlist with 5 people in the family. They just missed successfully registering by 1 hour when the last spots were taken, one month before the event.
    - Family 2 registers on the waitlist one week before the event with 3 people
    - Family 3 registers on the waitlist 2 days before the event with 2 people

    Two spots open up at 9am the day before the event (we always see the highest number of cancellations the previous day or same day as an event). Family 3 immediately and automatically gets moved from the waitlist to the registration list to fill up those 2 spots.

    Five minutes later, another family of 3 cancels and so Family 2 moves into those 3 spots.

    No more spots open up so Family 1 never moves off the waitlist, even though technically there were 5 spots that opened up since the day they registered and they've waited the longest.

    What could be a "fair" way to handle this?

  • 🇧🇬Bulgaria pfrenssen Sofia

    I think "Seats" is a strange term to use. Rest of the module uses "Spaces" so maybe should stick to that to keep language the same and meaningful.

    Great suggestion, I will change the terminology.

    Regarding use of Profile module, it seems like it could be overkill if Registrants are not also users on the site.

    Sorry I wasn't clear. I didn't mean to suggest to use the Profile module to solve this, just that this case reminds me of solving the same thing the Profile module does: it has multiple Profiles with personal data per User, while we need multiple Guests (?) with personal data per Registrant.

    That makes me think that probably for us the ideal situation would be to have multiple Registrants and one Registration?

    - "Previously when creating or editing a registrant as an event manager you had the option to either put the registrant on the waitlist, or not. I added a new option to handle this automatically depending on current availability. Then the event manager doesn't need to check if there are still enough places available"
    - I think this should be its own issue so that people not following this one will be aware of the change, or at least make sure this is announced very clearly if these features go into a release

    This is a very interesting case!

    The field is always present in the code but is hidden for everyone except admins with the modify registrant waitlist permission. Previously a simple Yes / No toggle was sufficient: either there is room for 1 single person, or there is no room. In reality though, there is more going on behind the scenes: when the value was (invisible to the normal user) set to "No", some automated logic kicks in to check if there is actually still room at the moment the form is submitted. If space ran out, an error would be shown. So beforehand the actual choice for a normal user and for an event manager was "Yes / Automatic", with the automatic option being the default.

    I needed a way to track the _intention_ of the user creating the registration. An admin might want to force a user on the waitlist, or force them on the active list, or (most often) just want to make the registration automatically depending on whether there is room. Once the registration is made the decision has been made and the option is still a simple Yes / No. The automatic option is just there in the UI, it is never stored in the database. But you're right, this is not ideal and might confuse existing users. I will think about ways to work around this and make it a binary choice again and restore the automatic handling in a way that is invisible to the end user.

    In gneeral, for me, these changes are not helpful because we would no longer be able to track information per guest. In other words, under the proposed changes, all guests will have the same name and email address as the single "main" Registrant. For our purposes, we require guests to have some different information from the "main" Registrant.

    I'm sorry, I did not catch this requirement from the issue summary but I see now that it was implied. I did not mean to disrupt the work but rather to try out a different way to address some problems we encountered.

    I will give some background information about the use case I am targeting in my experimental MR. I am trying to find a way to address the feedback we had from our customer (a museum). They regularly receive large groups such as school classes managed by a teacher, or a bus full of tourists managed by a tour guide. Having individual registrants makes the management of the events tedious and error prone for the museum staff. Some of the feedback we got:

    • It is laborious to manage existing reservations. Example: to process a request to add 15 people to an existing reservation it is needed to manually create 15 registrants linked to the original registrant.
    • The Registrant overview doesn't clearly show which registrants belong together. The list contains pages and pages of identical looking entries. We experimented with filtering on email and event instance but this is still difficult, especially if a single person (like a tour operator) makes multiple registrations for different groups using the same email address. We are missing an effective way to group by "Guest of".
    • Having multiple registrants requires a way to do bulk editing / deleting. We provided some custom bulk editing views, but this feels like a workaround. The customer wants to be able to edit the reservation in a single form, similar to how one is created.
    • There is a risk that group organizers are bombarded with duplicate emails. This can happen when registrants are updated / deleted / promoted, but also when making an innocent change to an event series or instance. For example changing the end time on an event instance can trigger a flood of emails.

    What I am realizing now is that I am actually solving a different use case. My needs are aligned much closer to what is requested in #3090186: Registration quantity widget . Probably the way to go is to move the MR over there and update the issue summaries to make it clear that two approaches are explored in parallel.

    Another potential case that neither of our solutions solves but comes up frequently. for us... what about people who want to register a certain number of people exactly -- let's say it's a family event and family of 4 wants to register. There are 2 spots left...

    This has been discussed in #3090186: Registration quantity widget . I see now that my approach actually closely follows the solution suggested in comment #4 #3090186-4: Registration quantity widget . Another good reason to move the MR over there.

  • 🇧🇬Bulgaria pfrenssen Sofia

    - a family event and multiple families of different sizes register to be on the waitlist, assuming we've modified the site to allow the waitlist to accommodate multiple registration spaces
    - Family 1 is first on the waitlist with 5 people in the family. They just missed successfully registering by 1 hour when the last spots were taken, one month before the event.
    - Family 2 registers on the waitlist one week before the event with 3 people
    - Family 3 registers on the waitlist 2 days before the event with 2 people

    Two spots open up at 9am the day before the event (we always see the highest number of cancellations the previous day or same day as an event). Family 3 immediately and automatically gets moved from the waitlist to the registration list to fill up those 2 spots.

    Five minutes later, another family of 3 cancels and so Family 2 moves into those 3 spots.

    No more spots open up so Family 1 never moves off the waitlist, even though technically there were 5 spots that opened up since the day they registered and they've waited the longest.

    What could be a "fair" way to handle this?

    I was thinking about the same scenario yesterday and I thought the most fair way to handle is to use a first-come-first-served rule. I also implemented it like that in my MR.

    The scenario above would be handled like this:

    1. Two spots open up at 9am the day before the event - Family 1 is first in line but needs 5 spots, so nothing happens.
    2. Five minutes later, another family of 3 cancels - Now there is enough space, so family 1 is promoted to the event list.
    3. Family 2 and 3 did not get a spot because they were further down the list.

    I can imagine though that depending on the project a different approach might be desired. For example an exclusive high-ticket event might want to focus on efficiently filling up available space. Maybe in a followup we can make the waitlist promotion pluggable?

  • 🇨🇦Canada endless_wander

    Maybe I'm not understanding because you also say that a registration cannot be made for more than the number of spaces remaining:

    "If there are not enough spaces left, the user can reserve max. the remaining spaces."

    So if there were only 3 spaces left, a family of 5 could not reserve 5 spaces, only 3?

  • 🇧🇬Bulgaria pfrenssen Sofia

    The waitlisting has been discussed a lot in #3090186: Registration quantity widget . The way I did it aligns with the proposal made in comment #4: #3090186-4: Registration quantity widget .

    I think this is a great solution for a first implementation. It keeps the code very simple (literally 4 lines of code). We can improve this with fancy AJAX in followups.

Production build 0.71.5 2024