Skip to content

Commit b42045b

Browse files
jerioxJulian Baumann
andauthored
guests: change unique constraints, send notification with access link on signup (#1651)
* guests: change unique constraints, send notification with access link on signup * resend notification when signing up again * filter guest participations by event * change notification logic, add translations * fix translations, lint --------- Co-authored-by: Julian Baumann <julian.baumann@sap.com>
1 parent bf84af9 commit b42045b

File tree

6 files changed

+144
-12
lines changed

6 files changed

+144
-12
lines changed

ephios/locale/de/LC_MESSAGES/django.po

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ msgid ""
77
msgstr ""
88
"Project-Id-Version: \n"
99
"Report-Msgid-Bugs-To: \n"
10-
"POT-Creation-Date: 2025-09-04 22:33+0200\n"
10+
"POT-Creation-Date: 2025-09-11 23:54+0200\n"
1111
"PO-Revision-Date: 2025-09-04 22:35+0200\n"
1212
"Last-Translator: Felix Rindt <felix@ephios.de>\n"
1313
"Language-Team: German <https://hosted.weblate.org/projects/ephios/ephios/de/"
@@ -1688,6 +1688,7 @@ msgstr ""
16881688
#: ephios/core/services/notifications/types.py:624
16891689
#: ephios/core/templates/core/mails/new_event.html:35
16901690
#: ephios/core/templates/core/userprofile_workinghours.html:47
1691+
#: ephios/plugins/guests/notifications.py:33
16911692
msgid "View event"
16921693
msgstr "Veranstaltung anzeigen"
16931694

@@ -4468,6 +4469,22 @@ msgstr "Gastteilnehmahme"
44684469
msgid "guest participations"
44694470
msgstr "Gastteilnehmahmen"
44704471

4472+
#: ephios/plugins/guests/notifications.py:12
4473+
msgid "A guest user has signed up"
4474+
msgstr "Ein Gast hat sich angemeldet"
4475+
4476+
#: ephios/plugins/guests/notifications.py:21
4477+
#, python-brace-format
4478+
msgid "You have signed up for {event}"
4479+
msgstr "Sie haben sich für {event} angemeldet."
4480+
4481+
#: ephios/plugins/guests/notifications.py:26
4482+
#, python-brace-format
4483+
msgid ""
4484+
"You have signed up for {event} at {platform}. You can use the link below to "
4485+
"make changes to your participation."
4486+
msgstr "Sie haben sich für {event} bei {platform} angemeldet. Sie können den Link unten benutzen, um Ihre Teilnahme anzupassen."
4487+
44714488
#: ephios/plugins/guests/templates/guests/guestuser_form.html:7
44724489
#: ephios/plugins/guests/templates/guests/guestuser_form.html:16
44734490
msgid "Register as guest"
@@ -4477,19 +4494,21 @@ msgstr "Als Gast registrieren"
44774494
msgid "Continue"
44784495
msgstr "Weiter"
44794496

4480-
#: ephios/plugins/guests/views.py:54
4497+
#: ephios/plugins/guests/views.py:55
44814498
msgid "Log out to register as guest."
44824499
msgstr "Melden Sie sich ab, um sich als Gast zu registrieren."
44834500

4484-
#: ephios/plugins/guests/views.py:78
4485-
msgid "You already registered as a guest for this event."
4486-
msgstr "Sie sind bereits als Gast für diese Veranstaltung registriert."
4501+
#: ephios/plugins/guests/views.py:80
4502+
msgid ""
4503+
"You already registered as a guest for this event. We sent you an email with "
4504+
"a link that you can use to change your participation."
4505+
msgstr "Sie sind bereits als Gast für diese Veranstaltung registriert. Wir haben Ihnen eine E-Mail mit einem Link geschickt, über den Sie Ihre Teilnahme ändern können."
44874506

4488-
#: ephios/plugins/guests/views.py:81
4507+
#: ephios/plugins/guests/views.py:98
44894508
msgid "Save the URL of this page to access this site later."
44904509
msgstr "Speichern Sie die URL dieser Seite, um später zurückzukehren."
44914510

4492-
#: ephios/plugins/guests/views.py:90
4511+
#: ephios/plugins/guests/views.py:107
44934512
msgid "Log out to view the guest version of this page."
44944513
msgstr "Melden Sie sich ab, um die Besucheransicht dieser Seite zu sehen."
44954514

@@ -5082,7 +5101,7 @@ msgstr ""
50825101
msgid "Saved questionnaire answers"
50835102
msgstr "Gespeicherte Antworten"
50845103

5085-
#: ephios/plugins/questionnaires/templates/questionnaires/savedanswer_list.html:29
5104+
#: ephios/plugins/questionnaires/templates/questionnaires/savedanswer_list.html:26
50865105
msgid "not used anymore"
50875106
msgstr "nicht mehr verwendet"
50885107

@@ -5357,6 +5376,9 @@ msgstr "Passwort erfolgreich zurückgesetzt"
53575376
msgid "Please check your mailbox for further instructions."
53585377
msgstr "Bitte prüfen Sie Ihren E-Mail-Posteingang für weitere Anweisungen."
53595378

5379+
#~ msgid "You already registered as a guest for this event."
5380+
#~ msgstr "Sie sind bereits als Gast für diese Veranstaltung registriert."
5381+
53605382
#, python-brace-format
53615383
#~ msgid ""
53625384
#~ "You are already confirmed for the following other shifts: {shifts}. "
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Generated by Django 5.2.6 on 2025-09-11 20:06
2+
3+
from django.db import migrations
4+
from django.db.models import Count
5+
6+
from ephios.core.models.events import PlaceholderParticipation
7+
from ephios.plugins.guests.models import GuestParticipation
8+
9+
10+
def deduplicate_guest_participations(apps, schema_editor):
11+
GuestUser = apps.get_model("guests", "GuestUser")
12+
for duplicate_guest in (
13+
GuestUser.objects.values("email", "event_id").annotate(Count("id")).filter(id__count__gt=1)
14+
):
15+
for participation in GuestParticipation.objects.filter(
16+
guest_user__email=duplicate_guest["email"],
17+
guest_user__event_id=duplicate_guest["event_id"],
18+
):
19+
PlaceholderParticipation.objects.create(
20+
display_name=participation.guest_user.display_name,
21+
shift=participation.shift,
22+
state=participation.state,
23+
structure_data=participation.structure_data,
24+
finished=participation.finished,
25+
individual_start_time=participation.individual_start_time,
26+
individual_end_time=participation.individual_end_time,
27+
)
28+
participation.delete()
29+
GuestUser.objects.filter(
30+
email=duplicate_guest["email"], event_id=duplicate_guest["event_id"]
31+
).delete()
32+
33+
34+
class Migration(migrations.Migration):
35+
36+
dependencies = [
37+
("core", "0038_eventtype_default_description"),
38+
("guests", "0006_alter_guestuser_qualifications"),
39+
]
40+
41+
operations = [
42+
migrations.RunPython(deduplicate_guest_participations),
43+
migrations.AlterUniqueTogether(
44+
name="guestuser",
45+
unique_together={("event", "email")},
46+
),
47+
]

ephios/plugins/guests/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def __str__(self):
7171

7272
class Meta:
7373
# there might be two people using the same email *sigh*
74-
unique_together = [["event", "email", "display_name"]]
74+
unique_together = [["event", "email"]]
7575
verbose_name = _("guest user")
7676
verbose_name_plural = _("guest users")
7777

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from urllib.parse import urljoin
2+
3+
from django.utils.translation import gettext_lazy as _
4+
from dynamic_preferences.registries import global_preferences_registry
5+
6+
from ephios.core.dynamic import dynamic_settings
7+
from ephios.core.models import Notification
8+
from ephios.core.services.notifications.types import AbstractNotificationHandler
9+
10+
11+
class GuestUserSignupNotification(AbstractNotificationHandler):
12+
slug = "guests_signup"
13+
title = _("A guest user has signed up")
14+
unsubscribe_allowed = False
15+
16+
@classmethod
17+
def send(cls, **kwargs):
18+
Notification.objects.create(slug=cls.slug, data=kwargs)
19+
20+
@classmethod
21+
def get_subject(cls, notification):
22+
return _("You have signed up for {event}").format(event=notification.data["event_title"])
23+
24+
@classmethod
25+
def get_body(cls, notification):
26+
return _(
27+
"You have signed up for {event} at {platform}. You can use the link below to make changes to your participation."
28+
).format(
29+
event=notification.data["event_title"],
30+
platform=global_preferences_registry.manager()["general__organization_name"],
31+
)
32+
33+
@classmethod
34+
def get_actions(cls, notification):
35+
return [
36+
(
37+
str(_("View event")),
38+
urljoin(dynamic_settings.SITE_URL, notification.data["event_url"]),
39+
)
40+
]

ephios/plugins/guests/signals.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from django.dispatch import receiver
22

3-
from ephios.core.signals import event_forms, participant_from_request
3+
from ephios.core.signals import event_forms, participant_from_request, register_notification_types
44
from ephios.plugins.guests.forms import EventAllowGuestsForm
55
from ephios.plugins.guests.models import GuestUser
6+
from ephios.plugins.guests.notifications import GuestUserSignupNotification
67

78

89
@receiver(
@@ -23,3 +24,8 @@ def guest_participant_from_request(sender, request, **kwargs):
2324
)
2425
def guests_event_forms(sender, event, request, **kwargs):
2526
return [EventAllowGuestsForm(request.POST or None, event=event, request=request)]
27+
28+
29+
@receiver(register_notification_types, dispatch_uid="guests.signals.guests_notification_types")
30+
def register_guests_notification_types(sender, **kwargs):
31+
return [GuestUserSignupNotification]

ephios/plugins/guests/views.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from ephios.extra.auth import access_exempt
1616
from ephios.extra.widgets import CustomDateInput
1717
from ephios.plugins.guests.models import EventGuestShare, GuestUser
18+
from ephios.plugins.guests.notifications import GuestUserSignupNotification
1819

1920

2021
@access_exempt
@@ -75,11 +76,27 @@ def form_valid(self, form):
7576
# unique_together constraint not passed
7677
form.add_error(
7778
None,
78-
_("You already registered as a guest for this event."),
79+
_(
80+
"You already registered as a guest for this event. We sent you an email with a link that you can use to change your participation."
81+
),
82+
)
83+
guest = GuestUser.objects.get(email=form.cleaned_data["email"], event=self.event)
84+
GuestUserSignupNotification.send(
85+
event_title=self.event.title,
86+
guest_name=guest.display_name,
87+
email=guest.email,
88+
event_url=guest.as_participant().reverse_event_detail(self.event),
7989
)
8090
return self.form_invalid(form)
91+
event_url = guest.as_participant().reverse_event_detail(self.event)
92+
GuestUserSignupNotification.send(
93+
event_title=self.event.title,
94+
guest_name=guest.display_name,
95+
email=guest.email,
96+
event_url=event_url,
97+
)
8198
messages.info(self.request, _("Save the URL of this page to access this site later."))
82-
return redirect(guest.as_participant().reverse_event_detail(self.event))
99+
return redirect(event_url)
83100

84101

85102
class GuestEventDetailView(RedirectAuthenticatedUserMixin, DetailView):

0 commit comments

Comments
 (0)