diff --git a/funnel/forms/sync_ticket.py b/funnel/forms/sync_ticket.py index fae507f95..1682820a5 100644 --- a/funnel/forms/sync_ticket.py +++ b/funnel/forms/sync_ticket.py @@ -175,8 +175,8 @@ class TicketParticipantForm(forms.Form): ) email = forms.EmailField( __("Email"), - validators=[forms.validators.DataRequired(), forms.validators.ValidEmail()], - filters=[forms.filters.strip()], + validators=[forms.validators.Optional(), forms.validators.ValidEmail()], + filters=[forms.filters.none_if_empty()], ) phone = forms.StringField( __("Phone number"), @@ -219,6 +219,9 @@ def set_queries(self) -> None: def validate(self, *args, **kwargs) -> bool: """Validate form.""" result = super().validate(*args, **kwargs) + if self.email.data is None: + self.user = None + return True with db.session.no_autoflush: accountemail = AccountEmail.get(email=self.email.data) if accountemail is not None: diff --git a/funnel/models/sync_ticket.py b/funnel/models/sync_ticket.py index d51940425..29f99708d 100644 --- a/funnel/models/sync_ticket.py +++ b/funnel/models/sync_ticket.py @@ -207,7 +207,7 @@ class TicketParticipant(EmailAddressMixin, UuidMixin, BaseMixin, Model): """A participant in one or more events, synced from an external ticket source.""" __tablename__ = 'ticket_participant' - __email_optional__ = False + __email_optional__ = True __email_for__ = 'participant' fullname = with_roles( @@ -376,7 +376,9 @@ def checkin_list(cls, ticket_event: TicketEvent) -> list: # TODO: List type? TicketEventParticipant, TicketParticipant.id == TicketEventParticipant.ticket_participant_id, ) - .join(EmailAddress, EmailAddress.id == TicketParticipant.email_address_id) + .outerjoin( + EmailAddress, EmailAddress.id == TicketParticipant.email_address_id + ) .outerjoin( SyncTicket, TicketParticipant.id == SyncTicket.ticket_participant_id ) diff --git a/funnel/views/ticket_participant.py b/funnel/views/ticket_participant.py index 126d300b6..d788a22b3 100644 --- a/funnel/views/ticket_participant.py +++ b/funnel/views/ticket_participant.py @@ -96,7 +96,9 @@ def ticket_participant_checkin_data(ticket_participant, project, ticket_event): 'puuid_b58': puuid_b58, 'fullname': ticket_participant.fullname, 'company': ticket_participant.company, - 'email': mask_email(ticket_participant.email), + 'email': mask_email(ticket_participant.email) + if ticket_participant.email + else None, 'badge_printed': ticket_participant.badge_printed, 'checked_in': ticket_participant.checked_in, 'ticket_type_titles': ticket_participant.ticket_type_titles, diff --git a/migrations/versions/017c60414c03_make_ticket_participant_email_optional.py b/migrations/versions/017c60414c03_make_ticket_participant_email_optional.py new file mode 100644 index 000000000..e10c3250b --- /dev/null +++ b/migrations/versions/017c60414c03_make_ticket_participant_email_optional.py @@ -0,0 +1,44 @@ +"""Make ticket participant email optional. + +Revision ID: 017c60414c03 +Revises: 4f9ca10b7b9d +Create Date: 2023-10-05 15:08:34.540672 + +""" + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = '017c60414c03' +down_revision: str = '4f9ca10b7b9d' +branch_labels: str | tuple[str, ...] | None = None +depends_on: str | tuple[str, ...] | None = None + + +def upgrade(engine_name: str = '') -> None: + """Upgrade all databases.""" + # Do not modify. Edit `upgrade_` instead + globals().get(f'upgrade_{engine_name}', lambda: None)() + + +def downgrade(engine_name: str = '') -> None: + """Downgrade all databases.""" + # Do not modify. Edit `downgrade_` instead + globals().get(f'downgrade_{engine_name}', lambda: None)() + + +def upgrade_() -> None: + """Upgrade default database.""" + with op.batch_alter_table('ticket_participant', schema=None) as batch_op: + batch_op.alter_column( + 'email_address_id', existing_type=sa.INTEGER(), nullable=True + ) + + +def downgrade_() -> None: + """Downgrade default database.""" + with op.batch_alter_table('ticket_participant', schema=None) as batch_op: + batch_op.alter_column( + 'email_address_id', existing_type=sa.INTEGER(), nullable=False + )