Repository: svthalia/concrexit

Issue:
V2 events API reports wrong participants number
### Describe the bug
On some event the amount of participants is not reported correctly on V2 version of the API.

### How to reproduce
Steps to reproduce the behaviour:
1. Go to https://thalia.nu/api/v2/events/1005/
2. Go to https://thalia.nu/events/1005/
3. Observe a small difference.

The difference is not present in V1
Counting the pictures of the participants matches up with V1 and not V2

### Expected behaviour
The V2 API should properly report the number of registered members


Discussion:
Given that the serializer seems to directly use this, the property in the model probably needs some adjusting: https://github.com/svthalia/concrexit/blob/465718ec7677b7898c34a73fa266802c5a2db22e/website/events/models/event.py#L258-L263

It should probably just use `Q(eventregistration__date_cancelled=None)` to exclude cancellations
We did some testing with canceling, and when canceling it did decrease the number in v2.
Did you remove the registration? With my register and cancel action I have brought the number in API v2 to 13 now :p

I registered and did not enter anything in the checkbox.
I think this can be a bit flaky based on the python process that is running the request. Let's review this piece of code:

```
participant_count = AggregateProperty(
        Count(
            "eventregistration",
            filter=~Q(eventregistration__date_cancelled__lt=timezone.now()),
        )
    )
```

This is a property in the model file so everything here is executed at the time the server is started and the file is loaded. This means that `timezone.now()` is executed and the value will always be _that_ value after init. 

Resolving patch:
diff --git a/website/events/models/event.py b/website/events/models/event.py
--- a/website/events/models/event.py
+++ b/website/events/models/event.py
@@ -258,7 +258,7 @@ def has_fields(self):
     participant_count = AggregateProperty(
         Count(
             "eventregistration",
-            filter=~Q(eventregistration__date_cancelled__lt=timezone.now()),
+            filter=Q(eventregistration__date_cancelled=None),
         )
     )
 


Test patch:
diff --git a/website/events/tests/test_views.py b/website/events/tests/test_views.py
--- a/website/events/tests/test_views.py
+++ b/website/events/tests/test_views.py
@@ -182,7 +182,7 @@ def setUp(self):
     def test_registration_register_not_required(self):
         response = self.client.post("/events/1/registration/register/", follow=True)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
 
     def test_registration_register(self):
         self.event.registration_start = timezone.now() - datetime.timedelta(hours=1)
@@ -191,7 +191,7 @@ def test_registration_register(self):
         self.event.save()
         response = self.client.post("/events/1/registration/register/", follow=True)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
         self.assertEqual(self.event.eventregistration_set.first().member, self.member)
 
     def test_registration_register_twice(self):
@@ -203,7 +203,7 @@ def test_registration_register_twice(self):
         self.assertEqual(response.status_code, 200)
         response = self.client.post("/events/1/registration/register/", follow=True)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
 
     def test_registration_register_closed(self):
         self.event.registration_start = timezone.now() - datetime.timedelta(hours=2)
@@ -212,7 +212,7 @@ def test_registration_register_closed(self):
         self.event.save()
         response = self.client.post("/events/1/registration/register/", follow=True)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(self.event.participants.count(), 0)
+        self.assertEqual(self.event.participant_count, 0)
 
     def test_registration_cancel(self):
         self.event.registration_start = timezone.now() - datetime.timedelta(hours=1)
@@ -222,7 +222,7 @@ def test_registration_cancel(self):
         EventRegistration.objects.create(event=self.event, member=self.member)
         response = self.client.post("/events/1/registration/cancel/", follow=True)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(self.event.participants.count(), 0)
+        self.assertEqual(self.event.participant_count, 0)
 
     def test_registration_register_no_fields(self):
         self.event.registration_start = timezone.now() - datetime.timedelta(hours=1)
@@ -261,7 +261,7 @@ def test_registration_register_no_fields(self):
         )
         self.assertEqual(response.status_code, 200)
 
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
         registration = self.event.eventregistration_set.first()
         self.assertEqual(field1.get_value_for(registration), None)
         self.assertEqual(field2.get_value_for(registration), None)
@@ -301,7 +301,7 @@ def test_registration_missing_fields(self):
         self.assertEqual(response.status_code, 200)
         template_names = [template.name for template in response.templates]
         self.assertIn("events/registration.html", template_names)
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
 
     def test_registration_register_fields_required(self):
         self.event.registration_start = timezone.now() - datetime.timedelta(hours=1)
@@ -320,7 +320,7 @@ def test_registration_register_fields_required(self):
         self.assertEqual(response.status_code, 200)
         template_names = [template.name for template in response.templates]
         self.assertIn("events/registration.html", template_names)
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
 
     def test_registration_update_form_load_not_changes_fields(self):
         self.event.registration_start = timezone.now() - datetime.timedelta(hours=1)
@@ -428,7 +428,7 @@ def test_registration_update_form_post_changes_fields(self):
         )
         self.assertEqual(response.status_code, 200)
 
-        self.assertEqual(self.event.participants.count(), 1)
+        self.assertEqual(self.event.participant_count, 1)
         registration = self.event.eventregistration_set.first()
         self.assertEqual(field1.get_value_for(registration), False)
         self.assertEqual(field2.get_value_for(registration), 1337)
@@ -443,7 +443,7 @@ def test_registration_cancel_after_deadline_notification(self):
         EventRegistration.objects.create(event=self.event, member=self.member)
         response = self.client.post("/events/1/registration/cancel/", follow=True)
         self.assertEqual(response.status_code, 200)
-        self.assertEqual(self.event.participants.count(), 0)
+        self.assertEqual(self.event.participant_count, 0)
         self.assertEqual(len(mail.outbox), 1)
         self.assertEqual(
             mail.outbox[0].to,