Skip to content

Commit be1c3ee

Browse files
authored
Merge pull request #3565 from webkom/ivarnakken/aba-855-add-filter-for-users-in-a-specific-pool-to-announcements
Extend announcement to support more filtering event
2 parents 79ad51b + e414577 commit be1c3ee

File tree

11 files changed

+195
-15
lines changed

11 files changed

+195
-15
lines changed

lego/apps/events/fixtures/test_events.yaml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@
198198
created_by: 1
199199
require_auth: False
200200
responsible_group: 25
201-
201+
202202
- model: events.Pool
203203
pk: 1
204204
fields:
@@ -287,9 +287,9 @@
287287
pk: 9
288288
fields:
289289
name: Abakusmember
290-
capacity: 1
290+
capacity: 1
291291
event: 13
292-
counter: 1
292+
counter: 1
293293
activation_date: "2019-09-01T13:20:30+03:00"
294294
permission_groups:
295295
- - Abakus
@@ -361,3 +361,12 @@
361361
pool: 9
362362
registration_date: "2011-09-01T13:20:30+03:00"
363363
status: "SUCCESS_REGISTER"
364+
365+
- model: events.Registration
366+
pk: 8
367+
fields:
368+
user: 10
369+
event: 1
370+
pool: null
371+
registration_date: "2011-09-01T13:20:30+03:00"
372+
status: "SUCCESS_REGISTER"

lego/apps/events/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,10 +776,14 @@ def restricted_lookup(self) -> tuple[list[User], list]:
776776
)
777777
return [registration.user for registration in registrations], []
778778

779-
def announcement_lookup(self) -> list[User]:
779+
def announcement_lookup(self, exclude_waiting_list: bool) -> list[User]:
780780
registrations: QuerySet[Registration] = self.registrations.filter(
781781
status=constants.SUCCESS_REGISTER
782782
)
783+
784+
if exclude_waiting_list:
785+
registrations = registrations.exclude(pool=None)
786+
783787
return [registration.user for registration in registrations]
784788

785789
def add_legacy_registration(self) -> None:

lego/apps/events/tests/test_registrations.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,13 +413,13 @@ def test_register_to_waiting_list_after_unregister(self):
413413

414414
registration = Registration.objects.get_or_create(event=event, user=user)[0]
415415
event.register(registration)
416-
self.assertEqual(event.waiting_registrations.count(), 1)
416+
self.assertEqual(event.waiting_registrations.count(), 2)
417417

418418
event.unregister(registration)
419-
self.assertEqual(event.waiting_registrations.count(), 0)
419+
self.assertEqual(event.waiting_registrations.count(), 1)
420420

421421
event.register(registration)
422-
self.assertEqual(event.waiting_registrations.count(), 1)
422+
self.assertEqual(event.waiting_registrations.count(), 2)
423423

424424
def test_unregistering_non_existing_user(self):
425425
"""Test that non existing user trying to unregister raises error"""

lego/apps/meetings/fixtures/test_meetings.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,26 @@
2727
end_time: "2011-02-01T23:59:00+00:00"
2828
report: "tomp"
2929
report_author: 3
30+
31+
- model: meetings.Meeting
32+
pk: 4
33+
fields:
34+
title: Enda et tomt møte
35+
location: "null"
36+
start_time: "2024-02-01T17:15:00+00:00"
37+
end_time: "2024-02-01T23:59:00+00:00"
38+
report: "hei"
39+
report_author: 3
40+
41+
- model: meetings.MeetingInvitation
42+
pk: 1
43+
fields:
44+
user: 8
45+
meeting: 4
46+
status: "ATTENDING"
47+
48+
- model: meetings.MeetingInvitation
49+
pk: 2
50+
fields:
51+
user: 9
52+
meeting: 4

lego/apps/meetings/models.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,17 @@ def restricted_lookup(self):
105105
"""
106106
return self.invited_users, []
107107

108-
def announcement_lookup(self):
109-
return self.invited_users
108+
def announcement_lookup(self, meeting_invitation_status) -> list[User]:
109+
meeting_invitations = self.invitations
110+
111+
if meeting_invitation_status:
112+
meeting_invitations = meeting_invitations.filter(
113+
status=meeting_invitation_status
114+
)
115+
116+
return User.objects.filter(
117+
id__in=meeting_invitations.values_list("user", flat=True)
118+
)
110119

111120
@property
112121
def content_target(self):

lego/apps/notifications/fixtures/test_announcements.yaml

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
pk: 1
33
fields:
44
message: abakom
5-
sent: '2019-02-10T14:38:49.164657Z'
5+
sent: "2019-02-10T14:38:49.164657Z"
66
groups: [3]
77
created_by: 4
88

@@ -11,15 +11,15 @@
1111
fields:
1212
message: event_from_arrkom
1313
from_group: 4
14-
sent: '2019-02-10T14:38:49.164657Z'
14+
sent: "2019-02-10T14:38:49.164657Z"
1515
events: [1]
1616
created_by: 4
1717

1818
- model: notifications.Announcement
1919
pk: 3
2020
fields:
2121
message: event_abakom
22-
sent: '2019-02-10T14:38:49.164657Z'
22+
sent: "2019-02-10T14:38:49.164657Z"
2323
groups: [3]
2424
events: [1]
2525
created_by: 4
@@ -29,7 +29,7 @@
2929
fields:
3030
message: user_from_webkom
3131
from_group: 12
32-
users: [1, 2,3]
32+
users: [1, 2, 3]
3333
created_by: 4
3434

3535
- model: notifications.Announcement
@@ -46,3 +46,34 @@
4646
message: test_from_user_webkom
4747
groups: [1]
4848
created_by: 3
49+
50+
- model: notifications.Announcement
51+
pk: 7
52+
fields:
53+
message: another_event_from_arrkom
54+
events: [1]
55+
exclude_waiting_list: false
56+
created_by: 9
57+
58+
- model: notifications.Announcement
59+
pk: 8
60+
fields:
61+
message: yet_another_event_from_arrkom
62+
events: [1]
63+
exclude_waiting_list: true
64+
created_by: 9
65+
66+
- model: notifications.Announcement
67+
pk: 9
68+
fields:
69+
message: meeting
70+
meetings: [4]
71+
created_by: 1
72+
73+
- model: notifications.Announcement
74+
pk: 10
75+
fields:
76+
message: meeting
77+
meetings: [4]
78+
meeting_invitation_status: "ATTENDING"
79+
created_by: 1
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Generated by Django 4.0.10 on 2024-03-07 14:51
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("notifications", "0014_alter_notificationsetting_notification_type"),
9+
]
10+
11+
operations = [
12+
migrations.AddField(
13+
model_name="announcement",
14+
name="exclude_waiting_list",
15+
field=models.BooleanField(default=False),
16+
),
17+
migrations.AddField(
18+
model_name="announcement",
19+
name="meeting_invitation_status",
20+
field=models.CharField(
21+
blank=True,
22+
choices=[
23+
("NO_ANSWER", "NO_ANSWER"),
24+
("ATTENDING", "ATTENDING"),
25+
("NOT_ATTENDING", "NOT_ATTENDING"),
26+
],
27+
max_length=50,
28+
),
29+
),
30+
]

lego/apps/notifications/models.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.utils import timezone
44

55
from lego.apps.action_handlers.events import handle_event
6+
from lego.apps.meetings import constants
67
from lego.utils.models import BasisModel
78

89
from .constants import (
@@ -76,12 +77,16 @@ class Announcement(BasisModel):
7677
message = models.TextField()
7778
sent = models.DateTimeField(null=True, default=None)
7879

79-
MANY_TO_MANY_RELATIONS = ["users", "groups", "events", "meetings"]
80+
MANY_TO_MANY_RELATIONS = ["users", "groups"]
8081

8182
users = models.ManyToManyField("users.User", blank=True)
8283
groups = models.ManyToManyField("users.AbakusGroup", blank=True)
8384
events = models.ManyToManyField("events.Event", blank=True)
85+
exclude_waiting_list = models.BooleanField(default=False)
8486
meetings = models.ManyToManyField("meetings.Meeting", blank=True)
87+
meeting_invitation_status = models.CharField(
88+
max_length=50, choices=constants.INVITATION_STATUS_TYPES, blank=True
89+
)
8590
from_group = models.ForeignKey(
8691
"users.AbakusGroup",
8792
on_delete=models.PROTECT,
@@ -104,6 +109,12 @@ def lookup_recipients(self):
104109
users = announcement_lookup()
105110
all_users += list(users)
106111

112+
for event in self.events.all():
113+
all_users += event.announcement_lookup(self.exclude_waiting_list)
114+
115+
for meeting in self.meetings.all():
116+
all_users += meeting.announcement_lookup(self.meeting_invitation_status)
117+
107118
return list(set(all_users))
108119

109120
def send(self):

lego/apps/notifications/serializers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ class Meta:
4343
"users",
4444
"groups",
4545
"events",
46+
"exclude_waiting_list",
4647
"meetings",
48+
"meeting_invitation_status",
4749
)
4850
read_only_fields = ("sent",)
4951

@@ -59,6 +61,8 @@ class Meta(AnnouncementListSerializer.Meta):
5961
"users",
6062
"groups",
6163
"events",
64+
"exclude_waiting_list",
6265
"meetings",
66+
"meeting_invitation_status",
6367
)
6468
read_only_fields = ("sent",)

lego/apps/notifications/tests/test_views.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class AnnouncementViewSetTestCase(BaseAPITestCase):
8181
"test_events.yaml",
8282
"test_companies.yaml",
8383
"test_announcements.yaml",
84+
"test_meetings.yaml",
8485
]
8586

8687
def setUp(self):
@@ -238,3 +239,59 @@ def test_send_announcement_unauthorized(self):
238239
self.client.force_authenticate(self.unauthorized_user)
239240
response = self.client.post(f"{self.url}{self.unsent_announcement.id}/send/")
240241
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
242+
243+
def test_send_announcement_twice(self):
244+
"""
245+
An announcement can not be sent twice
246+
"""
247+
248+
self.client.force_authenticate(self.authorized_user)
249+
response = self.client.post(f"{self.url}{self.unsent_announcement.id}/send/")
250+
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
251+
response = self.client.post(f"{self.url}{self.unsent_announcement.id}/send/")
252+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
253+
254+
def test_recipients_lookup_to_users(self):
255+
"""
256+
An announcement should be sent to the specified users
257+
"""
258+
259+
announcement = Announcement.objects.get(pk=4)
260+
recipients = announcement.lookup_recipients()
261+
self.assertEqual(len(recipients), 3)
262+
263+
def test_recipients_lookup_for_event(self):
264+
"""
265+
Everyone registered to an event should receive the announcement
266+
"""
267+
announcement = Announcement.objects.get(pk=7)
268+
recipients = announcement.lookup_recipients()
269+
self.assertEqual(len(recipients), 3)
270+
271+
def test_recipients_lookup_for_event_exclude_waiting_list(self):
272+
"""
273+
Everyone registered to an event, except those on waiting list,
274+
should receive the announcement
275+
"""
276+
277+
announcement = Announcement.objects.get(pk=8)
278+
recipients = announcement.lookup_recipients()
279+
self.assertEqual(len(recipients), 2)
280+
281+
def test_recipients_lookup_for_meeting(self):
282+
"""
283+
Everyone invited to a meeting should receive the announcement
284+
"""
285+
286+
announcement = Announcement.objects.get(pk=9)
287+
recipients = announcement.lookup_recipients()
288+
self.assertEqual(len(recipients), 2)
289+
290+
def test_recipients_lookup_for_only_meeting_attendees(self):
291+
"""
292+
Only those invited to a meeting and accepted should receive the announcement
293+
"""
294+
295+
announcement = Announcement.objects.get(pk=10)
296+
recipients = announcement.lookup_recipients()
297+
self.assertEqual(len(recipients), 1)

0 commit comments

Comments
 (0)